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?
x, y, z: Integer; ... ReadLn(fh, x, y, z); MessageBox(int2Str(y)); ...
y has a value, x and z are 0 ...
Note: This was edited after Mason Wheeler's entirely valid answer
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.
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.
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
z as well
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.
ReadLn? hmmm (from memory) Was it expecting one line for each variable??? Really don't remember...