Некорректное чтение данных из файла в 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 шт):
Проблема в этом куске кода
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;.
Вообще для этих целей есть стоит научится пользоваться отладкой.