Recent

Author Topic: Strings Again  (Read 1079 times)

JLWest

  • Full Member
  • ***
  • Posts: 229
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 16 Gig Ram
GeForce GTX 1080 Graphics - 8 Gig 1.5 Terabyte SSD

Handoko

  • Hero Member
  • *****
  • Posts: 2686
  • 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: 500
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!  ;D
« Last Edit: December 07, 2018, 03:18:27 am by lucamar »
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus 1.8.4/FPC 3.0.4 on:
(K)Ubuntu 11..16, Windows XP SP3 (Home/Prof.) and various DOS incarnations.

Handoko

  • Hero Member
  • *****
  • Posts: 2686
  • 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: 500
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 !!!) :P
Lazarus 1.8.4/FPC 3.0.4 on:
(K)Ubuntu 11..16, Windows XP SP3 (Home/Prof.) and various DOS incarnations.

JLWest

  • Full Member
  • ***
  • Posts: 229
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 16 Gig Ram
GeForce GTX 1080 Graphics - 8 Gig 1.5 Terabyte SSD

JLWest

  • Full Member
  • ***
  • Posts: 229
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 see your still answering beginners questions.
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 16 Gig Ram
GeForce GTX 1080 Graphics - 8 Gig 1.5 Terabyte SSD

JLWest

  • Full Member
  • ***
  • Posts: 229
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 16 Gig Ram
GeForce GTX 1080 Graphics - 8 Gig 1.5 Terabyte SSD

Handoko

  • Hero Member
  • *****
  • Posts: 2686
  • 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

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

So I have made your changes to brackets and Char.
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 16 Gig Ram
GeForce GTX 1080 Graphics - 8 Gig 1.5 Terabyte SSD

howardpc

  • Hero Member
  • *****
  • Posts: 2833
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

  • Full Member
  • ***
  • Posts: 229
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 16 Gig Ram
GeForce GTX 1080 Graphics - 8 Gig 1.5 Terabyte SSD

howardpc

  • Hero Member
  • *****
  • Posts: 2833
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: 542
Re: Strings Again
« Reply #13 on: December 07, 2018, 06:56:12 pm »
Something like this CSV might be useful...

Bart

  • Hero Member
  • *****
  • Posts: 3161
    • Bart en Mariska's Webstek
Re: Strings Again
« Reply #14 on: December 07, 2018, 07:23:21 pm »
Did anybody suggest using TStringList.CommaText?

Bart