Link to home
Start Free TrialLog in
Avatar of krydea
krydea

asked on

string problem (?easy?)

hi all,
i have a problem with some string's.
can someone help me?
the problem is:
i have a string like:"blabla=blabklajb?kehvvkjnse?kujsrnfkjsn?bndjblabla"
how can i set the string in a arry of max 7 words
so
arry 1 = blabla
arry 2 = blabklajb
arry 3 = kehvvkjnse
etc.
(mabye we can call the arry words or somthing...)
can someone help me out?

carlas smith

PS:i use borland delphi 5
Avatar of CrazyOne
CrazyOne
Flag of United States of America image

const
 sArray: array[0..6] of string = ('a', 'b', 'c', 'd', 'e', 'f', 'g');
or
var
sArray: array[0..6] of string;

begin

sArray[0] := 'a';
sArray[1] := 'b';
sArray[2] := 'c';
or
var
sArray: array of string;

begin

SetLength(sArray, 7);

sArray[0] := 'a';
sArray[1] := 'b';
sArray[2] := 'c';

Avatar of DrDelphi
DrDelphi

OR... you could use a TStringList with a Capacity of 7....

<g>

Good luck!!
DrDelphi
Good suggetion. I tend to forget about TStringList which is weird because I lean on it a lot. :>)
I'm not exactly certain what you need... but if you simply want to place any string into an array
of 7 elements... without regard to where the string is broken... then something like this will do it..
it's not optimal but is best I could come up with in 5 minutes :-)   I tried to keep the 7 elements as close to
the same size as possible...

procedure TForm1.Button1Click(Sender: TObject);
var
arry: array[1..7] of string;
MyString: string;
MyStrLength,a,b: integer;
begin
  MyString := 'blabla=blabklajb?kehvvkjnse?kujsrnfkjsn?bndjblabla';
  MyStrLength := length(MyString);

  If MyStrLength < 7 Then
    begin
    ShowMessage('MyString must be at least 7 characters in length!');
    exit;
    end;
   b := 1;
   a := MyStrLength div 7;
   //showmessage(IntToStr(a));
   arry[1] := Copy(MyString,1,a);
   arry[2] := Copy(MyString,a+1,a);
   arry[3] := Copy(MyString,2*a+1,a);
   arry[4] := Copy(MyString,3*a+1,a);
   arry[5] := Copy(MyString,4*a+1,a);
   arry[6] := Copy(MyString,5*a+1,a);
   arry[7] := Copy(MyString,5*a+5,length(MyString));
   showmessage(arry[1]+'  '+arry[2]+'  '+arry[3]+'  '+arry[4]+'  '
     +arry[5]+'  '+arry[6]+'  '+ arry[7]);

end;

oops.. I left some debug code in the source...
you can remove the variable b and the lines

b := 1;

 //showmessage(IntToStr(a));

<G>wen
Try this. It will cut your string apart at the "?" and put it in a memo, or you could create a string list.

procedure TForm1.Button1Click(Sender: TObject);
var
  S1,S2 : String;
  I : Integer;
begin
  S1 := 'blabklajb?kehvvkjnse?kujsrnfkjsn?bndjblabla';
  I := 1;
  Memo1.Clear;
  repeat
    S2 := '';
    while S1[I] <> '?' do
      begin
        S2 := S2 + S1[I];
        Inc(I);
      end;
      Memo1.Lines.Append(S2);
      Inc(I);
  until I > Length(S1);
disregard the source code above and look at this one... I made a silly typo error before..
this one is better :-)

procedure TForm1.Button1Click(Sender: TObject);
var
arry: array[1..7] of string;
MyString: string;
MyStrLength,a: integer;
begin
  MyString := 'blabla=blabklajb?kehvvkjnse?kujsrnfkjsn?bndjblabla';
  MyStrLength := length(MyString);

  If MyStrLength < 7 Then
    begin
      ShowMessage('MyString must be at least 7 characters in length!');
      exit;
    end;
  a := MyStrLength div 7;
  arry[1] := Copy(MyString,1,a);
  arry[2] := Copy(MyString,a+1,a);
  arry[3] := Copy(MyString,2*a+1,a);
  arry[4] := Copy(MyString,3*a+1,a);
  arry[5] := Copy(MyString,4*a+1,a);
  arry[6] := Copy(MyString,5*a+1,a);
  arry[7] := Copy(MyString,6*a+1,length(MyString));
  showmessage(arry[1]+'  '+arry[2]+'  '+arry[3]+'  '+arry[4]+'  '
  +arry[5]+'  '+arry[6]+'  '+ arry[7]);

end;
// a faster, simpler way to parse a string into a stringlist....
procedure TForm1.Button1Click(Sender: TObject);
var
 S:string;
 i:integer;
begin
  S:='blabla=blabklajb?kehvvkjnse?kujsrnfkjsn?bndjblabla';
  for i:=1 to length(S) do if S[i] in ['=','?'] then S[i]:=#10;
  with Memo1.Lines do begin
    BeginUpdate;
    Text:=S;
    while Count>7 do Delete(Count-1);
    EndUpdate;
  end;
end;
Avatar of krydea

ASKER

Gwena:
there can be more word's but there will be alway's 1'=' and max 5'?'
that make's 7 words;)
but how to do it if there are 4'?' or 3'?' etc.
do you understand my problem..?
is this posible and can you help?
Avatar of krydea

ASKER

(how to count the '?')
This will count the number of "?" and place the other seperate elements of the string into the a string list for later retrival. The "i" variable will be the count in this instance it will be 5.
 
var
  s1: string;
  i, iPos: Integer;
  sl: TStringList;
 
begin

  s1 := 'a?b?c?d?e?';
  i := 0;
  iPos := Pos('?', s1);
  sl := TStringList.Create;
  repeat
    Inc(i);
    sl.Add(Copy(s1, 1, iPos -1));
    System.Delete(s1, 1, iPos);
    iPos := Pos('?', s1);
  until iPos = 0;

end;

Be sure to free the StringList when it is no longer needed. Keep in mind System.Delete strips the variable down so if you need to refer back to the original string you could use a second variable(s2) to hold it. This is raw code so you will have to refine it for use in your code.
procedure TForm1.Button1Click(Sender: TObject);
var
 S:string;
 i:integer;
 QMarks:integer;
begin
  S:=Edit1.Text;
  QMarks:=0;
  for i:=1 to length(S) do if S[i]='?' then inc(QMarks);
  while QMarks>5 do begin
    while S[Length(S)]<>'?' do Delete(S,Length(S),1);
    Delete(S,Length(S),1);
    dec(QMarks)
  end;
  for i:=1 to length(S) do if S[i] in ['=','?'] then S[i]:=#10;
  Memo1.Lines.Text:=S;
end;
Avatar of krydea

ASKER

i whanted the arry so i could use if else if and else.
are is it posible to with a Stringlist etc. and how...please explane.
look in the delphi help file for TStringList "IndexOf" method,

quote
"Returns the position of a string in the list.
Call IndexOf to obtain the position of the first occurrence of the string"
unquote.

If you have not used it before it basically looks at the stringlist for a specific entry and if it exists it returns where it is in the list and if it does not exist than it returns -1.
IndexOf works well with   if---else    statements
Actually a string list is an array of sorts.
Ummm this line
>>>Actually a string list is an array of sorts

Should read
Actually a string list...in a way...is an array.
Ummm this line
>>>Actually a string list is an array of sorts

Should read
Actually a string list resembles an array.
Ummm this line
>>>Actually a string list is an array of sorts

Should read
Actually a string list...in a way...is an array.
Sorry for so many posts at one time. EE is playing tricks on me again.
Avatar of krydea

ASKER

CrazyOne:
does not matter but do you have a example of it..(with some explaning..please;))
Avatar of krydea

ASKER

if the point's are to low just say it...
Hi all,

I see a lot of activity in this thread :-)
I like an idea about TStringList, and easy (selftalking) sample is here:

......
var
  S: String; // initial string
  A: Array[0..6] of string; // result array
  I: Integer;
  L: TStringList;
begin

  S := 'one=two?three?four?five?six?seven?eight'; // initial string
  S := StringReplace(S, '?', ^M, [rfReplaceAll]); // replace "?" to CR
  S := StringReplace(S, '=', ^M, [rfReplaceAll]); // replace "=" to CR

  L := TStringList.Create;
  L.Text := S;
  // assign list items to array
  for I := 0 to 6 do
    if I < L.Count then
      A[I] := L[I] else  
      A[I] := ''; // clear rest of array if source string has less then 7 words
  L.Free;

  // ensure that it's works
  Caption := A[0]+'/'+A[1]+'/'.....;

....

Just my two cents.
----
Igor.
The easiest way to parse a string into parts is to use #10 as separator. In a form with a TListbox LB1, execute this:

procedure TForm1.ParseString;
const
  Str1 = 'This'#10'is'#10'a'#10'string';
begin
  LB1.Items.Text := Str1;
// Now LB1.Items[0] = 'This', LB1.Items[1] = 'is' etc.
end;
I already said that , belleson -
but I am glad you agree, thanks.
>> i whanted the arry so i could use if else if and else.
>> are is it posible to with a Stringlist etc. and how...please explane.

Could you give us an example and/or explanation of what you want to do?
Ok presuming you plugged in the code using all or some of the suggestions above and have populated the string list it is now time to evaluate it.

For the purpose of the following example lets say the string list is called slTheList.

if slTheList.IndexOf('a') <> -1 then
  ShowMessage('a was found')
else if slTheList.IndexOf('b') <> -1 then
  ShowMessage('b was found')
else if slTheList.IndexOf('c') <> -1 then
  ShowMessage('c was found')
else
  ShowMessage('Did not find it');

This is just a very simple example. There are various ways to approach this and through experimentaion you can do some real nifty things with the IndexOf method.

You can even treat the string list like an array by evaluating each ordinal positon, something like this

if (slTheList[0] = 'a') or (slTheList[1] = 'a')  then
  ShowMessage('a was found');

Again this is a very simple code but I hope it gives you an idea on how to approach it. Like I said there are a lot of different ways you can do this, it just takes time playing with it to find good useful ways to use it.

If you are still in need of assistance please...as Jeff_2 has stated...explain what exactly are you trying to do so we can narrow down the scope.
Avatar of krydea

ASKER

ok i have writen it in c++ and i whant to write it in delphi now if someone can c++ i gladly whant to show my source.


i will explane better here it is:

i got a string but i dont know how mutch '?' there in.
(i have to count it.)
counted there a 4 '?'(so there are in this case  1x '=' and 4x '?')
i have to set it in a string list appart line's word's (so i can use if and else to look what what is)
look if the thirst is 'bla' is it is then give a alert and the second 'blabla' etc.
is it clear now?

btw is it posible?
>> if someone can c++ i gladly whant to show my source.
  Please do!

>> i got a string but i dont know how mutch '?' there in.
  QMarks=0;
  for i:=1 to Length(S) do if S[i]='?' then inc(QMarks);


>> i have to set it in a string list appart line's word's
  for i:=1 to length(S) do if S[i] in ['=','?'] then S[i]:=#10;
  Memo1.Lines.Text:=S;

>> look if the thirst is 'bla' is it is then give a alert and the second 'blabla' etc.
  ???
is it clear now?
  No.

>> btw is it posible?
  Yes!!!
>> look if the thirst is 'bla' is it is then give a alert and the second 'blabla' etc.

Maybe like this?

const ValidStrings: Array[0..4] of string =
('blabla','blabklajb','kehvvkjnse','kujsrnfkjsn','bndjblabla') ;

procedure TForm1.Button4Click(Sender: TObject);
var i:integer;
begin
  for i:=0 to Memo1.Lines.Count-1 do begin
    if i>high(ValidStrings) then begin
     ShowMessage('Too many arguments!');
     BREAK;
    end;
    if Memo1.Lines[i]<>ValidStrings[i] then begin
    ShowMessage('Invalid argument('+IntToStr(i+1)+'):'+Memo1.Lines[i]);
    BREAK;
    end;
  end;
end;
Avatar of krydea

ASKER

ok here is it:
//--------------------------------------------------//
#include <string.h>
#include <stdio.h>
//--------------------------------------------------//

int getcommand(char *big_str,char words[7][4096])
{
   char *found_str;
   int count=0, i;

   if(found_str = strchr(big_str, '='))
   {
       strncpy(words[count],big_str,(size_t)(found_str - big_str));
       words[count][(found_str - big_str)]=0;
       big_str= found_str + 1;
       count++;

       while (found_str = strchr(big_str, '?'))
       {
           strncpy(words[count],big_str,(size_t)(found_str - big_str));
           words[count][(found_str - big_str)]=0;
           big_str= found_str + 1;
           count++;
           found_str = strchr(big_str, '?');
       }
       strcpy(words[count],big_str);
       count++;
   }

return count;
}

i can use if(strcmp(words[0],"HELLO") == 0 ) that is easy.
and how mutch words there are can i see later on the return.
very fast and simple.

is this posible in delphi to?
 
         
Avatar of krydea

ASKER

this it is:
1.look if there is a '=' else quit if it is make 1 word bevoor the =
2.count the '?' so i can how how mutch words there are(max 5)
3.and get the words bevoor the '?''s
4.get the last word behind '?'

Avatar of krydea

ASKER

please drop a example with some explaning
>> ok here is it:

type
  TWords=Array[0..7,0..4096] of Char;

function getcommand(big_str: pChar; var words: TWords): integer;
var
  i:integer;
  found_str:pChar;
const
  count:integer=0;
begin
  found_str:=StrScan(big_str, '=');
  if found_str<>nil then begin
    StrLCopy(words[count],big_str,LongInt(found_str - big_str));
    words[count][(found_str - big_str)]:=#0;
    big_str:= found_str + 1;
    inc(count);
    found_str:= StrScan(big_str, '?');
    while (found_str <> nil) do begin
      StrLCopy(words[count],big_str,LongInt(found_str - big_str));
      words[count][(found_str - big_str)]:=#0;
      big_str:= found_str + 1;
      inc(count);
      found_str:= StrScan(big_str, '?');
    end;
    strcopy(words[count],big_str);
    inc(count);
  end;
  Result:=count;
end;

// Test:
procedure TForm1.Button1Click(Sender: TObject);
var
  S:string;
  MyWords:TWords;
  i, N:integer;
begin
FillChar(MyWords,SizeOf(MyWords),'X');
S:='blabla=blabklajb?kehvvkjnse?kujsrnfkjsn?bndjblabla';
N:=getcommand(pChar(S),MyWords);
for i:=0 to N-1 do ShowMessage(StrPas(MyWords[i]));
end;
Avatar of krydea

ASKER

cool,
only 1 thing how can i compare MyWords with a string?
like this?:
if MyWords[0] = 'hello' then
begin
       ShowMessage('good morging');
end
else if MyWords[1] = 'cya' then
begin
       ShowMessage('bye');
end

or how?
(if you sayed that i will give you the point's)

You could build a translation table using the "Name=Value" pairs of a StringList...

procedure TForm1.Button1Click(Sender: TObject);
var
  S:string;
  MyWords:TWords;
  i, N:integer;
  TransTable:TStringList;
begin
  TransTable:=TStringList.Create;
  with TransTable do begin
    Add('hello=good morning');
    Add('yawn=good night');
    Add('noon=lunchtime');
    Add('howl=full moon');
    Add('cya=bye');
  end;
  S:='hello=yawn?noon?howl?cya';
  N:=getcommand(pChar(S),MyWords);
  for i:=0 to N-1 do ShowMessage(TransTable.Values[StrPas(MyWords[i])]);
end;
OOPS!
Don't forget to say:
  TransTable.Free;
at the end...
Avatar of krydea

ASKER

that i don't understand.
Avatar of krydea

ASKER

can't i use the if else statment?
procedure TForm1.Button1Click(Sender: TObject);
var
 S:string;
 MyWords:TWords;
 i, N:integer;
 TransTable:TStringList;
begin
 TransTable:=TStringList.Create;
 with TransTable do begin
   Add('hello=good morning');
   Add('yawn=good night');
   Add('noon=lunchtime');
   Add('howl=full moon');
   Add('cya=bye');
 end;
 S:='hello=yawn?noon?howl?cya';
 N:=getcommand(pChar(S),MyWords);
 for i:=0 to N-1 do ShowMessage(TransTable.Values[StrPas(MyWords[i])]);
 TransTable.Free; // <- Free the memory allocated to the StringList
end;
Yes, but you will end up with a LOT of if-then-else statements...
Using the Name=Value pairs will make your code a lot easier to maintain, if you decide to add more words
Avatar of krydea

ASKER

cool,
but can you explaine it?
else i will use if statment.
Avatar of krydea

ASKER

(and will give you the point's)
This is from the help file:

Values property

Applies to

TStrings, TStringList objects

Declaration

property Values[const Name: string]: string;

Description

The Values property gives you access to a specific string in a list of strings.
The strings must have a unique structure before you can use the Values property
array to access them:

Name=Value

The Name that identifies the string is to the left of the equal sign (=),
and the current Value of the Name identifier is on the right side of the equal sign.

There should be no spaces present before and after the equal sign.

Such strings are commonly found in .INI files.
This would also give you the option of easily storing the traslations in an
external text file, so you could just change the text file, rather than
re-compiling the entire application.

For instance, if you create a text file named "Trans.TXT" (using Notepad) containing these lines:

hello=good morning
yawn=good night
noon=lunchtime
howl=full moon
cya=bye


then you could just do something like this:

  TransTable:=TStringList.Create;
  TransTable.LoadFromFile('Trans.TXT')

instead of using all those "Add" statements.

If you want Spanish, you can just change the TextFile to read:

hello=buenos días
yawn=buenos noches
noon=hora almuerzo
howl=luna lleno
cya=adios

Avatar of krydea

ASKER

ok i understand that i can load it from a file but what have a to do if it is loaded?
Avatar of krydea

ASKER

ok if i have load it how to use it?
begin
  TransTable:=TStringList.Create;
  TransTable.LoadFromFile('Trans.TXT');
  S:='hello=yawn?noon?howl?cya';
  N:=getcommand(pChar(S),MyWords);
  for i:=0 to N-1 do ShowMessage(TransTable.Values[StrPas(MyWords[i])]);
  TransTable.Free;
end;
Avatar of krydea

ASKER

i understand it to here:
TransTable:=TStringList.Create;
 TransTable.LoadFromFile('Trans.TXT');
 S:='hello=yawn?noon?howl?cya';
 N:=getcommand(pChar(S),MyWords);

but what do you in this line:(?)
for i:=0 to N-1 do ShowMessage(TransTable.Values[StrPas(MyWords[i])]);

and i understand this line agen:
TransTable.Free;
end;
for i:=0 to N-1 do // <- walks through the array
ShowMessage( // <- Displays a MessageBox
TransTable // <- StringList
Values[ // <- Finds Value[Name] in the Name=Value pairs
StrPas( // <- Converts the Array of Char (0..4096) to a String
MyWords[i] // <- The "Name" to Find the "Value" of
Avatar of krydea

ASKER

ok if i whant to look for 'hello' i do:
ShowMessage(TransTable.Values[StrPas('hello')]);
he show's the Value?
Yes!
Avatar of krydea

ASKER

thx thx thx you help me so good not normal.
thx

btw:sorry my enlisch is os bad but i'm dutch and just 14
ASKER CERTIFIED SOLUTION
Avatar of Jeff_2
Jeff_2

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Hi, here may be some useful code:

The following function returns a part from a string (cut on a delimiter; e.g. your '?') and removes that part (including the delimiter) from the string:

function PickPart(var s: string; delimiter: char): string;
var i: integer;
Begin
  i:=pos(delimiter,s);
  if (i<>0) then begin
    Result:=copy(s,1,i-1);  {result is first part}
    delete(s,1,i);          {remove first part}
  end else begin  {delimiter not found}
    Result:=s;
    s:=''; {empty string}
  end;
End;


If you have more possible delimiters (a set of delimiters), you can use the following modification:

type SetOfChar = set of Char;

function PickPart(var s: string; delimiters: SetOfChar): string;
var i: integer;
Begin
  i:=0;
  while (i<length(s)) and not(s[i] in Delimiters) do inc(i);
  if (i<length(s)) then begin
    Result:=copy(s,1,i-1);  {result is first part}
    delete(s,1,i);          {remove first part}
  end else begin  {no delimiters found}
    Result:=s;
    s:=''; {empty string}
  end;
End;

Hope this is useful,

Spada