• B правой части каждого сообщения есть стрелки и . Не стесняйтесь оценивать ответы. Чтобы автору вопроса закрыть свой тикет, надо выбрать лучший ответ. Просто нажмите значок в правой части сообщения.

  • 15 апреля стартует «Курс «SQL-injection Master» ©» от команды The Codeby

    За 3 месяца вы пройдете путь от начальных навыков работы с SQL-запросами к базам данных до продвинутых техник. Научитесь находить уязвимости связанные с базами данных, и внедрять произвольный SQL-код в уязвимые приложения.

    На последнюю неделю приходится экзамен, где нужно будет показать свои навыки, взломав ряд уязвимых учебных сайтов, и добыть флаги. Успешно сдавшие экзамен получат сертификат.

    Запись на курс до 25 апреля. Получить промодоступ ...

Учет Старшинства Операций В Калькуляторе

  • Автор темы LukeSkywalker
  • Дата начала
L

LukeSkywalker

Здравствуйте, я пишу курсовую роботу в Delphi, а именно калькулятор. Никак не могу решить проблему: калькулятор считает без учета старшинства операций, т.е. выражения типа "2+2*2" он считает как "8". Помогите пожалуйста, как сделать учет старшинства операций? Если нужно, могу выложить файлы проекта.
 
S

Senset

создаешь массив (dstv[1..4] of char) инициируешь их как '*','/','+','-'
пишешь процедуру, которая определяет операнды действия: 2+3*4
У '*' операнды: 3,4
У '+' операнды: 2,7
процедура выглядит так: procedure get_operadns(s:string;dstv:integer;var o1,o2:string;var n,k:integer);
параметры процедуры:
s - строка, в которой определяешь операнды
dstv - позиция символа действия, т.е. для примера 2+2*2 позиция символа первого действия = 4
o1,o2 - через них должны вернуться операнды в виде строк (или сразу делай их типом integer или real)
n - позиция начала первого операнда
k - позиция конца второго операнда
Операнды определяются достаточно просто: идешь в левую (и в правую) сторону от номера символа dstv до тех пор пока не найдешь:
1) знак другого действия
2) конец строки
3) начало строки

Код использования в красивом виде будет выглядеть примерно так:
Код:
var o1,o2:string;
n,k:integer;
str:real;

s:='2+2*2';
dstv[1]:='*';
dstv[2]:='/';
dstv[3]:='+';
dstv[4]:='-';
for i:=1 to 4 do
begin
if pos(dstv[i],s)>0 then
begin
//найдено какое-либо действие
get_operands(s,pos(dstv[i],s),o1,o2,n,k);
case dstv[i] of 
'+': str:=strtofloat(o1)+strtofloat(o2);
'-': str:=strtofloat(o1)-strtofloat(o2);
'*': str:=strtofloat(o1)*strtofloat(o2); 
'/': str:=strtofloat(o1)/strtofloat(o2);
end;
delete(s,n,k-n+1);
insert(floattostr(str),s,n);
end;
end;

Оговорки:
1) Действие '-' лучше не учитывать... лучше рассматривать как действие с отрицательным числом
2) Код достаточно легко можно доработать до учитывания скобок () (делается рекурсией), по аналогии с разбитием действий можно доработать всякие функции (sin,cos.tg....)
3) Как можно понять функция get_operands - самая важная во всем этом деле... потому оставляю её тебе) - ибо похоже что она частично у тебя уже написана
P.S. если дополнить её (так чтобы она не всегда искала два операнда) - можно будет потом влепить её при определении операндов для мат. функций.
4) При использовании get_operand реально имеет смысл сразу возвращать числовой тип данных, и при этом: делать проверку перед конвертированием числа, что там не оказалось хлама... т.е. s='123fff' - при конверте =вылет, s='' - при конверте вылет, s='1.23' - при конверте = вылет (потому что разделителем целой и дробной частей в Delphi является запятая), в случае написания в Pascal = задача в разы усложняется, но для конверта можно будет использовать раздельное преобразование и соответственно сам определишь каким символом будут отделяться части (целой от дробной: хоть '.', хоть ',', хоть '#')
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!