Консультация № 177267
15.03.2010, 02:46
0.00 руб.
0 10 1
Добрый вечер! помогите пожалуйста решить задачу. тема динамические структуры данных. (лин. список)В системе регистрации заявок сервисного центра составляется список заявок в зависимости от приоритета отправителя (если клиент постоянный и важный приоритет – 0, если постоянный, но можно ненадолго отложить – 1 и т.д.). Сформировать список заявок, начиная с наивысшего приоритета и вывести его на экран.

Обсуждение

Неизвестный
15.03.2010, 16:36
общий
это ответ
Здравствуйте, Яруллина Ирина Булатовна.

Вот возможное решение.


Приложение:
{
В системе регистрации заявок сервисного центра
составляется список заявок в зависимости от
приоритета отправителя (если клиент постоянный
и важный приоритет - 0, если постоянный,
но можно ненадолго отложить - 1 и т.д.).

Сформировать список заявок, начиная с наивысшего
приоритета и вывести его на экран.
}

Program Requests;

Type
PRequestList = ^TRequest; { список заявок }
TRequest = Record { описание элемента списка}
req_text : string; { текст заявки }
req_rank : Byte; { приоритет заявки }

next : PRequestList; { следующая заявка в списке }
end;

TRequestFile = file of TRequest; { типизированный файл для хранения списка заявок }

Var
p : PRequestList; { указатель на список заявок }

s : string; { строка - используется для ввода данных пользователя }

{ Процедура аварийного завершения программы с описанием причины }
Procedure Fatal (msg : string);
begin
writeln;
writeln ('Ошибка: ', msg);
Halt (1);
end;

{ Процедура сохранения списка в файле }
Procedure SaveList (fname : string; p : PRequestList);
var
f : TRequestFile; { файловая переменная }
q : PRequestList; { указатель на элемент списка }

begin
{ Создание файла с обработкой ошибок }
{$I-}
Assign (f, fname); Rewrite (f);
{$I+}
if IOResult <> 0 then Fatal ('Не могу создать файл ' + fname + '!');

q := p; { начинаем обрабатывать список сначала }
while q <> nil do { пока есть элементы }
begin
write (f, q^); { записываем элемент в файл }
q := q^.next; { переходим к следующему элементу списка }
end;

Close (f); { закрыть файл }
end;

{ процедура считывания списка из файла }
Function LoadList (fname : string) : PRequestList;
var
f : TRequestFile; { файловая переменная }
p : PRequestList; { указатель на начало списка (точнее, элемент, предшествующий первому элементу списка) }
q : PRequestList; { указатель на элемент списка }

begin
{ Открытие файла с обработкой ошибок }
{$I-}
Assign (f, fname); Reset (f);
{$I+}
if IOResult <> 0 then Fatal ('Не могу открыть файл ' + fname + '!');

New (q); { создаем временный элемент списка }
q^.next := nil; { устанавливаем признак конца списка }
p := q; { сохраняем полученный указатель }
while not eof (f) do { считываем записи до конца файла }
begin
New (q^.next); { создаем новый элемент }
read (f, q^.next^); { считываем значение элемента из файла }
q^.next^.next := nil; { корректируем указатель на следующий элемент }
q := q^.next; { переходим к следующему элементу }
end;
LoadList := p^.next; { реальный список начинается со второго элемента }
Dispose (p); { удаляем временный элемент }

Close (f); { закрываем файл }
end;

{ Процедура очистки экрана (вместо использования аналогичной процедуры из модуля Crt) }
Procedure ClrScr; assembler;
asm
mov ax, 3
int 10h
end;

{ Процедура вывода списка согласно приоритетам }
Procedure PrintList (p : PRequestList);
var
q : PRequestList; { указатель на элемент списка }
cur_rank : Byte; { текущее значение приоритета }
first : Boolean; { флаг обработки начального элемента }
req_num : Byte; { количество выведенных заявок на текущем экране }

{ Локальная процедура вывода информации о приоритете }
procedure PrintRank (r : Byte);
begin
ClrScr;
writeln ('Заявки с приоритетом ', cur_rank);
writeln ('------------------------');
req_num := 0;
end;

{ Локальная процедура вывода подсказки для пользователя после заполнения экрана }
procedure PrintQuery;
begin
writeln;
write ('Нажмите Enter...');
readln;
end;

begin
q := p; { начинаем обработку с начала списка }
first := true; { устанавливаем признак начального элемента }
req_num := 0; { количество отображенных заявок - 0 }

while q <> nil do { пока элементы не закончились }
begin
{ если элемент начальный или произошла смена приоритета }
if first or (cur_rank <> q^.req_rank) then begin
if req_num <> 0 then PrintQuery; { если были выведены элементы - ждем реакцию пользователя }
cur_rank := q^.req_rank; { устанавливаем новый приоритет }
PrintRank (cur_rank); { выводим информацию о приоритете }
first := false; { сбрасываем признак начального элемента }
end;

writeln (q^.req_text); { выводим текст заявки }
Inc (req_num); { увеличиваем число выведенных заявок }
if req_num = 20 then begin { если вывели 21 заявку - ждем реакцию пользователя }
PrintQuery; { реакция }
PrintRank (cur_rank); { выводим информацию о приоритете }
end;

q := q^.next; { переходим к следующему элементу }
end;

if req_num <> 0 then PrintQuery; { если были выведены элементы - ждем реакцию пользователя }
end;

{ Процедура добавления заявки в список с учетом приоритета }
Procedure InsertIntoList (var p : PRequestList; r : PRequestList);
var
q : PRequestList; { элемент списка }

begin
q := p; { перебираем элементы с начала списка}
while q^.next <> nil do { пока список не пуст}
begin
{ если текущий элемент имеет такой же приоритет, как и у добавляемой заявки }
if q^.next^.req_rank = r^.req_rank then begin
{ вставим элемент перед текущим}
r^.next := q^.next;
q^.next := r;
break; { закончим просмотр списка }
end
{ если текущий элемент имеет более низкий приоритет, нежели у добавляемой заявки }
else if r^.req_rank < q^.next^.req_rank then begin
{ добавим элемент перед текущим - получаем список заявок, отсортированных по приоритетам }
r^.next := q^.next;
q^.next := r;
break; { закончим просмотр списка }
end;

q := q^.next; { перейдем к следующему элементу }
end;

{ если просмотрели весь список и не смогли вставить заявку - }
{ значит, у данной заявки новый приоритет, причем он самый низкий }
{ поэтому добавляем заявку в конец списка }
if q^.next = nil then q^.next := r;
end;

{ Функция ввода заявки пользователем }
Function InputRequest : PRequestList;
var
r : PRequestList; { указатель на заявку }

begin
New (r); { создаем заявку }
r^.next := nil; { следующего элемента нет}

{ запрос ввода текста заявки }
write ('Введите текст заявки (или введите "." для окончания ввода): '); readln (r^.req_text);
if r^.req_text = '.' then begin
Dispose (r); { удалить заявку }
InputRequest := nil; { возвратить нулевой указатель }
exit;
end;

{ запрос ввода приоритета заявки }
write ('Введите приоритет заявки: '); readln (r^.req_rank);
InputRequest := r; { возвратить заявку }
end;

{ Функция ручного ввода списка заявок }
Function InputList : PRequestList;
var
p : PRequestList; { указатель на список }
r : PRequestList; { указатель на заявку }

begin
ClrScr; { очистить экран и вывести заголовок }
writeln ('Ручной ввод заявок');
writeln;

New (p); { создать список }
p^.next := nil; { только временный элемент }

Repeat
r := InputRequest; { ввод заявки пользователем }
if r = nil then break { выйти из цикла при окончании ввода }
else InsertIntoList (p, r); { добавить заявку в список в соответствии с приоритетом }
Until false; { повторить ввод заявки }

InputList := p^.next; { возвратить список без учета временного элемента }
Dispose (p); { удалить временный элемент }
end;

{ Функция получения списка заявок }
Function GetList : PRequestList;
var
s : string;

begin
ClrScr; { очистить экран }

{ запрос информации от пользователя }
write ('Укажите имя файла со списком заявок (или введите "-" для ручного ввода): '); readln (s);

{ сформировать список заявок либо с помощью ручного ввода, либо путем загрузки из файла }
if s = '-' then GetList := InputList else GetList := LoadList (s);
end;

{ Процедура добавления новых заявок в список }
Procedure AddRequests (var p : PRequestList);
var
r : PRequestList; { указатель на заявку }
t : PRequestList; { указатель на список заявок }

begin
{ запрос информации от пользователя }
write ('Хотите добавить заявки? '); readln (s);
if s [1] in ['Y', 'y', 'Д', 'д'] then begin
New (t); { сформировать временный элемент }
t^.next := p; { перед реальным списком }

Repeat
r := InputRequest; { ввод заявки пользователем }
if r = nil then break; { выйти из цикла при окончании ввода }
InsertIntoList (t, r); { добавить заявку в список в соответствии с приоритетом }
Until false; { повторить ввод заявки }

p := t^.next; { откорректировать указатель на первый элемент списка }
Dispose (t); { удалить временный элемент }
end;
end;

{ Основная программа }
Begin
p := GetList; { получить список заявок }
PrintList (p); { вывести список на экран }

AddRequests (p); { добавить новые заявки }
PrintList (p); { вывести обновленный список }

{ предложить пользователю сохранить список в файле }
write ('Введите имя файла для сохранения списка заявок (или введите "-" если не хотите сохранять): ');
readln (s);
if s <> '-' then SaveList (s, p); { сохранить список в файле }
End.
Неизвестный
15.03.2010, 16:36
общий
Яруллина Ирина Булатовна:
При добавлении элемента происходит просмотр списка вплоть до нахождения нужного места для вставки.
Можно модифицировать программу, введя массив указателей, чтобы для каждого приоритета не нужно было бы искать место для вставки.
Если приоритетов не больше 255 (как обычно и бывает), то дополнительным расходом 1К памяти можно добиться существенной гибкости:
- упрощение добавления новых заявок (прямая вставка вместо поиска)
- возможность обработки отдельного списка заявок для каждого приоритета (в данной реализации - необходим предварительный поиск)

Причем можно хранить не только начальный, но и конечный указатель для каждого приоритета.

Если интересно - могу скинуть и такой вариант.
Неизвестный
16.03.2010, 10:22
общий
ого так много. я не знаю выдает ошибку. все равно спасибо за помощь.
Неизвестный
16.03.2010, 10:28
общий
слишком большой объем, можно ли как то проще решить, компакнее.
Неизвестный
16.03.2010, 12:47
общий
Яруллина Ирина Булатовна:
Что за ошибка? Каким компилятором пользуетесь? Проверялось в BP 7.1
Насчет большого объема и компактности - сейчас подумаю
Неизвестный
16.03.2010, 14:48
общий
Яруллина Ирина Булатовна:
Вот покороче...

Код:

{
В системе регистрации заявок сервисного центра
составляется список заявок в зависимости от
приоритета отправителя (если клиент постоянный
и важный приоритет - 0, если постоянный,
но можно ненадолго отложить - 1 и т.д.).

Сформировать список заявок, начиная с наивысшего
приоритета и вывести его на экран.
}

Program Requests;

Type
PRequestList = ^TRequest; { список заявок }
TRequest = Record { описание элемента списка}
req_text : string; { текст заявки }
req_rank : Byte; { приоритет заявки }

next : PRequestList; { следующая заявка в списке }
end;

TRankPosition = Record { диапазон заявок }
first : PRequestList; { начальная заявка в диапазоне }
last : PRequestList; { конечная заявка в диапазоне }
end;

TRankPosArray = array [0..255] of TRankPosition; { массив диапазонов по приоритетам }

Var
p : PRequestList; { указатель на список заявок }
rPos : TRankPosArray; { указатели на диапазоны заявок по приоритетам }
i : Byte; { переменная цикла }

{ Процедура аварийного завершения программы с описанием причины }
Procedure Fatal (msg : string);
begin
writeln;
writeln ('Ошибка: ', msg);
Halt (1);
end;

{ процедура считывания списка заявок из текстового файла }
{ файл содержит список заявок по одной на строке в виде <приоритет>-<текст заявки>}
Function LoadList (fname : string) : PRequestList;
var
f : text; { файловая переменная }
p : PRequestList; { указатель на начало списка }
q : PRequestList; { указатель на элемент списка }
s : string; { строка из файла }
r : Byte; { приоритет заявки }
i : Byte; { позиция разделителя в строке }
j : Byte; { переменная цикла }
ff : Boolean; { флаг успешного поиска }

e : Integer; { переменная для получения ошибки выполнения функции Val }

begin
{ Открытие файла с обработкой ошибок }
{$I-}
Assign (f, fname); Reset (f);
{$I+}
if IOResult <> 0 then Fatal ('Не могу открыть файл ' + fname + '!');

p := nil;
while not eof (f) do { вначале списка нет }
begin
readln (f, s); { читаем строку файла }

i := Pos ('-', s); { определяем позицию разделителя }
if i = 0 then continue; { игнорируем строки без раздилителя }

New (q); { создаем новую заявку }
Val (Copy (s, 1, i-1), r, e); { выбираем из строки приоритет }
q^.req_rank := r; { сохраняем его в заявку }
q^.req_text := Copy (s, i+1, length (s) - i); { записываем текст заявки }

ff := false;
if rPos [r].first = nil then begin { первая заявка с данным приоритетом }
rPos [r].first := q; { устанавливаем позиции начала }
rPos [r].last := q; { и конца диапазона с данным приоритетом }

if r > 0 then { если приоритет не высший }
for j := r - 1 downto 0 do { ищем ближайший не пустой диапазон заявок }
if rPos [j].last <> nil then begin { с более высоким приоритетом }
q^.next := rPos [j].last^.next; { добавляем новую заявку после }
rPos [j].last^.next := q; { последней в найденном диапазоне }
ff := true;
break; { и выходим из поиска }
end;

if not ff then begin { если ничего не нашли }
q^.next := p; { добавляем заявку }
p := q; { в начало списка }
end;
end
else begin { не первая заявка с данным приоритетом }
q^.next := rPos [r].last^.next; { корректируем границы диапазона заявок }
rPos [r].last^.next := q; { с данным приоритетом}
rPos [r].last := q;
end;
end;

Close (f); { закрываем файл }

LoadList := p; { возвращаем сформированный список }
end;

{ Процедура очистки экрана (вместо использования аналогичной процедуры из модуля Crt) }
Procedure ClrScr; assembler;
asm
mov ax, 3
int 10h
end;

{ Процедура вывода списка согласно приоритетам }
Procedure PrintList (a : TRankPosArray);
var
q : PRequestList; { указатель на элемент списка }
req_num : Byte; { количество выведенных заявок на текущем экране }
r : Byte;

{ Локальная процедура вывода информации о приоритете }
procedure PrintRank (r : Byte);
begin
ClrScr;
writeln ('Заявки с приоритетом ', r);
writeln ('------------------------');
req_num := 0;
end;

{ Локальная процедура вывода подсказки для пользователя после заполнения экрана }
procedure PrintQuery;
begin
writeln;
write ('Нажмите Enter...');
readln;
end;

begin
for r := 0 to 255 do
begin
if a [r].first <> nil then begin
PrintRank (r);
req_num := 0; { количество отображенных заявок - 0 }

q := a [r].first;
while q <> a [r].last^.next do { пока элементы не закончились }
begin
writeln (q^.req_text); { выводим текст заявки }
Inc (req_num); { увеличиваем число выведенных заявок }
if req_num = 20 then begin { если вывели 21 заявку - ждем реакцию пользователя }
PrintQuery; { реакция }
PrintRank (r); { выводим информацию о приоритете }
end;

q := q^.next; { переходим к следующему элементу }
end;

if req_num <> 0 then PrintQuery; { если были выведены элементы - ждем реакцию пользователя }
end;
end;
end;

{ Основная программа }
Begin
{ проверяем то, что при вызове задано имя файла }
if ParamCount = 0 then Fatal ('Должен быть задан параметр - имя файла со списком заявок!');

{ инициализация массива диапазонов }
for i := 0 to 255 do
begin
rPos [i].first := nil;
rPos [i].last := nil;
end;

p := LoadList (ParamStr (1)); { получить список заявок }
PrintList (rPos); { вывести список на экран }
End.


Здесь список заявок задается в текстовом файле.
Вот пример такого файла:

Код:

0-Q1-P0
1-Q1-P1
4-Q1-P4
3-Q1-P3
0-Q2-P0


Имя файла со списком заявок передается в качестве параметра, например: 177267.exe 177267.txt
Неизвестный
17.03.2010, 11:07
общий
все равно ошибку выдает. а можно как то скачать?????
Неизвестный
17.03.2010, 13:02
общий
Яруллина Ирина Булатовна:
Приведите ошибку и скажите, каким компилятором пользуетесь.
А что вы скачивать хотите?
Неизвестный
18.03.2010, 12:28
общий
ошибка № 86(не хватает : TRankPosArray = array [0..255] of TRankPosition; а скачать хотела приложение.
Неизвестный
18.03.2010, 13:49
общий
Яруллина Ирина Булатовна:
[size=2]В очередной раз спрашиваю - какой у вас компилятор?[/size]

Как вы исходный текст подготавливали - скопировали или вручную набирали?
Проверьте, что перед TRankPosArray есть строка:
end;

А вообще это какое-то бредовое сообщение. Никаких предпосылок для него нет. Попробуйте еще раз скопировать текст программы и откомпилировать его.
Форма ответа