0

I have a small code where I want to initialize an array of records by fields and then just output this records on screen.

Data types:

type
  grade = 1..5;
  Person = record
    Name: string[16];
    isMale: boolean;
    grades: array [1..6] of grade;
  end;
var
  Table: array [1..10] of Person;
  R: Person;
  N,J,I: Integer;

Part of code with initialization and output:

  readln(n);
  if N>10 then N:=10;    if N<1 then N:=1;
  for I:=1 to N do begin
    R:=Table[I];
    //write('Gender?'); readln(j); R.isMale:=j>=0; <= This works just fine
    write('Name? ');  readln(R.Name);
    write('Gender? '); readln(j);  R.isMale:=j>=0;
    write('Grades? ');  for j:=1 to 6 do read(R.grades[J]);  writeln;
  end;
  for I:=1 to N do begin
    R:=Table[I];
    write(I,' ', R.Name,' ',R.isMale);
  end;

When I enter info about first person it works fine, but then every other person's name input is skipped (output is "Name? Gender? ). If I switch entering boolean and string, code works correct, but that's not a logic order. Why is this happening?

  • Change `Read()` to `ReadLn()` when you ask for `Grades`. Reason is that the `CR LF` in the input buffer is not removed by `Read()`, so, it is seen by the the next `ReadLn()`which therefore returns immediately (when asking for next name). – Tom Brunberg Oct 07 '18 at 08:07
  • See [this](https://stackoverflow.com/a/48112264/2292722) for explanation – Tom Brunberg Oct 07 '18 at 08:12
  • 1
    Surely you mean to assign the value of ´R´ to the table array at the end of the first loop. – LU RD Oct 07 '18 at 08:30
  • There are some habits you need to get into: a) using the debugger for your Pascal implementation; b) putting each statement on its own line (makes using the debugger easier); c) using meaningful variable names, not just single-letter ones, even if it involves more typing; d) using dynamic arrays if your Pascal supports them; e) learning flow control so that you dont' force the user to perform a fixed number of operations when they might prefer to do fewer; f) using numeric constants rather than hard-coded numbers. TBC – MartynA Oct 07 '18 at 08:40

1 Answers1

1

At the end of the loop, you should assign the record to the array. Note that, unlike with classes, assigning a record copies the data in the record, it does not reference the record. So instead of what you have, rather do:

for I := 1 to N do 
begin
  //write('Gender?'); readln(j); R.isMale:=j>=0; <= This works just fine
  write('Name? ');  
  readln(R.Name);
  write('Gender? '); 
  readln(j);  
  R.isMale := j >= 0;
  write('Grades? ');
  for j := 1 to 5 do 
    read(R.grades[J]);
  readln(R.grades[6]); // readln reads the end-of-line too.
  writeln;
  Table[I] := R; // copy the data from R into the table
end;

That way, the data from the record R is copied into the table. There is no need to copy R from the table at the beginning of the loop, as the table is empty anyway.

Unlike with classes, with records like this, you could do the following too:

  write('Name? ');
  readln(Table[I].Name);
  write('Gender? '); 
  readln(j);  
  Table[I].isMale := j >= 0;
  // etc...

And in the final loop:

  Writeln(I, ' ', Table[I].Name, ' ', Table[I].IsMale);

without using R at all.

Rudy Velthuis
  • 28,387
  • 5
  • 46
  • 94
  • FWIW, for `Gender`, you might consider reading a `Char`, and converting that to a `Boolean`: `'M'` and `'m'` convert to `True` and `'F'` and `'f'` convert to `False`. For other characters you should ask again. You may even consider using an enumeration like `type TGender = (male, female, nonbinary);` etc. and use that in your record instead. `'N'` and `'n'` could translate to non-binary. – Rudy Velthuis Oct 07 '18 at 13:05