Консультация № 177763
09.04.2010, 03:31
0.00 руб.
0 4 1
Добрый вечер.

Нужна помощь в реализации следующей задачи:

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

В новый файл записать студентов со средним баллом >=4.0, а ФИО остальных студентов рассортировать в алфавитном порядке, записав их в третий файл.

Организовать вывод всех файлов.

Обсуждение

давно
Академик
320937
2216
09.04.2010, 08:54
общий
geschutze:
Можете показать пример строки текстового файла? Выржение "последняя сессия" как-то используется?
Неизвестный
09.04.2010, 09:40
общий
Да, поскольку нужно разбирать строку, то нужно знать, что и в каком порядке записано в ней, что может быть использовано в качестве разделителей полей
Неизвестный
12.04.2010, 14:47
общий
это ответ
Здравствуйте, geschutze.
Что-то Вы не отвечаете на вопросы наши ...
Поэтому написал, как понял (кое-какие комментарии есть в тексте программы).
Прикрепляю архив с исходным файлом и файлом исходных данных (смотреть надо в Паскале, поскольку кодировка ДОСовская)
Пример окна программы:
Код:
Конвертировано записей:6
Сидоров В. П. 3 4 5 1 3.25
Иванов С. Е. 5 5 5 5 5.00
Сергеев И. Иванович 3 3 3 3 3.00
Ступник Остап Карпович 5 5 5 5 5.00
Тупой Сергей Сергеевич 2 2 2 2 2.00
Ещетупее С. С. 1 1 1 1 1.00

Имеется информация о студентах: 6
Из них среднюю оценку 4 и выше имеют: 2
Остальных: 4
Другие:
Ещетупее С. С. 1 1 1 1 1.00
Сергеев И. Иванович 3 3 3 3 3.00
Сидоров В. П. 3 4 5 1 3.25
Тупой Сергей Сергеевич 2 2 2 2 2.00


Приложение:
uses CRT;
CONST
src_fileName = '177763.dat';
typ_fileName = '177763.typ';
d04_fileName = 'above4.dat';
other_fileName = 'other.dat';
FIO_len = 25;
subjects = 4;

{Полагаю, что в текстовом файле сначала идет фамилия, потом через пробел
инициалы, каждый из которых заканчивается точкой. Между инициалами
могут быть пробелы. Могут быть не инициалы, а имя и отчество - тоже
допустимо.
Лишь бы не была превышена максимальная длина поля 25 (константа
FIO_len) - будет просто отброшено лишнее
Потом через пробелы 4 цифры - оценки за предметы "последней" сессии
Считаю, что оценка может состоять из одной цифры от 0 до 5
В качестве разделителей могут быть пробелы, запятые, точки с запятой}
deviders: Set of char = [' ',',',';'];
numbers : set of char = ['0'..'5'];

TYPE
TOneStudent = record
FIO: String[FIO_len];
scores: array[1..subjects] of Byte; {Оценки}
mid_score: Real; {Средняя оценка}
end;

function Analyse(src: String; var t: TOneStudent): Boolean;
{Анализ одной строки. Возврашает FALSE, если нельзя преобразовать
полностью}
var i, j, len, count, sum: Integer;
buf: String;
begin
Analyse:=FALSE;
len := length(src);
i:=1;
while i <= len do
begin
{Пропуск разделителей (пробелов)}
while (src[i] in deviders) and ( i <= len) do inc(i);
if i > len then Exit;
{Должна начинаться фамилия}
buf:='';
while (NOT(src[i] in deviders)) and (i <= len ) do begin
buf := buf + src[i];
inc(i);
end;
buf := buf + ' '; {Один пробел для разделения}
if i > len then Exit; {нет инициалов и оценки}
while (src[i] in deviders) and ( i <= len) do inc(i);
if i > len then Exit;
while (NOT(src[i] in deviders)) and (src[i] <> '.') and (i <= len ) do begin
buf := buf + src[i];
inc(i);
end;
if src[i] = '.' then
begin
inc(i);
buf := buf + '. '
end
else
buf := buf + ' ';
while (src[i] in deviders) and ( i <= len) do inc(i);
if i > len then Exit;
while (NOT(src[i] in deviders)) and (i <= len ) do begin
buf := buf + src[i];
inc(i);
end;
t.FIO := copy(buf, 1, FIO_len); {Возможная обрезка по длине поля}
{Теперь ищем 4 цифры}
count := 0;
while (count < 4) and (i <= len) do
begin
{Всегда вначале пропускаем разделители}
while (src[i] in deviders) and ( i <= len) do inc(i);
if (i > len) or NOT(src[i] in numbers) then Exit;
{Тут стоит в строке все, угодно,
но не оценка - считаем ошибкой и не обрабатываем больше ничего}
inc(count);
t.scores[count] := ord(src[i]) - ord('0'); {Так вычисляем}
inc(i);
if (src[i] in numbers) or ((i > len) and (count < 4)) then Exit;
{Или цифра двузначная или строка кончилась, а нужно числа
оценок нет}
end;
{Вычисление средней оценки}
sum := 0; {будет сумма}
for j:=1 to 4 do
sum := sum + t.scores[j];
t.mid_score := sum/4;
Analyse := TRUE; Exit;
{Все хорошо выполнили.
Дальше в строке может быть записано что угодно - игнорируем}
end;
Analyse := TRUE; {Если сюда добрались, значит все было хорошо}
end;

{Возращает число конвертированных строк}
function ConvertTextToTypified(srcFile, destFile: String): Longint;
var
t: Text;
f: File of TOneStudent;
r: TOneStudent;
s: String;
count: longint;
begin
ConvertTextToTypified := 0;
assign(t, srcFile);
{$I-} Reset(t); {$I+}
if IOResult <> 0 then begin
WriteLn('Не могу открыть исходный файл ', srcFile);
Exit;
end;
assign(f, destFile);
rewrite(f); {Можно, конечно, посмотреть, имеется ли и спросить,
что делать: переписать или дополнить - нужно будет, сделаю}
count := 0; {счетчик удачно конвертированных строк}
While NOT EOF(t) do
begin
Readln(t, s);
if Analyse(s, r) then
begin
inc(count);
Write(f, r);
end;
end;
Close(t);
Close(f);
ConvertTextToTypified:=count
end;

procedure ShowTyped(typedFile: String);
var
f: File of TOneStudent;
r: TOneStudent;
begin
Assign(f, typedFile);
{$I-} Reset(f); {$I+}
if IOResult <> 0 then begin
WriteLn('Не могу открыть типизированный файл ',typedFile);
Exit
end;
While NOT EOF(f) do begin
{$I-} Read(f, r); {$I+}
if IOResult <> 0 then begin
WriteLn('Ошибка чтения из файла ',typedFile);
end
else WriteLn(r.FIO:FIO_len, r.scores[1]:3,
r.scores[2]:3,r.scores[3]:3,r.scores[4]:3,
r.mid_score:10:2);
end;
Close(f);
end;


function FourAndAbove(src_typedFile,
dest_fourFile, dest_otherFile: String): LongInt;
var f, d4f, dof: File of TOneStudent;
count, count_o, count_4, p1, p_min: Longint;
r, buf: TOneStudent;
p: Longint;
begin
{Функция возвращает общее число записей
а также распределит записи по критерию "средняя 4 и выше" и остальные
остальные сортирует}
FourAndAbove := 0;
Assign(f, src_typedFile);
{$I-} Reset(f); {$I+}
if IOResult <> 0 then begin
WriteLn('Не могу открыть ', src_typedFile,'. Работа не возможна');
Exit;
end;
count := 0;
Assign(d4f, dest_fourFile);
count_4 := 0;
Rewrite(d4f);
Assign(dof, dest_otherFile);
count_o := 0;
Rewrite(dof);
{Сортировка по файлам}
while NOT EOF(f) do begin
{$I-} Read(f, r); {$I+}
if IOResult <> 0 then begin
WriteLn('Ошибка чтения из файла ',src_typedFile);
Continue; {Перейти к следующей записи}
end;
inc(count);
if r.mid_score >= 4.0 then
begin
Write(d4f, r);
inc(count_4)
end
else
begin
Write(dof, r);
inc(count_o)
end
end;
WriteLn('Имеется информация о студентах: ', count);
WriteLn('Из них среднюю оценку 4 и выше имеют: ', count_4);
WriteLn('Остальных: ', count_o);
{Сортировка в файле остальных - методом вставки}
if count_o > 1 then
{Если меньше, то пустой или одна запись - нечего сортировать}
begin
Reset(dof);
count_o := count - 3;
{счет положения в файле начинается с нуля}
for p1 := 0 to count_o do {p1 - Текущее положение в файле}
begin
seek(dof, p1);
read(dof, r);
p_min := p1;
while NOT EOF(dof) do
begin
p := FilePos(dof);
read(dof, buf);
if buf.FIO < r.FIO then
begin
p_min := p;
r := buf
end;
end;
if p_min <> p1 then
begin
seek (dof, p1);
Read(dof, buf);
seek (dof, p1);
Write(dof, r);
seek (dof, p_min);
Write(dof, buf);
end
end
end;

Close(f);
Close(d4f);
Close(dof);
FourAndAbove := count
end;

BEGIN
ClrScr;
Writeln('Конвертировано записей:',
ConvertTextToTypified(src_FileName, typ_fileName));
ShowTyped(typ_fileName);
WriteLn;
FourAndAbove(typ_fileName, d04_fileName, other_fileName);

WriteLn('Другие:');
ShowTyped(other_fileName);
END.
Прикрепленные файлы:
5
Благодарю за потраченное время (=
Неизвестный
12.04.2010, 15:54
общий
Спасибо за оценку, и подтверждаю, что открыт для вопросов по теме этой
Форма ответа