### Author Topic: Strings Again  (Read 1851 times)

#### JLWest

• Sr. Member
• Posts: 373
##### Strings Again
« on: December 07, 2018, 01:56:10 am »
Get this error on line 11. ---> uutils.pas(51,19) Fatal: Syntax error, ";" expected but "(" found

Code: Pascal  [Select]
1. function CutLoc (Const aInt : Integer; aStr : String) : Integer;
2.   Var
3.    Idx : Integer = 0;
4.    Lgth : Integer = 0;
5.    str  : String = '';
6.    Str2 : String = '';
7.    begin
8.      Str2 := aStr;
9.      Lgth := Length(Str2);
10.      for IDX := 0 to (Lgth -1) do Begin
11.        Str := Str2(Idx);
12.        if Str = ',' and Idx = aInt then  break;
13.     end;
14.      Return := IDX;
15.    end;
JLWEST
FPC 3.0.4, Lazarus IDE v1.8.2 Windows 10 Pro
Intel i7 770K CPU 4.2GHz 32702MB Ram
GeForce GTX 1080 Graphics - 8 Gig 1.5 Terabyte SSD
3 Terabyte conventional disk space.

#### Handoko

• Hero Member
• Posts: 2851
• My goal: build my own game engine using Lazarus
##### Re: Strings Again
« Reply #1 on: December 07, 2018, 02:44:42 am »
The line #11 should be:
Code: Pascal  [Select]
1.        Str := Str2[Idx];

And line #5 should be:
Code: Pascal  [Select]
1.   Str : Char;

#### lucamar

• Hero Member
• Posts: 865
##### Re: Strings Again
« Reply #2 on: December 07, 2018, 03:14:43 am »
You don't need Str2: you can use aStr directly. It's a normal value-passed parameter so it can be used as a local var. In fact, most of your code is superfluous.

This is basically what your function does:

Code: Pascal  [Select]
1. function CutLoc (Const aInt : Integer; aStr : String) : Integer;
2. begin
3.   if (Length(aStr) > aInt) and (aStr[aInt] = ',') then
4.     Result := aInt
5.   else
6.     Result := Length(aStr))
7. end;
8.

BTW, there's another error in your code: line 12:
if Str = ',' and Idx = aInt then  break;
should be:
if (Str = ',') and (Idx = aInt) then  break;

Oh! And Strings are indexed from 1, not 0.

Have fun!
« Last Edit: December 07, 2018, 03:18:27 am by lucamar »
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!)
Lazarus 1.8.4/FPC 3.0.4 on:
(K)Ubuntu 12..16, Windows XP SP3 (Home/Prof.) and various DOS incarnations.

#### Handoko

• Hero Member
• Posts: 2851
• My goal: build my own game engine using Lazarus
##### Re: Strings Again
« Reply #3 on: December 07, 2018, 03:24:45 am »
I suggest further improvement:

Code: Pascal  [Select]
1. function CutLoc(aInt: Integer; const aStr: string): Integer;

The keyword const should be for aStr. Because unmodified string parameters will be optimized if it used with const keyword. And for Integer parameters, the const keyword is not very useful.

#### lucamar

• Hero Member
• Posts: 865
##### Re: Strings Again
« Reply #4 on: December 07, 2018, 03:28:22 am »
One could go even further:

Code: Pascal  [Select]
1. function CutLoc(
2.     constref aInt: Integer;
3.     constref aStr: string): Integer;

Now all things are just pointers
But better use const and let the compiler optimize.
« Last Edit: December 07, 2018, 03:32:44 am by lucamar »
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!)
Lazarus 1.8.4/FPC 3.0.4 on:
(K)Ubuntu 12..16, Windows XP SP3 (Home/Prof.) and various DOS incarnations.

#### JLWest

• Sr. Member
• Posts: 373
##### Re: Strings Again
« Reply #5 on: December 07, 2018, 04:58:32 am »
@ Lucmar

Your functor always return 65. But maybe I didn't explain the problem very well.

I have a list box with 27,000 + lines.

Each line looks as follows, of course with different values.

// LAN  ,   YSSY  ,   NZAA  ,   B789_LAN_LATAM  ,  0010  ,   LA800  ,   CC-BGA  ,  0  ,0325

Each line can consist of either 8 or 9 fields delimited by a comma. The spaces between the comma is not uniform. So the record could look like the above orl ike so:

// LAN,   YSSY,   NZAA ,   B789_LAN_LATAM ,  0010,LA800,   CC-BGA  ,0,0325

I count the commas to get the number of fields and add 1.

If I want the first field I can do a str := Copy(Line,1,3);

But with field 2  I need to know where the first and second comma are located.
Third field the 2 and  and 3rd location of commas.

And so on until I reach 9 or 10 fields.

What I.m trying to do with;

function CutLoc (Const aInt : Integer; aStr : String) : Integer;

is pass the number of the comma I want the location for.

So if I'm looking for the third comma of the following string the function should hand back
16 and the forth comma 34.
So 16 +1 = 17

Cut1 := 17;
Cut2 := 34;
Field4 := (Line,Cut1,cut2);

Field4 = '   B789_LAN_LATAM'
Trim Field4 and I should wind up with Field4 := 'B789_LAN_LATAM'

1                 2                3                4                5                6
123456789012345678901234567890123456789012345678901234567890
LAN,   YSSY,   NZAA ,   B789_LAN_LATAM ,  0010,LA800,   CC-BGA  ,0,0325

JLWEST
FPC 3.0.4, Lazarus IDE v1.8.2 Windows 10 Pro
Intel i7 770K CPU 4.2GHz 32702MB Ram
GeForce GTX 1080 Graphics - 8 Gig 1.5 Terabyte SSD
3 Terabyte conventional disk space.

#### JLWest

• Sr. Member
• Posts: 373
##### Re: Strings Again
« Reply #6 on: December 07, 2018, 05:08:10 am »
I suggest further improvement:

Code: Pascal  [Select]
1. function CutLoc(aInt: Integer; const aStr: string): Integer;

The keyword const should be for aStr. Because unmodified string parameters will be optimized if it used with const keyword. And for Integer parameters, the const keyword is not very useful.

Hi Handoko.

I'm trying to make your answer work but if I understand you.

Basicaly

A : string;
B : String
,
,
,
A := 'ABCDEF';
B:= Copy(A,1,1);
Both A and B are treated as a string;

But B := A(Idx);

the value of A(Idx) is now a Char so if I change B to a Char it should work.

JLWEST
FPC 3.0.4, Lazarus IDE v1.8.2 Windows 10 Pro
Intel i7 770K CPU 4.2GHz 32702MB Ram
GeForce GTX 1080 Graphics - 8 Gig 1.5 Terabyte SSD
3 Terabyte conventional disk space.

#### JLWest

• Sr. Member
• Posts: 373
##### Re: Strings Again
« Reply #7 on: December 07, 2018, 05:42:15 am »
The line #11 should be:
Code: Pascal  [Select]
1.        Str := Str2[Idx];

And line #5 should be:
Code: Pascal  [Select]
1.   Str : Char;

Code: Pascal  [Select]
1. function CutLoc (Const aStr : String; aInt : Integer) : Integer;
2.   Var
3.    Idx : Integer  = 0;
4.    Lgth : Integer = 0;
5. //   str  : Char;
6.   Str : String;
7.    begin
8.      Lgth := Length(aStr);
9.      for IDX := 1 to Length(aStr)  do Begin
10.       Str := aStr(Idx);
11.        if Str = ',' and Idx = aInt then  break;
12.     end;
13.      Return := IDX;
14.    end;

Changing Str to a Char the compiler error is:
uutils.pas(51,15) Error: Incompatible types: got "AnsiString" expected "Char"

Cementing Str out and running str as a string  the compiler error is:
uutils.pas(52,19) Fatal: Syntax error, ";" expected but "(" found

JLWEST
FPC 3.0.4, Lazarus IDE v1.8.2 Windows 10 Pro
Intel i7 770K CPU 4.2GHz 32702MB Ram
GeForce GTX 1080 Graphics - 8 Gig 1.5 Terabyte SSD
3 Terabyte conventional disk space.

#### Handoko

• Hero Member
• Posts: 2851
• My goal: build my own game engine using Lazarus
##### Re: Strings Again
« Reply #8 on: December 07, 2018, 07:09:47 am »
A : string;
B : String
,
,
,
A := 'ABCDEF';
B:= Copy(A,1,1);
Both A and B are treated as a string;

But B := A(Idx);

the value of A(Idx) is now a Char so if I change B to a Char it should work.

You wrote it wrong:

Code: Pascal  [Select]
1. B := A(Idx);

Below is the corrected version, can you notice the difference?

Code: Pascal  [Select]
1. B := A[Idx];

You can use string for B in the line below:

Code: Pascal  [Select]
1. B := A[Idx];

But because the result is only a single character string, it is more efficient to use char. String is much expensive compare to char.
« Last Edit: December 07, 2018, 07:36:01 am by Handoko »

#### JLWest

• Sr. Member
• Posts: 373
##### Re: Strings Again
« Reply #9 on: December 07, 2018, 07:34:26 am »
Yes, Brackets '[' ']' verses '('  ')'.

It compiled. not I have to test the Logic.

Thank You
JLWEST
FPC 3.0.4, Lazarus IDE v1.8.2 Windows 10 Pro
Intel i7 770K CPU 4.2GHz 32702MB Ram
GeForce GTX 1080 Graphics - 8 Gig 1.5 Terabyte SSD
3 Terabyte conventional disk space.

#### howardpc

• Hero Member
• Posts: 2880
##### Re: Strings Again
« Reply #10 on: December 07, 2018, 09:41:40 am »
I think you're looking for a function something like this:
Code: Pascal  [Select]
1. function GetFieldNo(const aText: String; aFieldNo: Integer; out fieldCount: Integer): String;
2. const
3.   Comma = ',';
4. type
5.   TPosArray = array[1..9] of Integer;
6. var
7.   text: String;
8.   arr:  TPosArray;
9.   i: Integer;
10. begin
11.   fieldCount := 0;
12.   text := Trim(aText);
13.   arr := Default(TPosArray);
14.   if (Length(text) < 2) or (Pos(Comma, text) = 0) or (aFieldNo < 1) then
15.     Exit('');
16.   for i := 1 to Length(text) do
17.     if text[i] = Comma then
18.       begin
19.         Inc(fieldCount);
20.         arr[fieldCount] := i;
21.       end;
22.   if aFieldNo > Succ(fieldCount) then
23.     Exit('');
24.   case aFieldNo = 1 of
25.     True:  Result := Trim(Copy(text, 1, Pred(arr[1])));
26.     False: begin
27.              if aFieldNo = Succ(fieldCount) then
28.                Result := Trim(Copy(text, Succ(arr[fieldCount]), Length(text)))
29.              else Result := Trim(Copy(text, Succ(arr[Pred(aFieldNo)]), Pred(arr[aFieldNo] - arr[Pred(aFieldNo)])));
30.            end;
31.   end;
32.   Inc(fieldCount);
33. end;

#### JLWest

• Sr. Member
• Posts: 373
##### Re: Strings Again
« Reply #11 on: December 07, 2018, 06:19:51 pm »
@Howardpc

Yes It is what I'm trying to do I think. I can follow the solution a little bit. But will have to research some of the statements.   "arr := Default(TPosArray);" Not sure what Default dose for you. Researching on google is pretty tedious for me right now.

But if I get the print  big enough I can sometimes figure this out.

JLWEST
FPC 3.0.4, Lazarus IDE v1.8.2 Windows 10 Pro
Intel i7 770K CPU 4.2GHz 32702MB Ram
GeForce GTX 1080 Graphics - 8 Gig 1.5 Terabyte SSD
3 Terabyte conventional disk space.

#### howardpc

• Hero Member
• Posts: 2880
##### Re: Strings Again
« Reply #12 on: December 07, 2018, 06:24:45 pm »
Default() is a recently introduced compiler intrinsic that initialises any variable to zero/nil/null value(s) as appropriate depending on the variable's type.
Earlier code would have done this by calling FillChar() or FillWord(),  or by explicitly assigning zero to each record field or array element etc.

#### garlar27

• Hero Member
• Posts: 574
##### Re: Strings Again
« Reply #13 on: December 07, 2018, 06:56:12 pm »
Something like this CSV might be useful...

#### Bart

• Hero Member
• Posts: 3312
##### Re: Strings Again
« Reply #14 on: December 07, 2018, 07:23:21 pm »
Did anybody suggest using TStringList.CommaText?

Bart