[image]

Программирование

 
RU 140466(ака Нумер) #29.09.2004 01:42
+
-
edit
 
Вообще обучение программированию на славной каферде СМ-6, которую, видимо в руководстве МВТУ считают вторым, а то и третьим сортом (и это при том, что тов.Зеленцов - у нас как Янус Полуэктович, един в 2 лицах - и зав.каф. и декан!) - вопрос особый. Конечно, многого и не обещали, но вообще практически ничему не учить!
Но тут дело касается конкретного случая. Нужно создать програмку-калькулятор для 4 действий. На Паскале. Всё, вроде просто и прозрачно за исключением того, что не ясно, как заставить комп отличать + от минуса. Пока я задаю переменные, как real всё нормально, но ведь действия - это не числа! Куда их деть? Как обозвать переменные? Обозначить, как булевские? Тоже, вроде, не верно. А как иначе? Нам ничего по этому поводу не говорили. А учебника на руках нет. Да и вряд ли в нём что-то нужное есть.
   
RU Кирилл #29.09.2004 07:31
+
-
edit
 

Кирилл

втянувшийся

Для этого есть тип char :)
   
RU BrAB #29.09.2004 09:31  @140466(ака Нумер)#29.09.2004 01:42
+
-
edit
 

BrAB

аксакал
★★
1.Н.>Но тут дело касается конкретного случая. Нужно создать програмку-калькулятор для 4 действий. На Паскале. Всё, вроде просто и прозрачно за исключением того, что не ясно, как заставить комп отличать + от минуса. Пока я задаю переменные, как real всё нормально, но ведь действия - это не числа! Куда их деть? Как обозвать переменные? Обозначить, как булевские? Тоже, вроде, не верно. А как иначе? Нам ничего по этому поводу не говорили. А учебника на руках нет. Да и вряд ли в нём что-то нужное есть.[»]

Вау! узнаю свой первый курс. :)

Воощем, тупо это делается так:
1) вводишь первый операнд как реал
2) вводишь строку
3) сравнивашь строку с + - / *
4) если совпадает с чем -то, то
5) вводишь второй операнд
6) выполняешь действие (проше всего так: case s of .......)
7)иначе грязно ругаешся на неверный символ операции
   
Не понял? То есть сначала вводим x, потом просим ввести символ действия и сравниваем его с ±*? Но ведь нужно как-то обозначить переменные! Я подумал - ещё придумал извращённый вариант, вывести строку, говорящую о том, что символом плюса будет единица, минуса - двойка и т.д. Т.е. избавился от плюсов и заменил их цифрами. Но это, конечно извращённый вариант.

Насчёт "char" -спасибо, попробую. Собственно единственная пролема - обозначением действий. Во всяком случае других проблем я пока не заметил.
 
RU Centuriones #29.09.2004 12:11
+
-
edit
 

Centuriones

опытный

Вот пример из поставки ТР 7.0 для ДОС.
code text
  1. {************************************************}
  2. {                                                }
  3. {   Turbo Vision Demo                            }
  4. {   Copyright (c) 1990 by Borland International  }
  5. {                                                }
  6. {************************************************}
  7.  
  8. unit Calc;
  9.  
  10. {$F+,O+,S-}
  11.  
  12. { Calculator object. See TVDEMO.PAS for an example
  13.   program that uses this unit.
  14. }
  15.  
  16. interface
  17.  
  18. uses Drivers, Objects, Views, Dialogs;
  19.  
  20. type
  21.  
  22.   TCalcState = (csFirst, csValid, csError);
  23.  
  24.   PCalcDisplay = ^TCalcDisplay;
  25.   TCalcDisplay = object(TView)
  26.     Status: TCalcState;
  27.     Number: string[15];
  28.     Sign: Char;
  29.     Operator: Char;
  30.     Operand: Real;
  31.     constructor Init(var Bounds: TRect);
  32.     constructor Load(var S: TStream);
  33.     procedure CalcKey(Key: Char);
  34.     procedure Clear;
  35.     procedure Draw; virtual;
  36.     function GetPalette: PPalette; virtual;
  37.     procedure HandleEvent(var Event: TEvent); virtual;
  38.     procedure Store(var S: TStream);
  39.   end;
  40.  
  41.   PCalculator = ^TCalculator;
  42.   TCalculator = object(TDialog)
  43.     constructor Init;
  44.   end;
  45.  
  46. const
  47.   RCalcDisplay: TStreamRec = (
  48.      ObjType: 10040;
  49.      VmtLink: Ofs(TypeOf(TCalcDisplay)^);
  50.      Load:    @TCalcDisplay.Load;
  51.      Store:   @TCalcDisplay.Store
  52.   );
  53.   RCalculator: TStreamRec = (
  54.      ObjType: 10041;
  55.      VmtLink: Ofs(TypeOf(TCalculator)^);
  56.      Load:    @TCalculator.Load;
  57.      Store:   @TCalculator.Store
  58.   );
  59.  
  60. procedure RegisterCalc;
  61.  
  62. implementation
  63.  
  64. const
  65.   cmCalcButton = 100;
  66.  
  67. constructor TCalcDisplay.Init(var Bounds: TRect);
  68. begin
  69.   inherited Init(Bounds);
  70.   Options := Options or ofSelectable;
  71.   EventMask := evKeyDown + evBroadcast;
  72.   Clear;
  73. end;
  74.  
  75. constructor TCalcDisplay.Load(var S: TStream);
  76. begin
  77.   inherited Load(S);
  78.   S.Read(Status, SizeOf(Status) + SizeOf(Number) + SizeOf(Sign) +
  79.     SizeOf(Operator) + SizeOf(Operand));
  80. end;
  81.  
  82. procedure TCalcDisplay.CalcKey(Key: Char);
  83. var
  84.   R: Real;
  85.  
  86. procedure Error;
  87. begin
  88.   Status := csError;
  89.   Number := 'Error';
  90.   Sign := ' ';
  91. end;
  92.  
  93. procedure SetDisplay(R: Real);
  94. var
  95.   S: string[63];
  96. begin
  97.   Str(R: 0: 10, S);
  98.   if S[1] <> '-' then Sign := ' ' else
  99.   begin
  100.     Delete(S, 1, 1);
  101.     Sign := '-';
  102.   end;
  103.   if Length(S) > 15 + 1 + 10 then Error
  104.   else
  105.   begin
  106.     while S[Length(S)] = '0' do Dec(S[0]);
  107.     if S[Length(S)] = '.' then Dec(S[0]);
  108.     Number := S;
  109.   end;
  110. end;
  111.  
  112. procedure GetDisplay(var R: Real);
  113. var
  114.   E: Integer;
  115. begin
  116.   Val(Sign + Number, R, E);
  117. end;
  118.  
  119. procedure CheckFirst;
  120. begin
  121.   if Status = csFirst then
  122.   begin
  123.     Status := csValid;
  124.     Number := '0';
  125.     Sign := ' ';
  126.   end;
  127. end;
  128.  
  129. begin
  130.   Key := UpCase(Key);
  131.   if (Status = csError) and (Key <> 'C') then Key := ' ';
  132.   case Key of
  133.     '0'..'9':
  134.       begin
  135.         CheckFirst;
  136.         if Number = '0' then Number := '';
  137.         Number := Number + Key;
  138.       end;
  139.     '.':
  140.       begin
  141.         CheckFirst;
  142.         if Pos('.', Number) = 0 then Number := Number + '.';
  143.       end;
  144.     #8, #27:
  145.       begin
  146.         CheckFirst;
  147.         if Length(Number) = 1 then Number := '0' else Dec(Number[0]);
  148.       end;
  149.     '_', #241:
  150.       if Sign = ' ' then Sign := '-' else Sign := ' ';
  151.     '+', '-', '*', '/', '=', '%', #13:
  152.       begin
  153.         if Status = csValid then
  154.         begin
  155.           Status := csFirst;
  156.           GetDisplay(R);
  157.           if Key = '%' then
  158.             case Operator of
  159.               '+', '-': R := Operand * R / 100;
  160.               '*', '/': R := R / 100;
  161.             end;
  162.           case Operator of
  163.             '+': SetDisplay(Operand + R);
  164.             '-': SetDisplay(Operand - R);
  165.             '*': SetDisplay(Operand * R);
  166.             '/': if R = 0 then Error else SetDisplay(Operand / R);
  167.           end;
  168.         end;
  169.         Operator := Key;
  170.         GetDisplay(Operand);
  171.       end;
  172.     'C':
  173.       Clear;
  174.   end;
  175.   DrawView;
  176. end;
  177.  
  178. procedure TCalcDisplay.Clear;
  179. begin
  180.   Status := csFirst;
  181.   Number := '0';
  182.   Sign := ' ';
  183.   Operator := '=';
  184. end;
  185.  
  186. procedure TCalcDisplay.Draw;
  187. var
  188.   Color: Byte;
  189.   I: Integer;
  190.   B: TDrawBuffer;
  191. begin
  192.   Color := GetColor(1);
  193.   I := Size.X - Length(Number) - 2;
  194.   MoveChar(B, ' ', Color, Size.X);
  195.   MoveChar(B[I], Sign, Color, 1);
  196.   MoveStr(B[I + 1], Number, Color);
  197.   WriteBuf(0, 0, Size.X, 1, B);
  198. end;
  199.  
  200. function TCalcDisplay.GetPalette: PPalette;
  201. const
  202.   P: string[1] = #19;
  203. begin
  204.   GetPalette := @P;
  205. end;
  206.  
  207. procedure TCalcDisplay.HandleEvent(var Event: TEvent);
  208. begin
  209.   inherited HandleEvent(Event);
  210.   case Event.What of
  211.     evKeyDown:
  212.       begin
  213.         CalcKey(Event.CharCode);
  214.         ClearEvent(Event);
  215.       end;
  216.     evBroadcast:
  217.       if Event.Command = cmCalcButton then
  218.       begin
  219.         CalcKey(PButton(Event.InfoPtr)^.Title^[1]);
  220.         ClearEvent(Event);
  221.       end;
  222.   end;
  223. end;
  224.  
  225. procedure TCalcDisplay.Store(var S: TStream);
  226. begin
  227.   TView.Store(S);
  228.   S.Write(Status, SizeOf(Status) + SizeOf(Number) + SizeOf(Sign) +
  229.     SizeOf(Operator) + SizeOf(Operand));
  230. end;
  231.  
  232. { TCalculator }
  233.  
  234. constructor TCalculator.Init;
  235. const
  236.   KeyChar: array[0..19] of Char = 'C'#27'%'#241'789/456*123-0.=+';
  237. var
  238.   I: Integer;
  239.   P: PView;
  240.   R: TRect;
  241. begin
  242.   R.Assign(5, 3, 29, 18);
  243.   inherited Init(R, 'Calculator');
  244.   Options := Options or ofFirstClick;
  245.   for I := 0 to 19 do
  246.   begin
  247.     R.A.X := (I mod 4) * 5 + 2;
  248.     R.A.Y := (I div 4) * 2 + 4;
  249.     R.B.X := R.A.X + 5;
  250.     R.B.Y := R.A.Y + 2;
  251.     P := New(PButton, Init(R, KeyChar[I], cmCalcButton,
  252.       bfNormal + bfBroadcast));
  253.     P^.Options := P^.Options and not ofSelectable;
  254.     Insert(P);
  255.   end;
  256.   R.Assign(3, 2, 21, 3);
  257.   Insert(New(PCalcDisplay, Init(R)));
  258. end;
  259.  
  260. procedure RegisterCalc;
  261. begin
  262.   RegisterType(RCalcDisplay);
  263.   RegisterType(RCalculator);
  264. end;
  265.  
  266. end.

(Если надо, могу и весь дистрибутив переслать, весит он немного).
   
+
-
edit
 
Guest>Не понял? То есть сначала вводим x, потом просим ввести символ действия и сравниваем его с ±*? Но ведь нужно как-то обозначить переменные! Я подумал - ещё придумал извращённый вариант, вывести строку, говорящую о том, что символом плюса будет единица, минуса - двойка и т.д. Т.е. избавился от плюсов и заменил их цифрами. Но это, конечно извращённый вариант.
ну я ж написал про стринг. выглядеть будет так
var a,b:real;s:string;

.................
readln(a);
readln(s);
readln(b);

дальше ставишь case на s и всё

 

hsm

опытный

Пример калькулятора есть в Страуструпе, 2-м издании :).
но если все ограничено четыремя действиями (нет скобок, функций и пр.) и двумя операндами то можно проще. :)
Пример на С для целых чисел:

int a;
int b;
int rez;
char ops;

while( 1 ){ // бесконечный цикл, выход по Ctrl-C
scanf("%d %c %d", &a, &ops, &b);
switch( ops ){
case '+':
rez=a+b;
breake;
case '-':
.... ну тут дальше должно быть все понятно
default :
exit(0);
}
printf("=%d\n", rez);
}

PS
Надо быть большими чудаками, чтоб Паскаль учить, ну если тоьлко в образовательных целях... B)
   

hsm

опытный

О! Пример работы моего калькулятора:

1+2
=3
5 + 10
=15
^C

Обрати внимание - пробелы сами собой обработались. Но это может быть по разному на разных системах.
   
+
-
edit
 

Balancer

администратор
★★★★★
Guest>Не понял? То есть сначала вводим x, потом просим ввести символ действия и сравниваем его с ±*?

Берём всё выражение, строкой, разбиваем его на токены (числа, знаки операций, функции), переводим в обратную польскую запись и испольняем по порядку. Разницы между 4-мя действиями и полноценным калькулятором нет никакой, на всё программирование - пол-часа, из них 3/4 времени - написание парсера выражений :)

Помню, я как-то по этой теме у нас в институте семинар провёл. Преподавателю показалось, что я "слишком много знаю" и он предложил провести мне семинар вместо него. К его удивлению я семинар мало того, что провёл, но и в одно занятие группа разобралась со всем, что планировалось на 4 занятия :D В итоге он мне поставил зачёт и больше я на этих занятиях не был :D
   
+
-
edit
 

Balancer

администратор
★★★★★
Вот, ловите мой калькулятор, который я писал для тестирования класса ассоциативных массивов в C++ 11 лет назад :) За многое там сейчас, вроде бы, стыдно, но, дык, 11 лет назад :)

А так - пощупайте exe-шник калькулятора, довести до ума (запоминание выражений и т.п.) - полезная программа получится :)
Прикреплённые файлы:
 
   
+
-
edit
 

Balancer

администратор
★★★★★
Если кому качать лень, то вот основные элементы:
Так добавляются новые функции&nbsp[показать]


Лексическая разборка.&nbsp[показать]


Собственно вычисления. Несколько перегружено и коряво, но я тогда за чистотой кода не гонялся&nbsp[показать]



Основной цикл&nbsp[показать]

   

hsm

опытный

А вот полный листинг для 4-х действий и двух операндов.
code cpp
  1. #include <stdio.h>
  2.  
  3. int main(){
  4.     int a,b,rez;
  5.     char ops;
  6.    
  7.     while( 1 ){
  8.         scanf("%d %c %d",&a,&ops,&b);
  9.         switch( ops ){
  10.             case '+':
  11.                 rez=a+b;
  12.                 break;
  13.             case '-':
  14.                 rez=a-b;
  15.                 break;
  16.             case '*':
  17.                 rez=a*b;
  18.                 break;
  19.             case '/':
  20.                 rez=a/b;
  21.                 break;
  22.             default:
  23.                 return 0;
  24.                 break;
  25.             }
  26.         printf("=%d\n",rez);
  27.         }
  28.     return 0;
  29. }


Почуствуйте разницу! ;)
минуты две - три на все про все.

Балансер, Нумер спрашивал как ему заставить комп плюс от минуса отличить а ты ему в ответ: "Парсер, токены, обратная польская ..". Это конечно здорово, но чтоб понастоящему прочуствовать что и как происходит в компе (если нужно, конечно :) ) лучше начинать с вещей базовых и примитивных как-то: основные типы и указатели.

ЗЫ
Как говориться "Упс!". Движок форума всю разметку "съел".
   
Это сообщение редактировалось 29.09.2004 в 14:45

Balancer

администратор
★★★★★
hsm>Балансер, Нумер спрашивал как ему заставить комп плюс от минуса отличить а ты ему в ответ: "Парсер, токены, обратная польская ..".

Без обратной польской всё равно не поймёшь, что там творится :)
Процессор-то считает именно так.
И любой транслятор переводит формулы в бесскобочную запись :)

hsm>Как говориться "Упс!". Движок форума всю разметку "съел".[»]

Используй тэги [ code cpp ] ... [ /code ] (без пробелов внутри тэга, естествненно).

Подправил твой листинг :)
   
+
-
edit
 

Balancer

администратор
★★★★★
hsm>лучше начинать с вещей базовых и примитивных как-то

Кстати, тогда ты совершенно зря используешь scanf или printf - они напрочь собьют с толку :) да и switch в C++ тоже не очень прозрачен :)
   

hsm

опытный

hsm>>лучше начинать с вещей базовых и примитивных как-то
Balancer>Кстати, тогда ты совершенно зря используешь scanf или printf - они напрочь собьют с толку :) да и switch в C++ тоже не очень прозрачен :)[»]

Функциональность printf и scanf "интуитивно понятна" :) , особенно если принимать их "как есть" и не вдаваться в детали.(В данном случае scanf реализует функции ввода и парсера, а printf - просто printf :) ) Да и switch - куда-уж прозрачнее?
Зато потом будет легко и просто понимать что такое парсер (и прочие малопонятные словечки), что и каким, примерно, образом он делает. Видеть "железную" суть за словесными словообразованиями. :)

А все остальное можно узнать и чуть позже. Кстати, помниться, обратная польская запись использовалась в программируемых калькуляторах. Ее приходилось изучать до знакомства с компьютером. (Это середина-конец восьмедисятых, прошлого века :) )

ЗЫ
Спасибо за правку!
   
+
-
edit
 

Balancer

администратор
★★★★★
hsm>Функциональность printf и scanf "интуитивно понятна" :)

Здрасьте! printf - это маски, печатаемые типы и т.п. scanf - это, вообще, указатели, буфера, возможность переполнения :)

>Да и switch - куда-уж прозрачнее?

Угу, и break; после каждого case: :)

hsm>А все остальное можно узнать и чуть позже. Кстати, помниться, обратная польская запись использовалась в программируемых калькуляторах. Ее приходилось изучать до знакомства с компьютером. (Это середина-конец восьмедисятых, прошлого века :) )

Хы. Повторюсь, вся сегодняшняя арифметика транслируется в постфиксную нотацию перед исполнением или комипляцией :D

Да и Форт, даже сегодня, отнюдь не умер, хотя у него нет былой популярности :)
   
Да я вообще ничего не понял из того, что вы все понмписали. :) Я же сказал, что программировать не умею. К тому же тут явно не тот Паскаль, что у нас. У нас Борланд Паскаль - первая версия для Windows, переделанная с ДОСа
 
+
-
edit
 

AidarM

аксакал
★★
А что неясного-то?
Вам предлагают сканировать вводимую строку и искать в ней символы плюс, минус и т.д., отделять мух(числа) от котлет(операции). Можно тупо сравнивать с '+','-'.
Т.е. :
if MyString[Номер символа]='+' then
begin
...
end;
Борланд Паскаль и TP - по сути одно и то же. Язык Паскаль в понимании и исполнении фирмы Борланд. Просто в комплект Турбо входит меньший комплект каких-то фич, чем в комплект 'Борланд', кажется.
Правда тут местами явно С вместо Паскаля. :)
   
+
-
edit
 

-exec-

опытный

Balancer, в вашем kcalk ln(e) чему равно? ;)

AidarM: imho там вообще странность: BorlandC++>>TurboC++, но TurboPascal>>BorlandPascal.
   
+
-
edit
 

Balancer

администратор
★★★★★
-exec->Balancer, в вашем kcalk ln(e) чему равно? ;)

Константы вводились в последний момент перед тем, как я программу забросил :D И при тамошнем доморощенном парсере, не удивительно, что вкралась ошибка, где-то там 'e'-константа с 'e'-порядком путается :)
   
Guest>Да я вообще ничего не понял из того, что вы все понмписали. :) Я же сказал, что программировать не умею. К тому же тут явно не тот Паскаль, что у нас. У нас Борланд Паскаль - первая версия для Windows, переделанная с ДОСа[»]

Так.... правильно :) набежали супер програмеры загрузили по полной. На паскале под винды никогда не писал (для этого делфи есть), сейчас напишу на нём по dos. думаю адаптировать будет недолго.
 

BrAB

аксакал
★★
Guest>>Да я вообще ничего не понял из того, что вы все понмписали. :) Я же сказал, что программировать не умею. К тому же тут явно не тот Паскаль, что у нас. У нас Борланд Паскаль - первая версия для Windows, переделанная с ДОСа[»]
brab>Так.... правильно :) набежали супер програмеры загрузили по полной. На паскале под винды никогда не писал (для этого делфи есть), сейчас напишу на нём по dos. думаю адаптировать будет недолго.[»]

Воощем....................... надеюсь написал понятно. работает под TP 7.0
code text
  1. uses crt;
  2. var a,b,c:real;s:string;
  3. begin
  4.      repeat {бесконечный цикл}
  5.      clrscr;
  6.      writeln('Enter a');
  7.      readln(a);
  8.      repeat
  9.            writeln('Enter +;-;*;/;exit');
  10.            readln(s);
  11.      until (s='-') or (s='+') or (s='*') or (s='/') or (s='exit'); {проверяем ввод знака или условие выхода}
  12.      if s='exit' then halt; {выходим из программы если введено exit}
  13.      writeln('Enter b');
  14.      readln(b);
  15.      case s[1] of {s[1] - это первый символ строки. case не понимает строк, поэтому мы даём ему символ}
  16.            '-':c:=a-b;  {если s[1]=- то вычитаем}
  17.            '+':c:=a+b;
  18.            '*':c:=a*b;
  19.            '/':c:=a/b;
  20.      end;
  21.      writeln(a:5:3,s,b:5:3,'=',c:5:3); {:5:3 ограничение по кол-ву знаков после запятой и ещё чему то :)}
  22.      readln;
  23.      until 1<>1; {из цикла выходим внутри него при вводе exit}
  24. end.

Ежели чего непонятно - в форум, аську, почту. нужно будет изменить под делфи - изменю. нужно что-то исправить - исправлю :)
   

в начало страницы | новое
 
Поиск
Настройки
Твиттер сайта
Статистика
Рейтинг@Mail.ru