Brendan
Brendan

Reputation: 19393

Why does ReadLn not assign values to all my variables in Delphi?

When using Delphi's ReadLn to read values from a tab-delimited file into a series of variables, why do some of the variables not get assigned to appropriate value when I step through the debugger?

i.e.


x, y, z: Integer;
...
ReadLn(fh, x, y, z);
MessageBox(int2Str(y));
...

Only y has a value, x and z are 0 ...

Note: This was edited after Mason Wheeler's entirely valid answer

Upvotes: 3

Views: 1063

Answers (4)

Wim ten Brink
Wim ten Brink

Reputation: 26682

The use of ReadLn() is unreliable in this example, because it will read to the first whitespace, add this to the first number, then to the second whitespace, add that, etc. You're doing a ReadLn, thus anything beyond the third integer on that line is ignored! And missing values default to zero.

If your numbers are prefixed with spaces, X would be the space, thus zero. Y would be the first number up to the tab delimiter. Z would be the second space in front of the second number, thus default zero.

To be honest, I only use ReadLn() to read a whole string from a textfile. With tab-delimited types I tend to use all kinds of other techniques, including using a stringlist.

Upvotes: 1

Brendan
Brendan

Reputation: 19393

This is a symptom of a more general gotcha, in particular trying to debug the values of unused variables.

In Short: By default, the compiler optimises away unused variables

If when writing code incrementally, you decide to debug and find out, say, that the ReadLn procedure is reading in the variables correctly, you may find that the values are empty or 0. Unless the variables are used later in the code - which may not be the case if you are debugging as you write each line - the compiler appears to optimise them away.

I used ReadLn in the example since it may well be that you want to use data in the second column of a csv file and so have to create various throwaway variables that are not used. When checking the values of the throwaway variables, you then find that they do not contain what you expect!

In the above example you can force the debugger to load the vlaues by simply 'using' the variables later in the code, i.e.


x, y, z: Integer;
...
ReadLn(fh, x, y, z);
MessageBox(int2Str(y));
MessageBox(int2Str(x));
MessageBox(int2Str(z));
...

Now, mousover will reveal the values of y and z as well

Upvotes: 1

Mason Wheeler
Mason Wheeler

Reputation: 84630

Readln will parse input as well as it can for the variable types you give it, but if your first one (name) is a string, it'll read everything up to the linebreak. If you want to load in a tab-delimited file, I'd use a TStringList and set the delimiter character to #9.

Upvotes: 5

Fabricio Araujo
Fabricio Araujo

Reputation: 3820

ReadLn? hmmm (from memory) Was it expecting one line for each variable??? Really don't remember...

Upvotes: 0

Related Questions