Некорректное чтение данных из файла в record

Есть текстовый файл с записанными в строку данными Имя Фамилия Вес Рост Пол. В файле несколько строк по количеству описанных таким образом людей. Необходимо прочитать файл и записать строки в элементы массива типа record с соответствующими атрибутами. Программа организована в виде нескольких процедур: запись с клавиатуры, сохранение в текстовый файл, чтение текстового файла, и несколько специфических выводов для контроля корректности(самый тяжелый мальчик, самая легкая девочка). Код программы:

program schoolkids;
uses crt;
type kid_info = record
    first_name: string[20];
    second_name: string[30];
    weight: string[11];
    gender: string[1];
    height: string[11];
end;

type kid_record = array[1..100] of kid_info;
type read_string = string[100];
type read_word = string[30];
var kids: kid_record;
    filename:read_string;
    word:read_word;
    letter:char;
    i, n, option,attr,list_size, max_height, max_i, min_weight, min_i,
    height_as_int, weight_as_int, error_code: integer;

    kid_info_file: text;

procedure Input_records();
begin
clrscr;
write('How many students do you want to record? '); readln(n);
for i:=1 to n do
    with kids[i] do
        begin
        write('Input #',i,' student`s name: ');readln(first_name);
        write('Input #',i,' student`s surname: ');readln(second_name);
        write('Input #',i,' student`s weigth, kg: ');readln(weight);
        write('Input #',i,' student`s gender (m/f): ');readln(gender);
        write('Input #',i,' student`s height, cm: ');readln(height);

        end;
readln;
end;

procedure Tall_boy(max_height:integer);
begin
clrscr;
for i:=1 to n do
    with kids[i] do
    begin

    if kids[i].gender='m' then
        begin
        Val(kids[i].height, height_as_int, error_code);
        if height_as_int>max_height then
            begin
            max_i:=i;
            max_height:=height_as_int;
            end;
        end;
    end;
writeln('Tallest schoolboy has following attributes:');
writeln('Name:    ',kids[max_i].first_name);
writeln('Surname: ',kids[max_i].second_name);
writeln('Height:  ',kids[max_i].height);
writeln('Weight:  ',kids[max_i].weight);
readln;
end;

procedure Light_girl(min_weight:integer);
begin
clrscr;
for i:=1 to n do
    with kids[i] do
    begin

    if kids[i].gender='f' then
        begin
        Val(kids[i].weight, weight_as_int, error_code);
        if weight_as_int<min_weight then
            begin
            min_i:=i;
            min_weight:=weight_as_int;
            end;
        end;
    end;
writeln('Lightest schoolgirl has following attributes:');
writeln('Name:    ',kids[min_i].first_name);
writeln('Surname: ',kids[min_i].second_name);
writeln('Height:  ',kids[min_i].height);
writeln('Weight:  ',kids[min_i].weight);
readln;
end;

procedure Save_file(n:integer; kids:kid_record);
begin
assign(kid_info_file,'students.txt');
rewrite(kid_info_file);
for i:=1 to n do
        writeln(kid_info_file,kids[i].first_name,' ',kids[i].second_name,' ',kids[i].weight,' ',kids[i].height,' ',kids[i].gender);
close(kid_info_file);
end;

procedure Open_file(filename:read_string;
                    letter:char;
                    word:read_word;
                    attr, list_size:integer);
begin
clrscr;
writeln('Input root to file:');
readln(filename);
assign(kid_info_file,filename);
reset(kid_info_file);
list_size:=0;

for i:=1 to 100 do
    begin
    list_size:=list_size+1;
    word:='';
    attr:=1;
    kids[i].first_name:='';
    kids[i].second_name:='';
    kids[i].gender:='';
    kids[i].height:='';
    kids[i].weight:='';
    repeat
    begin
    read(kid_info_file, letter);
    if letter<>' ' then word:=word+letter
                    else begin
                           case attr of
                           1: begin kids[i].first_name:=word; attr:=attr+1; break; end;
                           2: begin kids[i].second_name:=word; attr:=attr+1; break; end;
                           3: begin kids[i].weight:=word; attr:=attr+1; break; end;
                           4: begin kids[i].height:=word; attr:=attr+1; break; end;
                           5: begin kids[i].gender:=word; break; end;
                           end;
                         end;
    end;
    until eoln(kid_info_file);

    if eof(kid_info_file) then break;
    end;
close(kid_info_file);
for i:=1 to list_size do
        begin
        writeln(kids[i].first_name,' ',kids[i].second_name,' ',kids[i].weight,' ',kids[i].height,' ',kids[i].gender);
        end;

readln;
end;

{main}
begin

repeat
    clrscr;
    max_height:=0; min_weight:=32000;
    writeln('Main menu');
    writeln('1. Input records about students');
    writeln('2. Show tallest schoolboy info');
    writeln('3. Show lightest schoolgirl info');
    writeln('4. Save records as file');
    writeln('5. Open file');
    writeln('6. Exit');

        readln(option);
        case option of
            1: Input_records();
            2: Tall_boy(max_height);
            3: Light_girl(min_weight);
            4: Save_file(n,kids);
            5: Open_file(filename,
                         letter,
                         word,
                         attr, list_size);
            6: Halt();
            else begin
                     writeln('Wrong option, choose another one.'); readln();
                 end;
        end;
until option=6;
end.

Ввод с клавиатуры, запись в текстовый файл и контрольные опции после ввода с клавиатуры работают корректно. Не выходит прочесть и правильно распарсить файл так, чтобы распределить в строках по атрибутам record'a. При выводе не печать вроде бы все правильно, но дальше массив записей невозможно использовать для вывода контрольных опций 2,3, а сохранение в файл создает пустой файл.

Помогите найти ошибку? Спасибо!


Ответы (1 шт):

Автор решения: Alex R.

Проблема в этом куске кода

if letter<>' ' then word:=word+letter
                else begin
                       case attr of
                       1: begin kids[i].first_name:=word; attr:=attr+1; break; end;
                       2: begin kids[i].second_name:=word; attr:=attr+1; break; end;
                       3: begin kids[i].weight:=word; attr:=attr+1; break; end;
                       4: begin kids[i].height:=word; attr:=attr+1; break; end;
                       5: begin kids[i].gender:=word; break; end;
                       end;
                     end;
end;

Здесь при записи в атрибут зачет-то вставлен break, этот оператор завершает текущий цикл, а это чтение строки, т.е. строка не дочитывается до конца с первого раза, а элемент уже следующий. Должно быть так.

if letter<>' ' then word:=word+letter
                else begin
                       case attr of
                       1: kids[i].first_name:=word;
                       2: kids[i].second_name:=word;
                       3: kids[i].weight:=word;
                       4: kids[i].height:=word;
                       5: kids[i].gender:=word;
                       end;

                       attr:=attr+1;
                       Word:='';
                     end;

Первым маркером, что-то что не так с программой это дублирование кода: attr:=attr+1; break;.

Вообще для этих целей есть стоит научится пользоваться отладкой.

→ Ссылка