Здравствуйте! Помогите, пожалуйста, решить задачу! Вот текст: Фирма по хранению и сбыту бытовых инструментов получает грузы с оборудованием по различным ценам и продает их затем с 20%-ной надбавкой, причем товары, полученные позднее, продаются в первую очередь. Нужно написать программу, считывающую записи о торговых операциях двух типов: операции по закупке и операции по продаже. Запись о закупке содержит префикс "R", количество товара, стоимость одного изделия и общую стоимость всей партии. Запись о продаже содержит префикс "S" и количество товара, а также стоимость данной партии. После считывания записи о закупке нужно вывести её на экран, например, если фирмой было продано 200 единиц оборудования, в которые входили 50 единиц с закупочной ценой 1,25$ и 150 единиц с закупочной ценой 1,1$, то должны быть напечатаны 3 строки: 50 штук по 1,50$ каждый на сумму 75.00$ 150 штук по 1.32$ каждый на сумму 198.00$ Всего продано на сумму 273.00$ Если на складе отсутствует требуемое в заказе число изделий, то нужно продать все имеющиеся и напечатать сообщение об отсутствии остальной части на складе.
Как подойти к решению? Как здесь использовать связанные списки? Пожалуйста, проконсультируйте!
volvo
26.09.2006 17:17
Связанные списки или ...связные списки? Если второе, то просто вместо массивов или файлов для хранения информации использовать списки (лучше - двухсвязные)...
pashist
26.09.2006 20:30
Задание на связанные списки.. На стеки..
volvo
26.09.2006 20:34
Цитата
Задание на связанные списки.. На стеки..
Так на списки или на стеки??? То же самое будет, если я тебе скажу: программу надо написать на Паскале. На Дельфи. На С++, разумеется... Выбери что-то одно, и иди в "FAQ: Все о динамических структурах данных".
pashist
26.09.2006 20:56
Сорри, СВЯЗАННЫЕ СПИСКИ. Пошел учить матчасть.
мисс_граффити
26.09.2006 23:44
нифига не поняла на что в итоге задание?
Цитата
Стек— это линейный список с определенной дисциплиной обслуживания, которая заключается в том, что элементы списка всегда включаются, выбираются и удаляются с одного конца, называемого вершиной стека. Доступ к элементам здесь происходит по принципу “последним пришел — первым ушел” (LIFO — last in first out), т.е. последний включенный в стек элемент первым из него удаляется.
Цитата
Фирма по хранению и сбыту бытовых инструментов получает грузы с оборудованием по различным ценам и продает их затем с 20%-ной надбавкой, причем товары, полученные позднее, продаются в первую очередь.
так что ты это... уточни.
pashist
28.09.2006 17:58
Узнал у препода: решать задачу можно любым удобным способом, смысл задачи заключается в использовании динамической памяти. Значит, удобнее всего использовать стек?
volvo
28.09.2006 19:22
Ты сначала расскажи, как именно должен происходить процесс покупки/продажи, а потом будем смотреть. Что, ты вводишь несколько итемов подряд с префиксом R, они записываются куда-то (намеренно не говорю, куда, пока не разьяснишь процесс - никаких предположений делать нельзя), а потом идет запрос на покупку?
КАК это все происходит? Что ТЫ вводишь, в какой последовательности? Приведи пример ВСЕЙ последовательности (что именно ты хочешь чтоб появлялось на экране ОТ и ДО, а не "как-то вот так", "просто вводим". НЕ БЫВАЕТ "просто вводим", нужно идеально точно знать, в какой последовательности и ЧТО ИМЕННО ты будешь вводить, и как должна реагировать система...)
pashist
2.10.2006 18:56
Программа работает как терминал. Объявляются две записи, на покупку и продажу. Пользователь с клавиатуры вводит то, что ему нужно: выступает в роли либо покупателя у терминала, либо продавца терминалу. Записи о поступлении товара на терминал заносятся в стек..
Цитата
После считывания записи о закупке нужно вывести её на экран
Скорее всего не о закупке, а о продаже, наверно смысловая опечатка, как думаете? Не спросил...
мисс_граффити
2.10.2006 22:05
а вот такой вопрос - тип товара не задается? как мы узнаем, ЧТО человеку нужно - только по цене ориентируемся, что ли? *представила. приходит покупатель: "дайте мне что-нибудь по 17 рублей!" - " у нас ничего такого нет, есть по 15 и 19" - "нет, мне нужно именно по 17" - "но они раньше стоили 17, а теперь подорожали!"
pashist
2.10.2006 23:15
Да, видимо так. Посмотри задание, в записи не указан тип товара. Значит, продаем одно и то же, только от разных поставщиков.
мисс_граффити
3.10.2006 19:31
Я бы сделала так: построила заголовочный список, в котором хранила инфу по каждому типу товаров, а именно: цена, количество на складе, указатель на след. элемент и указатель на список (или стек - как хочешь) поступлений по этому товару. каждый блок - только количество. если человек вводит приходную информацию - суммируем имеющееся количество с привезенным и "цепляем" блок. если покупает - смотрим, хватит ли нам товара. если нет - выводим сообщение о нехватке и удаляем нафиг весь прицепленный список (стек). если хватит, вычитаем из общего количества и начинаем с последнего блока вычитать из отдельных поставочных блоков. нулевые блоки удаляем.
pashist
3.10.2006 20:55
Я уже написал.. Посмотрите, пожалуйста, есть ошибки? По-моему, есть в сторках очистки памяти.. Может что-то можно упростить?
Программа(Показать/Скрыть)
Uses Crt;
Type TB=^Buy;
Buy=Record
Quantity: Integer;{Количество товара}
ProductCost: Real;{Стоимость одного изделия}
FullCost: Real; {Общая стоимость всей партии}
Prev: TB;
End;
TS=^Sell;
Sell=Record
Quantity: Integer;{Количество товара}
FullCost: Real; {Общая стоимость всей партии}
Prev: TS;
End;
Var B,TopB: TB;
S,TopS: TS;
a: Char;
Q: Integer;
PC,FC: Real;
Procedure InputBuyStack(Q: Integer; PC: Real);
Begin{FirstB:=Nil; в begin}
New(B);
B^.Prev:=TopB;
B^.Quantity:=Q;
B^.ProductCost:=PC;
B^.FullCost:=Q*PC;
TopB:=B
End;
Procedure InputSellStack(Q: Integer; FC: Real);
Begin{FirstS:=Nil; B Begin}
New(S);
S^.Prev:=TopS;
S^.Quantity:=Q;
S^.FullCost:=FC;
TopS:=S;
WriteLn(Q:5,' штук по ',FC/Q:5:2,'$ каждый на сумму ':5,FC:5:2);
End;
Function FullCostCount: Real;
Var Invoice: Real;
Begin
Invoice:=0;
While S<>NilDoBegin
Invoice:=Invoice+S^.FullCost;
S:=S^.Prev;
End;
FullCostCount:=Invoice;
End;
Procedure OutputBuyStack(Q: Integer);
BeginIf TopB<>NilThenBeginRepeatIf TopB^.Quantity>Q ThenBegin
InputSellStack(Q,Q*TopB^.ProductCost);
TopB^.Quantity:=TopB^.Quantity-Q;
Q:=0EndElseIf TopB^.Quantity=Q ThenBegin
InputSellStack(Q,TopB^.FullCost);
B:=TopB^.Prev;
Dispose(TopB);
TopB:=B;
Q:=0EndElse{If TopB^.Quantity<Q Then}Begin
InputSellStack(TopB^.Quantity, TopB^.Quantity*TopB^.ProductCost);
Q:=Q-TopB^.Quantity;
If TopB^.Prev=NilThenBegin
Q:=-Q;
Dispose(B);
TopB:=Nil;
EndElseBegin
B:=TopB^.Prev;
Dispose(TopB);
TopB:=B;
End;
End;
Until (Q=0) Or (Q<0);
If Q<0Then WriteLn('Продажа осуществлена не полностью');
WriteLn('Всего продано':5,'на сумму':5, FullCostCount:5:2);
EndElse
WriteLn('Терминал пуст.');
End;
Procedure OutText(Str: String; D,WrtLn: Boolean);
Var Temp: Real;
i: Integer;
k: Char;
Begin
k:=#0;
For i:=1To Length(Str) DoBeginWhile KeyPressed Do k:=ReadKey;
If k<>#27ThenBeginIf Str[i]=' 'ThenRepeat
Temp:=Temp+1;
Until Temp=999999;
Delay(20000); End;
Write(Str[i]);
Temp:=0;
End;
If D ThenRepeat
Temp:=Temp+1;
Until Temp=9999999;
If WrtLn Then WriteLn;
End;
Begin
ClrScr;
TopB:=Nil;
TopS:=Nil;
OutText('Добро пожаловать в консоль управления терминалом склада!',True,True);
OutText('Вы можете пополнить терминал товаром или выкупить его.',True,True);
OutText('Для пополнения нажмите B, для совершения покупки S',False,True);
Repeat
a:=ReadKey;
Case a Of'b':
Begin
OutText('Введите количество товара: ',False,False);
Read(Q);
OutText('Введите стоимость одного изделия: ',False,False);
Read(PC);
InputBuyStack(Q,PC);
End;
's':
Begin
OutText('Введите количество товара: ',False,False);
Read(Q);
OutputBuyStack(Q);
If S<>NilThen Dispose(S);
TopS:=Nil;
End;
End;
OutText('Для пополнения нажмите B, для совершения покупки S',False,True);
a:=#0Until a='z';
Dispose(B);
Dispose(TopB);
Dispose(S);
Dispose(TopS);
End.
volvo
3.10.2006 21:10
Цитата
Посмотрите, пожалуйста, есть ошибки?
Мне так нравится этот вопрос... "Прогоните и отладьте эту программу" - его второй смысл. ТЫ же ее писал, так отлаживай. Добейся сначала 100% правильного функционирования, а уж потом будешь гоняться за оптимальностью.
Я еще раз повторяю - программа должна прежде всего выдавать правильный результат, если она этого не делает - грош ей цена.
pashist
3.10.2006 21:17
Опять ты неправильно понял..... Программа работает правильно, есть даже некоторая защита от дурака. Я хочу, чтобы вы мне помогли её оптимизировать. Я написал так, насколько мне хватило опыта. У вас опыт больше, поэтому я и прошу мне помочь.
volvo
3.10.2006 21:49
a:=#0Until a='z';
И как выходим из программы?
pashist
3.10.2006 22:40
Это первое, что я исправил Спасибо)
volvo
3.10.2006 22:46
Кстати, у меня есть смутные подозрения, что если просто сделать выход по нажатию 'z', скажем, так:
Case a of
...
'z': Break; { <-- Выходим из Repeat ... Until }end;
, выбрать 2 раза пополнение, а потом, не производя покупок выйти из программы через 'z', то программа завершится аварийно (скорее всего - с 'invalid pointer operation' ). Я не прав?
pashist
3.10.2006 22:59
Прав.. А в чем дело?( Неполная очистка стека?
a:=#0;
a:=ReadKey;
Until a=#27;
If B<>NilThen Dispose(B);
If TopB<>NilThen TopB:=Nil;
If S<>NilThen Dispose(S);
If TopS<>NilThen TopS:=Nil;
Так ошибка не выскакивает
volvo
3.10.2006 23:03
Наоборот, ты пытаешься неоднократно применить Dispose к одному и тому же указателю, как результат - второй раз Dispose применяется к Nil, и ты видишь то, что видишь...
Что называется, "Вы глюков хотите - их есть у меня" (С)
Хы... Хитрый. А теперь попробуй сделать так:
Begin{ <--- Начало основной части программы }
WriteLn('Перед началом: ', MemAvail); { <-- Запиши это число }
ReadLn;
{ ... Вся твоя программа ... }
WriteLn('Перед завершением', MemAvail); { <-- Сравни с тем, что записал выше }
ReadLn;
End.
Эти 2 числа как пить дать не совпадут, а это означает, что у тебя есть утечка памяти...
pashist
3.10.2006 23:21
Вот я и хочу устранить эти баги.. Поэтому и спросил, где именно и что ковырять.
pashist
4.10.2006 16:08
Программу исправил, сдал и защитил. Всем спасибо.
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.