Solved

StringList Problem! Please help!

Posted on 2001-07-23
34
356 Views
Last Modified: 2010-04-06
Hi! I seem to have a problem with the following code. I always get an "Out of Bounds" error. I don't know why it does that. Can someone help me out. Thanks!

procedure TForm1.Button1Click(Sender: TObject);
var
  i: Integer;
  S: TStringList;
  Del: TListItem;
  DelIndex: String;
begin
  if ListView1.Selected = nil then
    Exit;

  S := TStringList.Create;
  Del:= ListView1.Selected;

  try
    S.LoadFromFile(SaveDir + 'Tools.txt');
  except
    S.Free;
    Exit;
  end;

  while Del <> nil do
    begin
      with ListView1 do
        begin
          for i := 0 to S.Count - 1 do
            begin
              if S.Strings[i] = (Selected.Caption + '=' + Selected.SubItems[i]) then
                begin
                  DelIndex := S.Strings[i];
                  S.Delete(S.IndexOf(DelIndex));
                end;
            end;

          Items.Delete(Items.IndexOf(Del));
        end;

      Del:= ListView1.GetNextItem(nil, sdAll, [isSelected]);
    end;

  S.SaveToFile(SaveDir + 'Tools.txt');
  S.Free;
end;
0
Comment
Question by:New2Delphi
  • 12
  • 11
  • 5
  • +3
34 Comments
 
LVL 5

Expert Comment

by:scrapdog
ID: 6310630
You are iterating through the StringList and deleting items from it in the same loop.

"S.Count - 1" in the for loop is evaluated at the beginning of the loop, not for every iteration.

If you want to reevaluate on every iteration (because S.Count changes after a delete), then use a "while" loop instead of a for loop.
0
 
LVL 5

Accepted Solution

by:
scrapdog earned 30 total points
ID: 6310638
i := 0;
while (i < S.Count) do
begin
    if S.Strings[i] = (Selected.Caption + '=' + Selected.SubItems[i]) then
    begin
        DelIndex := S.Strings[i];
        S.Delete(S.IndexOf(DelIndex));
    end;
    Inc(i);
end;
0
 
LVL 14

Expert Comment

by:DragonSlayer
ID: 6310655
or do it from bottom:

for i := S.Count - 1 downto 0 do
  S.Delete(i);

0
Courses: Start Training Online With Pros, Today

Brush up on the basics or master the advanced techniques required to earn essential industry certifications, with Courses. Enroll in a course and start learning today. Training topics range from Android App Dev to the Xen Virtualization Platform.

 

Expert Comment

by:d32coder
ID: 6310914
You should also only have S.Free; in one place (at the end).  This will help prevent an access to a stringlist that no longer exists.  

Dragon is right, loop backwards.



procedure
var .....
begin

if filexists(savedir+fiename) then
 begin
 loadfromfile(savedir+fiename)
 
 // loop here

 end;
 
 S.Free;
end;
0
 
LVL 5

Expert Comment

by:scrapdog
ID: 6310933
As long as we're talking about S.Free

try
   S.LoadFromFile(SaveDir + 'Tools.txt');
 except
   S.Free;
   Exit;
 end;


You should probably use try..finally instead of try..except.  Place the "try" before the S.LoadFromFile, and the "finally" right after S.SaveToFile.

It is not a good idea to call Exit in an exception handler;  it is better to call "raise".  (You wouldn't need to do that when you use finally).
0
 
LVL 1

Expert Comment

by:h_mohsenian
ID: 6311312
hello,

i think error msg ( index out of bound ) is not for <S> ( as a StringList ) . it is for <Selected.SubItems[i]>. ( although it can be for S , if just tools.txt was empty ).

this becouse of that the selected Item has not a SubItem. if the selected item has it . there is not eny error msg!

that is better he write :

if Selected.SubItems.Count <> 0 then
...
...
...

best regards
hamed
0
 
LVL 1

Expert Comment

by:h_mohsenian
ID: 6311326
Selected.Subitems.count must be equal to S.Count ( at least )
0
 

Author Comment

by:New2Delphi
ID: 6320729
Hmmm... what if I want to edit a string in the list? What procedure should I use?
0
 
LVL 14

Expert Comment

by:DragonSlayer
ID: 6320841
You mean string in the StringList?

e.g. You want to change value for String #3:

var
  MyString: string;
begin
  MyString := StringList.Strings[2];
  if InputQuery('StringList', 'Enter new value',
    MyString) then
    StringList.Strings[2] := MyString;
...



0
 
LVL 1

Expert Comment

by:h_mohsenian
ID: 6321159
Edit a String at StringList or Edit(add) a child as Subitem? although there is not so difference.(i think DragonSlayer comment is good)

what is ur idea about my last comment? do u agree with me?

hamed ;-)
0
 

Author Comment

by:New2Delphi
ID: 6324896
DragonSlayer's comment about doing it from bottom worked fine.

Now I have a problem with editing. See what my program does is take website addresses from a textfile, load it into a TStringList and then load the data into a TListView. Now if I want to edit, add or delete it, I just go back to the StringList and do the neccessary function on it. The code I posted was the function to delete an item from the TStringList. It compares the item in the TStringList with the selected item of the TListView and if they are the same, it deletes it from the TStringList and TListView. Also, the code I posted had a typo. Selected.SubItems[i] should be Selected.SubItems[0] since I only have one sub-item.

Anyway, when editing, what I want to do is load the item from my TListView onto 2 Edit boxes, edit the data from there, and then update the TStringList. Is this possible? Can you please post sample code for this. Thanks!
0
 

Author Comment

by:New2Delphi
ID: 6328645
Please help me.
0
 
LVL 1

Expert Comment

by:h_mohsenian
ID: 6329524
I think I found your mistake :

when u delete one string from S then Count decrese one, there fore u must refresh the for loop ( becouse if u not i passes end of Items of S )

now this is the corrected code :

 while Del <> nil do
   begin
     with ListView1 do
       begin
        ExitCode := False;

         while not Exitcode do
         begin
         ExitCode := True;
         for i := 0 to S.Count - 1 do
           begin
             if S.Strings[i] = (Selected.Caption + '=' + Selected.SubItems[0]) then
               begin
                 DelIndex := S.Strings[i];
                 S.Delete(S.IndexOf(DelIndex));
                 ExitCode := False;
                 break;
               end;
           end; // for
         end; // while

         Items.Delete(Items.IndexOf(Del));
       end;

     Del:= ListView1.GetNextItem(nil, sdAll, [isSelected]);
   end;

after each delete i refresh the for loop

best regards
hamed
0
 
LVL 1

Expert Comment

by:h_mohsenian
ID: 6331794
New2Delphi , are you here. Could last code solve your problem ? ;-)
0
 

Author Comment

by:New2Delphi
ID: 6336843
Hi! When editing, what I want to do is load the selected item from my TListView onto 2 Edit boxes, edit the
data from there, and then update the TStringList. Is this possible? Can you please post sample code
for this. Thanks!
0
 
LVL 1

Expert Comment

by:h_mohsenian
ID: 6337163
hi New2Delphi , how are you?

lets do step by step ( I am not shur i understand exactly that u want ) :

1. u want load selected item from TListView to 2 Edit Boxes.

Edit1.Text := Selected.Caption;
Edit2.Text := Selected.Caption;

i think u mean u want to load subitem to another EditBox.then :

Edit1.Text := Selected.Caption;
Edit2.Text := Selected.Selected.SubItems[0];

2.now you can Edit them in Edit Boxes

3.at the end you want to Update your TStringList ( I guess you mean <S> witch is a TStringList ):


if S.Strings[i] = (Edit1.Text + '=' + Edit2.Text) then
              begin
                DelIndex := S.Strings[i];
                S.Delete(S.IndexOf(DelIndex));
                ExitCode := False;
                break;
              end;
         

I think your goal is stile not so clear for me. is that 3 step usefull your u.

I think that is better we use a real time communication . chat is a good way but i have not ICQ. just I have Yahoomessanger in my computer . also i have not ID in that ( Yaho... used by my brother and he is not here know ) if you know a easy chat room ( that means we dont need any package for use it ) please tell me . we will design the time and will use that chatroom.

i think by chat room you can find your need very rapidly.

also other experts can attach us on that chat room.

best regards
hamed

















sorry, but i can not understand what u say! please tell me clearer. lets do step by step.

1. can it solve your last problem. that means is it stile related to that error message or not ?

2. if it is a new problem please repeat the question. with code and exactly point to line that you have problem!

3. I can not see where is your editing code! in your last codes.

best regards
hamed

0
 
LVL 1

Expert Comment

by:h_mohsenian
ID: 6337167
the text in the end is the last version of my comment. i wanted to send it becouse i can not understand what is your need. but read it again and write my main comment that you can read in start.

best regards
hamed
0
 

Author Comment

by:New2Delphi
ID: 6339162
hamed, sorry if I don't make any sense. Anyway, deleting from the StringList is not a problem anymore. My problem is editing a string from the StringList. I do not have sample code because I don't know if this is possible.

What my program does is load the contents of the StringList to a ListView. When I want to edit a string I load it from the ListView into 2 edit boxes:

Edit1.Text := Selected.Caption;
Edit2.Text := Selected.Selected.SubItems[0];

And then I edit it as necessary. Now, when I click on the "Save" button what I want to do is save the edited string back to the StringList so that the old string will be replaced with the edited one? Can this be done? Can you post code that will allow me to do this? Thanks!
0
 

Author Comment

by:New2Delphi
ID: 6339189
hamed, sorry if I don't make any sense. Anyway, deleting from the StringList is not a problem anymore. My problem is editing a string from the StringList. I do not have sample code because I don't know if this is possible.

What my program does is load the contents of the StringList to a ListView. When I want to edit a string I load it from the ListView into 2 edit boxes:

Edit1.Text := Selected.Caption;
Edit2.Text := Selected.Selected.SubItems[0];

And then I edit it as necessary. Now, when I click on the "Save" button what I want to do is save the edited string back to the StringList so that the old string will be replaced with the edited one? Can this be done? Can you post code that will allow me to do this? Thanks!
0
 
LVL 1

Expert Comment

by:h_mohsenian
ID: 6339469
is it mean you want to save S ( as StringList ) to the original txt file ?

that means :

1. you load S from txt file
2. Edit S ( as StringList ) in any way that u want
3. restore S to txt file by save button

now u can do step 1, and step 2. is ur problem to do step 3. that mean u want to know how u can store again the Updated S to the txt file?

best regards
hamed
0
 

Author Comment

by:New2Delphi
ID: 6339620
Yes! That is exactly my problem. Can you help me?
0
 
LVL 14

Expert Comment

by:DragonSlayer
ID: 6339813
S.SaveToFile(FileName);
0
 
LVL 1

Expert Comment

by:h_mohsenian
ID: 6340949
oh, he was so faster than me .like Loadfromfile you can use Savetofile.

best regards
hamed
0
 

Author Comment

by:New2Delphi
ID: 6343059
Yes, I know you have to save it to file. What I want to know is if the edited string will be saved with the same index number and if not, can you specify waht code I can use to do so. Thanks!

e.g.

If the original string is Test12=1234567 with an index of 3 and I change it to Test13=4567890 if I save it will it still be in the same index number?
0
 
LVL 14

Expert Comment

by:DragonSlayer
ID: 6343123
if you changed it using S.Strings[3] := 'Test13=4567890' then it will be saved with the same index number, IF you did not sort it.
0
 

Author Comment

by:New2Delphi
ID: 6343363
What if it's S.Strings[i] since I do not know for sure what the index is?
0
 
LVL 14

Expert Comment

by:DragonSlayer
ID: 6343496
e.g.

Edit1.Text := S.Strings[i];
// some editing
// value of i did not change
S.Strings[i] := Edit1.Text

will be fine
0
 
LVL 1

Expert Comment

by:h_mohsenian
ID: 6345244
i am stile mixture! ;-) the savetofile method save S in .txt file in the same order of its item . now do you wont for example save .txt file with sorted form? like this
Test1 = ...
Test2 = ...
Test3 = ...
Test4 = ...
..
.

after change. if u want it . you must at first Set S before saveing and when S updated in your need form you can use savetofile.

if it is your problem i think you can use sort Items in S. or somthing like this!

if i am still in wrong way please tell me ! dont worry about our time we are here to help each other .

best regards
hamed
0
 
LVL 1

Expert Comment

by:h_mohsenian
ID: 6353790
New2Delphi,what was happened? ;-) maybe you become tired becouse we can not understand all your your problems  exactly! :-( . if you want send me your App, email address : h_mohsenian@yahoo.com & mohsenianrad@scribe.com and discribe your problem with code. also if you want tell me more about yourself . I saw your profile , but there were not any thing about you!

Best regards
Hamed
0
 

Author Comment

by:New2Delphi
ID: 6362556
I'll post the results tomorrow. :-)
0
 
LVL 1

Expert Comment

by:h_mohsenian
ID: 6362726
ok! ;-) but witch results? do you talk about your code ? , your profile ? or ... ?  :-)

good coding
hamed
0
 

Author Comment

by:New2Delphi
ID: 6367317
Yes, the code I use.
0
 
LVL 26

Expert Comment

by:Russell Libby
ID: 8711400
No comment has been added lately, so it's time to clean up this TA.
I will leave a recommendation in the Cleanup topic area that this question is:

Accept scrapdog's comment as answer

Note:
This recommendation is based on the "original" question asked, and the points offered does not warrant a split. My apologies to the other experts.

Please leave any comments here within the next seven days.
 
PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!
 
Thank you,
Russell

EE Cleanup Volunteer
0

Featured Post

Courses: Start Training Online With Pros, Today

Brush up on the basics or master the advanced techniques required to earn essential industry certifications, with Courses. Enroll in a course and start learning today. Training topics range from Android App Dev to the Xen Virtualization Platform.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
proper way to parse text with delphi 7 120
Delphi XE2 application frozen on Windows 10 10 310
FMX StringGrid1->Canvas->FillRect Problem 3 150
Find and Replace Stream with 0s 8 62
Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
This Micro Tutorial will give you a basic overview how to record your screen with Microsoft Expression Encoder. This program is still free and open for the public to download. This will be demonstrated using Microsoft Expression Encoder 4.
Along with being a a promotional video for my three-day Annielytics Dashboard Seminor, this Micro Tutorial is an intro to Google Analytics API data.

785 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question