IPB
ЛогинПароль:

> Прочтите прежде чем задавать вопрос!

1. Заголовок темы должен быть информативным. В противном случае тема удаляется ...
2. Все тексты программ должны помещаться в теги [code=pas] ... [/code], либо быть опубликованы на нашем PasteBin в режиме вечного хранения.
3. Прежде чем задавать вопрос, см. "FAQ", если там не нашли ответа, воспользуйтесь ПОИСКОМ, возможно такую задачу уже решали!
4. Не предлагайте свои решения на других языках, кроме Паскаля (исключение - только с согласия модератора).
5. НЕ используйте форум для личного общения, все что не относится к обсуждению темы - на PM!
6. Одна тема - один вопрос (задача)
7. Проверяйте программы перед тем, как разместить их на форуме!!!
8. Спрашивайте и отвечайте четко и по существу!!!

 
 Ответить  Открыть новую тему 
> Задача на очередь, Паскаль
сообщение
Сообщение #1





Группа: Пользователи
Сообщений: 5
Пол: Мужской
Реальное имя: Ярослав

Репутация: -  0  +


Всем привет. Задача следующая.
Сформировать очередь елементами которой есть цифры и арифметические знаки. Нужно вывести результат.

Пробовал сделать, но у меня почему-то выводится самый последний символ в очереди вместо результата. Скорей всего ошибка детская, но в теме немного не разобрался ://

Вот текст программы:
Program lab13z;       
Const zn=['+','-','*','/'];
Type zv=^pointer; {описание переменных}
pointer=record
boolkey:boolean;
arsing:char;
arcint:integer;
next:zv;
end;
Var scher,lcher:zv;
symb:char;
cfr:integer;
a,b:integer;

Procedure vcherc(zv1:zv;cfr1:integer); {процедура вставки ЧИСЛА в очередь}
Var q:zv;
Begin
new(q);
q^.arcint:=cfr1;
zv1^.next:=q;
zv1:=zv1^.next;
end;

Procedure vchers(zv1:zv;simv:char); {Процедура вставки СИМВОЛА в очередь}
Var q:zv;
Begin
new(q);
q^.arsing:=simv;
zv1^.next:=q;
zv1:=zv1^.next;
end;

Begin {формирование очереди}
new(scher);
scher^.next:=nil;
lcher:=scher;
writeln('Введите очередь');
repeat
read(symb);
if symb in ['0'..'9'] then
Begin
cfr:=ord(symb)-48+cfr*10;
vcherc(lcher,cfr);
cfr:=0;
end;
if symb in zn then
vchers(lcher,symb)
until symb='=';
scher:=scher^.next;
a:=scher^.arcint;
scher:=scher^.next;
while (scher<>nil) do
Begin
symb:=scher^.arsing;
scher:=scher^.next;
b:=scher^.arcint;
scher:=scher^.next;
case symb of
'+':a:=a+b;
'-':a:=a-b;
'*':a:=a*b;
'/':a:=a div b;
end;
end; {Cкорей всего неправильно вывожу результат =/}
write(a);
Readln;
readln;
end.


Зарание спасибо за помощь.

Сообщение отредактировано: mirtan -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #2


Гость






Попробуй сразу после того, как ты "заполнил" очередь, ее напечатать (т.е., напечатать символы/цифры, присутствующие в очереди). Больше ничего делать не надо, просто напечатать. Тогда тебе станет понятно, что заполняешь ты очередь неверно.

Для начала: что такое очередь, тебе известно? Что ты имеешь в виду под термином "очередь"? Структуру FIFO (First In - First Out/Первым вошел - Первым выйдешь)? Или что-то другое?

По какому алгоритму ты заполняешь очередь? Опиши его словами, а не кодом на Паскале, пожалуйста. И поверь, я просто так ничего не спрашиваю. Потом поймешь, почему я задаю такие вопросы. Если будешь на них отвечать, разумеется, а не просто ждать, пока кто-нибудь исправит программу.

Только скажи сразу, чего ты хочешь. Хочешь разобраться (понять, что у тебя не так, и исправить) самостоятельно - пожалуйста, я помогу, надеюсь - не только я, остальные тоже с удовольствием помогут. Если надо исправить за тебя, то на мою помощь можешь не рассчитывать.
 К началу страницы 
+ Ответить 
сообщение
Сообщение #3





Группа: Пользователи
Сообщений: 5
Пол: Мужской
Реальное имя: Ярослав

Репутация: -  0  +


Очередь я представляю как одна из разновидностей линейного списка, все елементы которого добавляются в конец, а считываются с начала списка. Да именно под абревиатурой FIFO.

Я себе представляю это так:
1) создается новый динамический обьект;
2) указатель равняем nil; так как следующего обьекта пока что вроде нету.

Вводим данные в очередь символы.

1) Если является цифрой от 0 до 9, то проделывая cfr:=ord(symb)-48+cfr*10 мы переводим в число, если у нас идут несколько цифр подряд. Вставляем в очередь и после этого приравниваем к 0, чтобы можна было перепроверять последующие цифры.
2) Если мы имеем другой символ - просто вставляем его в очередь. Повторяем операцию, пока не встречаем символ =.
3) А вот дальше я не совсем понимаю принцып. Вроде как сперва берем елемент а, после него идет символ. С помощью кейса вводим операции для каждого символа. Ну и потом берем елемент б с которым будем проводить операцию. Результат присваиваем а и выводим его на экран. Собственно тут какойто бред выходит.

Нет, код мне писать не нужно)) Если вдруг на экзамене попадется. Хочу разобратся.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #4


Гость






Цитата
1) Если является цифрой от 0 до 9, то проделывая cfr:=ord(symb)-48+cfr*10 мы переводим в число, если у нас идут несколько цифр подряд. Вставляем в очередь и после этого приравниваем к 0, чтобы можна было перепроверять последующие цифры.
А теперь посмотри, что ты делаешь на самом деле:
Цитата
repeat
read(symb); // Взял очередной символ. Допустим ...
if symb in ['0'..'9'] then // Если это ЦИФРА - то:
Begin
cfr:=ord(symb)-48+cfr*10; // преобразуешь ее в число
vcherc(lcher,cfr); // Засовываешь это однозначное число 0 .. 9 в очередь
cfr:=0; // И обнуляешь свою переменную-"накопитель"
end;
if symb in zn then
vchers(lcher,symb)
until symb='=';
Понимаешь, в чем ошибка? Если уж ты взял символ, который лежит в интервале '0' .. '9', то тебе надо там организовать цикл, который будет выполняться, пока очередной символ не будет выпадать из этого интервала. И только потом, по окончании цикла, когда ты действительно соберешь число, а не переведешь одну цифру из Char в Integer, будешь добавлять это число в очередь. Исправляй...

Теперь о добавлении:
Цитата
Procedure vcherc(zv1:zv;cfr1:integer); {процедура вставки ЧИСЛА в очередь}
Var q:zv;
Begin
new(q);
q^.arcint:=cfr1;
zv1^.next:=q;
zv1:=zv1^.next;
end;
Это неправильная процедура. Изменения переменной zv1 не передаются в вызывающую программу. Потому что ты работаешь с копией этой переменной, передаешь параметр по значению. Чтобы вернуть новое значение zv1 из процедуры, тебе надо передавать первый параметр по ссылке:
Procedure vcherc(VAR zv1:zv;cfr1:integer);


Опять же, это делается не совсем так, как ты показал. Не надо заранее выделять память под лишний элемент (то что ты делаешь в 34-ой строке кода). Ты это делаешь по одной простой причине: тебе надо быть уверенным, что scher не NIL, иначе программа твоя начнет вылетать при попытке сделать NIL^.next, правда?

Все проще:
Procedure PutInteger(var head, tail: zv; value: integer);
var q: zv;
begin
new(q); // Выделил память под новый элемент
q^.next := nil; q^.arcint := value; // заполнил поля НОВОГО ЭЛЕМЕНТА

if head = nil then head := q // очередь пуста? Значит первый элемент будет начальным...
else tail^.next := q; // Ах, не пуста? Уже были элементы? Прекрасно ,"прикрепляемся" к последнему

tail := q; // и запоминаем только что добавленный элемент. Теперь ОН - последний
end;

// Вызывать так:
scher := nil; lcher := nil;
...
PutInteger(scher, lcher, cfr);
Вот и все. Теперь добавление в очередь будет работать корректно, и тебе останется только исправить только сам алгоритм вычислений...

С алгоритмом вычисления значения, кстати, тоже не все так просто: 2+3*4= чему?Сначала надо вычислить 3*4 по правилам арифметики, правда? Или тебе надо вычисление без учета приоритетов операций? Ты это не уточнил, поэтому на данный момент (по умолчанию принято вычисление с учетом приоритетов) твой алгоритм неверен.
 К началу страницы 
+ Ответить 
сообщение
Сообщение #5





Группа: Пользователи
Сообщений: 5
Пол: Мужской
Реальное имя: Ярослав

Репутация: -  0  +


1) Тоесть считывать число нужно так? Пока символ является цифрой - переводить его?

While symb in ['0'..'9'] do
Begin
cfr:=ord(symb)-48+cfr*10;
vcherc(lcher,cfr); /
cfr:=0;
end;


2) C процедурой вставки я всё понял, спасибо большое что обьяснил.
3) Вычисления должно производится по порядку, тоесть как есть, без учёта законов арифметики.
Я представляю себе такой алгоритм:
Запоминаем первое число, присваиваем ему а. Видим символ, после которого 100% будет еще одно число, пускай b. В зависимости от значения символа, через кейс вводим операции, результат которой будет вносится опять же в а. Потом берем уже ЭТО а, и продолжаем дальше двигатся по циклу.

Допустим: 1)2+3-5+13=
а + b
2)2+3-5+13=
a - b

Сообщение отредактировано: mirtan -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #6


Гость






Цитата
Тоесть считывать число нужно так? Пока символ является цифрой - переводить его?
Нет... Тебе надо добавлять только результат. То есть, в цикле изменяешь cfr, а добавляешь полученное число - уже после цикла, когда symb не попадает в интервал '0' .. '9'. Ты же опять пытаешься добавлять по одной цифре в очередь...

Цитата
Я представляю себе такой алгоритм:
Ну, все правильно, теперь попробуй это реализовать smile.gif
 К началу страницы 
+ Ответить 
сообщение
Сообщение #7





Группа: Пользователи
Сообщений: 5
Пол: Мужской
Реальное имя: Ярослав

Репутация: -  0  +


Цитата
Нет... Тебе надо добавлять только результат. То есть, в цикле изменяешь cfr, а добавляешь полученное число - уже после цикла, когда symb не попадает в интервал '0' .. '9'. Ты же опять пытаешься добавлять по одной цифре в очередь...


Понял. Спасибо тебе огромное за помощь smile.gif.
С алгоритмом вычисления я уже разберусь smile.gif.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 

 Ответить  Открыть новую тему 
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 





- Текстовая версия 3.05.2024 7:33
500Gb HDD, 6Gb RAM, 2 Cores, 7 EUR в месяц — такие хостинги правда бывают
Связь с администрацией: bu_gen в домене octagram.name