Reputation: 1188
Firstly, I know I'm going to get shouted at for using obsolete Delphi methods, but It was the way I was taught and I'm just practicing these things for an exam coming up.
Anyway, I'm reading a bunch of names via a textfile into an array. The user then has the option to search for a name in the text file, and it will either return that the name is there, or isn't.
Here's the code:
procedure TForm1.btnSearchClick(Sender: TObject);
var
myFile : TextFile;
Search : string;
k : Integer;
arrNames : array [1..200] of string;
bFound : Boolean;
begin
AssignFile (myFile, 'names.txt');
reset(myFile);
Search := UpperCase(InputBox('Search a Name', '', 'Tiffani Bressler'));
k := 1;
bFound := False;
while not Eof(myFile) or bFound = False do begin
Readln(myFile, arrNames[k]);
if Search = UpperCase(arrNames[k]) then
begin
bFound := true;
end;
lblLineSearched.Caption := 'Line searched: ' + IntToStr(k);
inc(k);
end;
if bFound = True then
ShowMessage('You searched for: ' + Search + ' and it was found on line: ' + IntToStr(k))
else ShowMessage('You searched for: ' + Search + ' and it was not found');
CloseFile(myFile);
end;
The problem is as soon as I press the search button (i directly copy a name from the text file itself), i get the message saying Name not found
.
What am I doing wrong?
edit: Where I put the 'LabelSearched', that doesn't even change after i have searched.
Upvotes: 0
Views: 172
Reputation: 612964
The logical expression is wrong. The equality test is binding to the whole expression. It's the same as
((not Eof(myFile)) or bFound) = False
Learn about this by studying the table of operator precedence. Note that =
has lower precedence than the other operators in this expression. And that not
has higher preference than or
which is why I added the parens around not Eof()
.
Since Eof
returns False
this test always fails and the body of the while
loop is never entered. You mean
not Eof(myFile) or (bFound = False)
But it is idiomatically poor to test booleans against true or false. So I'd do this like so:
not Eof(myFile) or not bFound
Even then that is still wrong. You need both conditions to be true to enter a new iteration. It's no good entering the loop body if Eof
returns true. So you need this condition:
not Eof(myFile) and not bFound
Personally I think I'd try to do without the bFound
local and use break
to escape from the loop, but that is perhaps more a matter of personal taste.
If you want to move on from legacy Pascal I/O then you might contemplate TStreamReader
. That will allow you to keep the same while
loop reading one line at a time.
I'm sure I've said this before, quite possibly to you, but your array is not only pointless and wasteful, but dangerous. You consider one line at a time. Use the same string
local variable to read each line. As it stands your code is bait for a buffer overrun error.
Ah yes, here's the question: Access of violation at address 00404094 with AssignFile(); Please review the answer you accepted to that question.
Upvotes: 6
Reputation: 951
It's not a direct answer to your question, but you can use another approach - a TStringList
.
Something like:
procedure Search(const aFileName: String; const aSearchString: String);
var
index: Integer;
sl: TStringList;
begin
sl := TStringList.Create;
try
sl.LoadFromFile(aFileName);
// case sensitive search
sl.CaseSensitive := True;
index := sl.IndexOf(aSearchString);
if index > -1 then
ShowMessage(Format('String found at line %d', [index + 1])) else
ShowMessage('String not found!');
finally
sl.Free;
end;
end;
Upvotes: 4