[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 для ДОС.
{************************************************}
{                                                }
{   Turbo Vision Demo                            }
{   Copyright (c) 1990 by Borland International  }
{                                                }
{************************************************}

unit Calc;

{$F+,O+,S-}

{ Calculator object. See TVDEMO.PAS for an example
  program that uses this unit.
}

interface

uses Drivers, Objects, Views, Dialogs;

type

  TCalcState = (csFirst, csValid, csError);

  PCalcDisplay = ^TCalcDisplay;
  TCalcDisplay = object(TView)
    Status: TCalcState;
    Number: string[15];
    Sign: Char;
    Operator: Char;
    Operand: Real;
    constructor Init(var Bounds: TRect);
    constructor Load(var S: TStream);
    procedure CalcKey(Key: Char);
    procedure Clear;
    procedure Draw; virtual;
    function GetPalette: PPalette; virtual;
    procedure HandleEvent(var Event: TEvent); virtual;
    procedure Store(var S: TStream);
  end;

  PCalculator = ^TCalculator;
  TCalculator = object(TDialog)
    constructor Init;
  end;

const
  RCalcDisplay: TStreamRec = (
     ObjType: 10040;
     VmtLink: Ofs(TypeOf(TCalcDisplay)^);
     Load:    @TCalcDisplay.Load;
     Store:   @TCalcDisplay.Store
  );
  RCalculator: TStreamRec = (
     ObjType: 10041;
     VmtLink: Ofs(TypeOf(TCalculator)^);
     Load:    @TCalculator.Load;
     Store:   @TCalculator.Store
  );

procedure RegisterCalc;

implementation

const
  cmCalcButton = 100;

constructor TCalcDisplay.Init(var Bounds: TRect);
begin
  inherited Init(Bounds);
  Options := Options or ofSelectable;
  EventMask := evKeyDown + evBroadcast;
  Clear;
end;

constructor TCalcDisplay.Load(var S: TStream);
begin
  inherited Load(S);
  S.Read(Status, SizeOf(Status) + SizeOf(Number) + SizeOf(Sign) +
    SizeOf(Operator) + SizeOf(Operand));
end;

procedure TCalcDisplay.CalcKey(Key: Char);
var
  R: Real;

procedure Error;
begin
  Status := csError;
  Number := 'Error';
  Sign := ' ';
end;

procedure SetDisplay(R: Real);
var
  S: string[63];
begin
  Str(R: 0: 10, S);
  if S[1] <> '-' then Sign := ' ' else
  begin
    Delete(S, 1, 1);
    Sign := '-';
  end;
  if Length(S) > 15 + 1 + 10 then Error
  else
  begin
    while S[Length(S)] = '0' do Dec(S[0]);
    if S[Length(S)] = '.' then Dec(S[0]);
    Number := S;
  end;
end;

procedure GetDisplay(var R: Real);
var
  E: Integer;
begin
  Val(Sign + Number, R, E);
end;

procedure CheckFirst;
begin
  if Status = csFirst then
  begin
    Status := csValid;
    Number := '0';
    Sign := ' ';
  end;
end;

begin
  Key := UpCase(Key);
  if (Status = csError) and (Key <> 'C') then Key := ' ';
  case Key of
    '0'..'9':
      begin
        CheckFirst;
        if Number = '0' then Number := '';
        Number := Number + Key;
      end;
    '.':
      begin
        CheckFirst;
        if Pos('.', Number) = 0 then Number := Number + '.';
      end;
    #8, #27:
      begin
        CheckFirst;
        if Length(Number) = 1 then Number := '0' else Dec(Number[0]);
      end;
    '_', #241:
      if Sign = ' ' then Sign := '-' else Sign := ' ';
    '+', '-', '*', '/', '=', '%', #13:
      begin
        if Status = csValid then
        begin
          Status := csFirst;
          GetDisplay(R);
          if Key = '%' then
            case Operator of
              '+', '-': R := Operand * R / 100;
              '*', '/': R := R / 100;
            end;
          case Operator of
            '+': SetDisplay(Operand + R);
            '-': SetDisplay(Operand - R);
            '*': SetDisplay(Operand * R);
            '/': if R = 0 then Error else SetDisplay(Operand / R);
          end;
        end;
        Operator := Key;
        GetDisplay(Operand);
      end;
    'C':
      Clear;
  end;
  DrawView;
end;

procedure TCalcDisplay.Clear;
begin
  Status := csFirst;
  Number := '0';
  Sign := ' ';
  Operator := '=';
end;

procedure TCalcDisplay.Draw;
var
  Color: Byte;
  I: Integer;
  B: TDrawBuffer;
begin
  Color := GetColor(1);
  I := Size.X - Length(Number) - 2;
  MoveChar(B, ' ', Color, Size.X);
  MoveChar(B[I], Sign, Color, 1);
  MoveStr(B[I + 1], Number, Color);
  WriteBuf(0, 0, Size.X, 1, B);
end;

function TCalcDisplay.GetPalette: PPalette;
const
  P: string[1] = #19;
begin
  GetPalette := @P;
end;

procedure TCalcDisplay.HandleEvent(var Event: TEvent);
begin
  inherited HandleEvent(Event);
  case Event.What of
    evKeyDown:
      begin
        CalcKey(Event.CharCode);
        ClearEvent(Event);
      end;
    evBroadcast:
      if Event.Command = cmCalcButton then
      begin
        CalcKey(PButton(Event.InfoPtr)^.Title^[1]);
        ClearEvent(Event);
      end;
  end;
end;

procedure TCalcDisplay.Store(var S: TStream);
begin
  TView.Store(S);
  S.Write(Status, SizeOf(Status) + SizeOf(Number) + SizeOf(Sign) +
    SizeOf(Operator) + SizeOf(Operand));
end;

{ TCalculator }

constructor TCalculator.Init;
const
  KeyChar: array[0..19] of Char = 'C'#27'%'#241'789/456*123-0.=+';
var
  I: Integer;
  P: PView;
  R: TRect;
begin
  R.Assign(5, 3, 29, 18);
  inherited Init(R, 'Calculator');
  Options := Options or ofFirstClick;
  for I := 0 to 19 do
  begin
    R.A.X := (I mod 4) * 5 + 2;
    R.A.Y := (I div 4) * 2 + 4;
    R.B.X := R.A.X + 5;
    R.B.Y := R.A.Y + 2;
    P := New(PButton, Init(R, KeyChar[I], cmCalcButton,
      bfNormal + bfBroadcast));
    P^.Options := P^.Options and not ofSelectable;
    Insert(P);
  end;
  R.Assign(3, 2, 21, 3);
  Insert(New(PCalcDisplay, Init(R)));
end;

procedure RegisterCalc;
begin
  RegisterType(RCalcDisplay);
  RegisterType(RCalculator);
end;

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

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


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


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



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

   

hsm

опытный

А вот полный листинг для 4-х действий и двух операндов.

#include <stdio.h>

int main(){
	int a,b,rez;
	char ops;
	
	while( 1 ){
		scanf("%d %c %d",&a,&ops,&b);
		switch( ops ){
			case '+':
				rez=a+b;
				break;
			case '-':
				rez=a-b;
				break;
			case '*':
				rez=a*b;
				break;
			case '/':
				rez=a/b;
				break;
			default:
				return 0;
				break;
			}
		printf("=%d\n",rez);
		}
	return 0;
}


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

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

ЗЫ
Как говориться "Упс!". Движок форума всю разметку "съел".
   
Это сообщение редактировалось 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

uses crt;
var a,b,c:real;s:string;
begin
     repeat {бесконечный цикл}
     clrscr;
     writeln('Enter a');
     readln(a);
     repeat
           writeln('Enter +;-;*;/;exit');
           readln(s);
     until (s='-') or (s='+') or (s='*') or (s='/') or (s='exit'); {проверяем ввод знака или условие выхода}
     if s='exit' then halt; {выходим из программы если введено exit}
     writeln('Enter b');
     readln(b);
     case s[1] of {s[1] - это первый символ строки. case не понимает строк, поэтому мы даём ему символ}
           '-':c:=a-b;  {если s[1]=- то вычитаем}
           '+':c:=a+b;
           '*':c:=a*b;
           '/':c:=a/b;
     end;
     writeln(a:5:3,s,b:5:3,'=',c:5:3); {:5:3 ограничение по кол-ву знаков после запятой и ещё чему то :)}
     readln;
     until 1<>1; {из цикла выходим внутри него при вводе exit}
end.

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

в начало страницы | новое
 
Поиск
Поддержка
Поддержи форум!
ЯндексЯндекс. ДеньгиХочу такую же кнопку
Настройки






Статистика
Рейтинг@Mail.ru
АвиаТОП
 
Яндекс.Метрика
website counter
 
free counters