StringList Question!

Ok i have a stringlist with eg 10 items..

I have a Integer Counter that it will
say what position will get from the
string list and put them on the 4 labels.

eg.
When the Counter = 1 then it will update the labels with the values from the first 4 items of the StringList

Label1.caption := Stringlist.Strings[0];
Label2.caption := Stringlist.Strings[1];
Label3.caption := Stringlist.Strings[2];
Label4.caption := Stringlist.Strings[3];

When the Counter = 2 then it will update the labels with the values from the second 4 items of the StringList

Label1.caption := Stringlist.Strings[4];
Label2.caption := Stringlist.Strings[5];
Label3.caption := Stringlist.Strings[6];
Label4.caption := Stringlist.Strings[7];

etc...

any ideas ?

tryed this but didn't worked when the
Counter >= 3  

Label1.caption := Stringlist.Strings[Counter * 2 -1];
Label2.caption := Stringlist.Strings[Counter * 2];
Label3.caption := Stringlist.Strings[Counter * 2 +1];
Label4.caption := Stringlist.Strings[Counter * 2 +2];

=-(

Thanx
LVL 2
k6__Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

k6__Author Commented:
Edited text of question.
0
philipleighsCommented:
Hi,

How about this small change. It assumes that Counter is zero based.


if Counter * 4 >= Stringlist.Count then
  raise Exception.Create('You need more items in the list.');
Label1.caption := Stringlist.Strings[Counter * 4];
Label2.caption := Stringlist.Strings[Counter * 4 + 1];
Label3.caption := Stringlist.Strings[Counter * 4 + 2];
Label4.caption := Stringlist.Strings[Counter * 4 + 3];


Cheers,
Phil.
0
scrapdogCommented:
If your Counter is 1 based then substitute (Counter - 1) everywhere you see "Counter" in philipleighs' code.
0
Cloud Class® Course: CompTIA Cloud+

The CompTIA Cloud+ Basic training course will teach you about cloud concepts and models, data storage, networking, and network infrastructure.

denizcanCommented:
Your code will work  for 3 but not more than 3, because it exceeds the count value of the StringList when Counter=4 and Counter * 2 + 2 = 10. Index values should be in the [0, Count -1] interval.
If your list has 10 items, so Count value is 10, than your index value should be lower than 10. If you add two more items to list, it will work for 4 also, but not 5.

if you explain with what algorithm your code should select the labels more than 3, I can correct your code...
0
scrapdogCommented:
>I can correct your code...

but philipleighs already did that
0
scrapdogCommented:
please read the comment history before you post as an answer
0
denizcanCommented:
I had already read the comment history, and what philipleighs wrote was not enough, it would not work when even the Counter is 3!!!!

Pls, interpret before sending a warning...
0
Fatman121898Commented:
I have an idea, but let me examine it.
Jo.
0
philipleighsCommented:
>>
it would not work when even the Counter is 3!!!!
<<

Actually it will raise an exception saying 'You need more items in the list' if Counter is three.
This is obviously intentional.

You need to look a little closer.
0
denizcanCommented:
What philipleighs did is not different than what TStringList does. TStringList also compares the Index value with Count value and raises exception. So the code

if Counter * 4 >= Stringlist.Count then
  raise Exception.Create('You need more
items in the list.');

is unnecessary...

Raising exception does not mean that the code works... Exceptions are used to debug the code...

I think, k6 needed to know why some exception messages were seen. What philipleighs did is only changing the exception message...

I had looked closer..
0
k6__Author Commented:
as i said i have a string list
with EG. 10 items.. it may have 200 or
324 or xxx items.. what i want is to
split it into Sections which each
section will contain eg 4 or 5 or x items... so i can easy get the items
of the section depending the counter.

eg if the counter is 1 then it will
get the first Section which contains
4 stringlist items..

First Section :
(StringList.Strings[0],  
 StringList.Strings[1],
 StringList.Strings[2]
 StringList.Strings[3])

2nd Section :
(StringList.Strings[4],  
 StringList.Strings[5],
 StringList.Strings[6]
 StringList.Strings[7])

3rd Section :
(StringList.Strings[8],  
 StringList.Strings[9])

0
denizcanCommented:
than what we discussed until now is nonsense :)

var
  Section: Integer;
  Index: Integer;
  Count: Integer;
begin
  Index := (Section - 1) * 4;
  Count := StringList.Count;

  if Index < Count then Label1.Caption := StringList[Index] else Label1.Caption := '';

  Inc(Index);
  if Index < Count then Label2.Caption := StringList[Index] else Label2.Caption := '';

  Inc(Index);
  if Index < Count then Label3.Caption := StringList[Index] else Label1.Caption := '';

  Inc(Index);
  if Index < Count then Label4.Caption := StringList[Index] else Label4.Caption := '';

....

no exceptions or annoying messages...

Section starts from 1...

I use Count variable instead using StringList.Count to optimize the code, letter creates more code...

And use Inc Index Index + xxx, to avoid compiler to add-up each time some value to Index twice...

there is an alternative way  based on tag values which is more convenient.
0
philipleighsCommented:
k6, check out the code at the bottom.

>>
You need to look a little closer.
<<

Hi Deniz, I was just being cheeky! ;-)

You say:
>>
Raising exception does not mean that the code works... Exceptions are used to debug the code...
<<
I don't agree with this at all. It that were so, then why would a function like ForceDirectories (and many many others) raise an exception if it failed. Surely it's not for debugging purposes. The main reason for it is that it relieves the programmer from checking the return value of every call.

Instead of

>>>
if not fileopen then
  result = false;  
  exit

if not fileread then
  closefile
  result = false;  
  exit

if not fileread then
  closefile
  result = false;  
  exit

fileclose
result = true  
<<<

You can have

>>>
fileopen
try
  fileread
  fileread
finally
  fileclose
end;
<<<

The caller would look like
>>>
if not ReadFileFunction then
  ShowError("Can't read file");
<<<

and

>>>
try
  ReadFileFunction
except
  ShowError("Can't read file");
end;
<<<

Program in C for a while and you'll appreciate exception handling.




OK k6, here's what I've got for you.

Have fun,

Cheers,
Phil.


function GetSectionItems(Strings: TStringList; SectionNumber: Integer; var a, b, c, d: string): Boolean;
begin
if SectionNumber * 4 >= Stringlist.Count then
  begin
    //Just for Deniz!  ;-)
    Result := false;
  end
else
  begin
    a := Stringlist.Strings[(SectionNumber - 1) * 4];
    b := Stringlist.Strings[(SectionNumber - 1) * 4 + 1];
    c := Stringlist.Strings[(SectionNumber - 1) * 4 + 2];
    d := Stringlist.Strings[(SectionNumber - 1) * 4 + 3];
    Result := true;
  end;
end;

Cheers,
Phil.
0
k6__Author Commented:
Well i found it! here it is :

 Var
  Counter,
  Counter2,
  Counter3,
  MyVar    : Integer;
 Begin
  Counter2 := 0; Counter3 := 0; MyVar := 2;
  For Counter := 0 To MyStringList.Count -1 Do
   Begin
    Inc(Counter2);
    If Counter2 = 4 Then
     Begin
      Counter2 := 0;
      Inc(Counter3);
      If Counter3 = MyVar Then
       Begin
        L01.Caption := MyStringList.Strings[Counter -3];
        L02.Caption := MyStringList.Strings[Counter -2];
        L03.Caption := MyStringList.Strings[Counter -1];
        L04.Caption := MyStringList.Strings[Counter];
       End;
     End;
   End;
 End;

So If i have a Multiple of 4 i wont have
any exceptions if it isn't then i have..
in this case i add TRY before LXX := MyStringLis.Strings[Counter -X] and
EXCEPT END; after it to avoid
error messages =)

SOOOO is there anything to optimize it or a better algorithm ?

Thanx!
0
k6__Author Commented:
Denizcan you code worked and it's well
optimized =))))) post it!!!

Thanx!
0
k6__Author Commented:
philipleighs you code won't work
if the last section contain items below
4 =(.
0
Fatman121898Commented:
How about this:

procedure TForm1.ShowItems(var OutSL:TStringList;GroupNumber:Integer);
  const GroupSize=4;
  var InSL:TStringList;
      I:Integer;
begin
  InSL:=TStringList.Create;
  InSL.Clear;
  for I:=0 to GroupSize-1 do
    if (GroupNumber-1)*GroupSize+I<=OutSL.Count-1
      then  InSL.Add(OutSL.Strings[(GroupNumber-1)*GroupSize+I])
      else  InSL.Add('');
  Label1.Caption:=InSL[0];
  Label2.Caption:=InSL[1];
  Label3.Caption:=InSL[2];
  Label4.Caption:=InSL[3];
  InSL.Free;
end;


I've tested it, wokrs good.
Jo.
0
denizcanCommented:
thanx k6

philipleighs, I do not need to work C a little...

In the past Microsoft had lots of problems with its codes. Then one of the maneger developed an error debugging tool. They used Assert macro to show exceptions...

I know sometimes exceptions can be used to show the user some msg. But they are usually for the programmers not users.

Example:
What does "Index out of range" mean for a user?

Instead a showing an exception message to user, I try to avoid them causing exceptions... Which one is better?

Example:
Think about an editor, which takes some values from a list, if the list is empty or nothing is selected in the list, I disable the editor...

thanx philipleighs, for discussion...
0
florisbCommented:
reading the comment history I read somebody say... ... a bit too much I think. Isn't it just a simple mathematical trick:

function FillLabels(counter:integer) : boolean;
var
addToIndex,x : integer;
begin
addToIndex := (counter -1) * 4; //1->0, 2->4, 3->8, 4->12, et cetera.
try
Label1.caption := Stringlist.Strings[0+addToIndex];
Label2.caption := Stringlist.Strings[1+addToIndex];
Label3.caption := Stringlist.Strings[2+addToIndex];
Label4.caption := Stringlist.Strings[3+addToIndex];
result := true;
except
  begin
  showMessage('Out of index');
  result := false;
  end;
end; //try
end;
0
florisbCommented:
And greetings offcourse,
Floris.

(hope I didn;t get the question wrond...;-)
0
rickpetCommented:
Ok guys where making this harder than it needs to be...


type
  TForm1 = class(TForm)
    Button1: TButton;
    ListBox1: TListBox;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }

  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}
type
  TMyRange = 0..9;
  TMySetRange = set of TMyRange;
var
  Counter: integer;
const
  Section1 = [0..3];
  Section2 = [4..7];
  Section3 = [8..9];

procedure TForm1.Button1Click(Sender: TObject);
var
  i: integer;
function FindIndex(aSection: TMySetRange): integer;
var
  tmpSection: TMySetRange;
  i: integer;
begin
  tmpSection := aSection;
  for i:= low(TMyRange) to high(TMyRange) do
  begin
    if i in tmpSection then
      break;
  end;
  Result := i;
end;
begin

  Case Counter of
    0:  i:= FindIndex(Section1);
    1:  i:= FindIndex(Section2);
    2:  i:= FindIndex(Section3);
    else
      Counter := 0;
  end;
  if i < ListBox1.Items.Count then
    Label1.Caption := ListBox1.Items[i];
  if i+1 < ListBox1.Items.Count then
    Label2.Caption := ListBox1.Items[i+1];
  if i+2 < ListBox1.Items.Count then
    Label3.Caption := ListBox1.Items[i+2];
  if i+3 < ListBox1.Items.Count then
    Label4.Caption := ListBox1.Items[i+3];
  inc(Counter);
end;

end.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
rickpetCommented:
change
else  
 Counter := 0;
to...

else  
 Counter := -1;

Rick
0
rickpetCommented:
hehe better way...

  Case Counter of
    0:  i:= FindIndex(Section1);
    1:  i:= FindIndex(Section2);
    2:  i:= FindIndex(Section3);
  end;
  if i < ListBox1.Items.Count then
    Label1.Caption := ListBox1.Items[i];
  if i+1 < ListBox1.Items.Count then
    Label2.Caption := ListBox1.Items[i+1];
  if i+2 < ListBox1.Items.Count then
    Label3.Caption := ListBox1.Items[i+2];
  if i+3 < ListBox1.Items.Count then
    Label4.Caption := ListBox1.Items[i+3];

  if Counter < 2 then
    inc(Counter)
  else
    Counter := 0;
0
Fatman121898Commented:
k6,

did you ever read what I've posted ?
In my opinion it was the best solution of the problem. And most compact - no "case", just one "if".
But you are the judge, so you decide...

Jo.
0
scrapdogCommented:
>But they are usually for the programmers not users.

The assumption that "all users are idiots" is a very good one.  And sometimes (no, always) there will be a user that is dumber than your intelligence (as a programmer), or your program's intelligence, could have possibly fathomed.  Catching exceptions is a relatively good way to mitigate the possible damage.  In some cases it will be even more efficient to use exception catching than to check for yourself...why reinvent the wheel in these cases?
0
rickpetCommented:
Jo...

I think part of the problem with your solution is that if the numbers change he has to refigure

addToIndex := (counter -1) * 4; //1->0, 2->4, 3->8, 4->12, et

What happens if say...he find that in Section1 he only wants 3 labels, but in Section 2 he wants 5 labels updated...and Section 3 he wants 2...my solution works...it will in the future easier to implement and allow other programmers to change.

Yes right now yours does what it needs to..but it is very rigid and will break with any tinkering and will then have to be scrapped.  Working with sets is very intuitive and scales very well...

just my 2cents

Rick

0
florisbCommented:
yeah, stop hiding; K6 and say something.....:-)

Or do we all have to defend outselves (fatman....:-)

F-)
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.