Recent

Author Topic: [SOLVED] Get position of string in array. Getting incompatible type error.  (Read 1782 times)

quake004

  • New Member
  • *
  • Posts: 33
I'm trying to make a graph with the integers associated to some cities. To make the adjacency list I need to get the city index of the destinations (Travels) which are in an array of strings (CityNames). When I use StrUtils.IndexStr I get:

Test.pas(34,81) Error: Incompatible type for arg no. 2: Got "Array[0..3] Of ShortString", expected "{Open} Array Of UnicodeString"

The data type ShortString is already used through the program so I need some way of using IndexOf with it.

Also is this the right way to use the TStringList? I'm creating it once for each city.

Here is the compiling code and the error commented:

Code: Pascal  [Select][+][-]
  1. program Test;
  2.  
  3. {$MODE OBJFPC}
  4.  
  5. uses
  6.   Classes, SysUtils, StrUtils;
  7.  
  8. type
  9.   TCity = (NY = 0, LONDON = 1, MOSCU = 2, OTHER = 3);
  10.  
  11. const
  12.   TCities: array[0..3] of TCity = (NY, LONDON, MOSCU, OTHER);
  13.   CityNames: array[0..3] of string = ('new york','london','moscu','other city');
  14.   Travels: array[0..3] of string = ('london,moscu',
  15.     'moscu',
  16.     '"new york","other city"',
  17.     ''); // 'other city' doesn''t have travels
  18.  
  19. procedure ListDestinations;
  20. var
  21.   i, j: Integer;
  22.   travelsList: TStringList;
  23. begin
  24.   for  i := 0 to Length(TCities) - 1  do
  25.   begin
  26.     travelsList := TStringList.Create;
  27.     travelsList.Delimiter := ',';
  28.     travelsList.DelimitedText := Travels[i];
  29.     WriteLn('Destinations from ' + CityNames[ord(TCities[i])] + ': ');
  30.  
  31.     for  j := 0 to pred(travelsList.Count)  do
  32.     begin
  33.       WriteLn(travelsList[j] + ' ');
  34.       // WriteLn(travelsList[j] + ' ' + IntToStr(IndexStr(travelsList[j], CityNames)));
  35.     end;
  36.   end;
  37. end;
  38.  
  39. begin
  40.   ListDestinations;
  41. end.
  42.  
« Last Edit: April 16, 2020, 02:38:01 pm by quake004 »

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Get position of string in array. Getting incompatible type error.
« Reply #1 on: April 16, 2020, 11:04:49 am »
You could use a TStringList, but a simple array would suffice.
Code: Pascal  [Select][+][-]
  1. program Test;
  2.  
  3. {$mode objfpc}{$H-}
  4.  
  5. type
  6.   TCity = (cNY, cLONDON, cMOSCU, cOTHER);
  7.  
  8. const
  9.   CityNames: array[TCity] of shortstring = ('new york','london','moscu','other city');
  10.   Travels:   array[TCity] of shortstring = ('london,moscu',
  11.                                             'moscu',
  12.                                             'new york,other city',
  13.                                             '(no travels)');
  14.  
  15. procedure ListDestinations;
  16. var
  17.   city: TCity;
  18. begin
  19.   for city in TCity do
  20.     WriteLn('Destinations from ',CityNames[city],': ',Travels[city]);
  21. end;
  22.  
  23. begin
  24.   ListDestinations;
  25.   ReadLn;
  26. end.

quake004

  • New Member
  • *
  • Posts: 33
Re: Get position of string in array. Getting incompatible type error.
« Reply #2 on: April 16, 2020, 11:21:47 am »
What I want is to have the array of indexes from destinations for each city. So vertix 0 ('new york') would have an array of [1, 2] because it can travel to London and Moscu. And like that for each city. 'Other city' would be vertix 3 and would have an empty array representing it's destinations. That's why I need to get the index of each city in Travels from CityNames. Because I know how to iterate through the destinations of each city but I'm only getting the name, I need the corresponding index to the name. To get the index for each city I need to take each destination from Travels and see in which position it is on the array CityNames.

Right know I've modified my procedure MakeGraph to ListDestinations and I'm just Writing out the destinations and it's indexes to have an easier compiling example. This is the actual code:

Code: Pascal  [Select][+][-]
  1. program BFS;
  2.  
  3. {$MODE OBJFPC}
  4.  
  5. uses
  6.   Classes, SysUtils, StrUtils;
  7. type
  8.   TCity = (NY = 0, LONDON = 1, MOSCU = 2, OTHER = 3);
  9.  
  10.   Node = record
  11.     vertex: integer;
  12.     edges: array of integer;
  13.   end;
  14.   TGraph = array of node;
  15.  
  16. const
  17.   TCities: array[0..3] of TCity = (NY, LONDON, MOSCU, OTHER);
  18.   CityNames: array[0..3] of string = ('new york','london','moscu','other city');
  19.   Travels: array[0..3] of string = ('london,moscu',
  20.     'moscu',
  21.     '"new york","other city"',
  22.     ''); // 'other city' doesn''t have travels
  23.  
  24. var
  25.   Graph: TGraph;
  26.  
  27. procedure MakeGraph;
  28. var
  29.   i, j: Integer;
  30.   edge: Array of Integer;
  31.   travelsList: TStringList;
  32. begin
  33.   SetLength(Graph, Length(TCities));
  34.   for  i := 0 to Length(TCities) - 1  do
  35.   begin
  36.     travelsList := TStringList.Create;
  37.     travelsList.Delimiter := ',';
  38.     travelsList.DelimitedText := Travels[i];
  39.     WriteLn('Destinations from ' + CityNames[ord(TCities[i])] + ': ');
  40.     SetLength(edge, travelsList.Count);
  41.  
  42.     for  j := 0 to pred(travelsList.Count)  do
  43.     begin
  44.       // WriteLn(travelsList[j] + ' ');
  45.       WriteLn(travelsList[j] + ' ' + IntToStr(IndexStr(travelsList[j], CityNames)));
  46.     end;
  47.  
  48.     WriteLN();
  49.   end;
  50. end;
  51.  
  52. begin
  53.   MakeGraph();
  54. end.
  55.  
« Last Edit: April 16, 2020, 11:33:18 am by quake004 »

quake004

  • New Member
  • *
  • Posts: 33
I just found the implementation of IndexStr on github.

So I changed to use AnsiIndexStr but I don't understand if I have defined my string as String and this is asking for String as parameter why is it saying that I'm giving it a ShortString?

BFS.pas(45,85) Error: Incompatible type for arg no. 2: Got "Array[0..3] Of ShortString", expected "{Open} Array Of AnsiString"

Code: Pascal  [Select][+][-]
  1. Function AnsiIndexStr(const AText: string; const AValues: array of string): Integer;
  2. Function IndexStr(const AText: UnicodeString; const AValues: array of UnicodeString): Integer;
  3. function IndexStr(const AText: string; const AValues: array of string): Integer; inline;
  4.  

Code: Pascal  [Select][+][-]
  1. function IndexStr(const AText: string; const AValues: array of string): Integer;
  2. begin
  3.   Result := AnsiIndexStr(AText, AValues);
  4. end;
  5.  
  6. function AnsiIndexStr(const AText: string; const AValues: array of string): Integer;
  7. var
  8.   i : longint;
  9. begin
  10.   result:=-1;
  11.   if (high(AValues)=-1) or (High(AValues)>MaxInt) Then
  12.     Exit;
  13.   for i:=low(AValues) to High(Avalues) do
  14.      if (avalues[i]=AText) Then
  15.        exit(i);                                 // make sure it is the first val.
  16. end;
  17.  
  18. function IndexStr(const AText: UnicodeString; const AValues: array of UnicodeString): Integer;
  19. var
  20.   i: longint;
  21. begin
  22.   Result := -1;
  23.   if (high(AValues) = -1) or (High(AValues) > MaxInt) Then
  24.     Exit;
  25.   for i := low(AValues) to High(Avalues) do
  26.      if (avalues[i] = AText) Then
  27.        exit(i);                                 // make sure it is the first val.
  28. end;
  29.  
« Last Edit: April 16, 2020, 12:47:12 pm by quake004 »

Handoko

  • Hero Member
  • *****
  • Posts: 5537
  • My goal: build my own game engine using Lazarus
I quickly tested, this below compiles without error:

Code: Pascal  [Select][+][-]
  1. type
  2.   TCity = (NY = 0, LONDON = 1, MOSCU = 2, OTHER = 3);
  3.  
  4. const
  5.   TCities: array[0..3] of TCity = (NY, LONDON, MOSCU, OTHER);
  6.   CityNames: array[0..3] of string = ('new york','london','moscu','other city');
  7.   Travels: array[0..3] of string = ('london,moscu',
  8.     'moscu',
  9.     '"new york","other city"',
  10.     ''); // 'other city' doesn''t have travels
  11.  
  12. function AnsiIndexStr(const AText: string; const AValues: array of string): Integer;
  13. var
  14.   i : longint;
  15. begin
  16.   result:=-1;
  17.   if (high(AValues)=-1) or (High(AValues)>MaxInt) Then
  18.     Exit;
  19.   for i:=low(AValues) to High(Avalues) do
  20.      if (avalues[i]=AText) Then
  21.        exit(i);                                 // make sure it is the first val.
  22. end;
  23.  
  24. procedure ListDestinations;
  25. var
  26.   i, j: Integer;
  27.   travelsList: TStringList;
  28. begin
  29.   for  i := 0 to Length(TCities) - 1  do
  30.   begin
  31.     travelsList := TStringList.Create;
  32.     travelsList.Delimiter := ',';
  33.     travelsList.DelimitedText := Travels[i];
  34.     WriteLn('Destinations from ' + CityNames[ord(TCities[i])] + ': ');
  35.  
  36.     for  j := 0 to pred(travelsList.Count)  do
  37.     begin
  38.       // WriteLn(travelsList[j] + ' ');
  39.       WriteLn(travelsList[j] + ' ' + IntToStr(AnsiIndexStr(travelsList[j], CityNames)));
  40.     end;
  41.   end;
  42. end;

quake004

  • New Member
  • *
  • Posts: 33
It's weird that it doesn't work with the implementation provided by StrUtils. Well it's working now. Thanks.

Code: Pascal  [Select][+][-]
  1. program BFS;
  2.  
  3. {$MODE OBJFPC}
  4.  
  5. uses Classes, SysUtils;
  6.  
  7. type
  8.   TCity = (NY = 0, LONDON = 1, MOSCU = 2, OTHER = 3);
  9.  
  10. const
  11.   TCities: array[0..3] of TCity = (NY, LONDON, MOSCU, OTHER);
  12.   CityNames: array[0..3] of string = ('new york','london','moscu','other city');
  13.   Travels: array[0..3] of string = ('london,moscu',
  14.     'moscu',
  15.     '"new york","other city"',
  16.     ''); // 'other city' doesn''t have travels
  17.  
  18. function AnsiIndexStr(const AText: string; const AValues: array of string): Integer;
  19. var
  20.   i : longint;
  21. begin
  22.   Result := -1;
  23.   if (High(AValues) = -1) or (High(AValues) > MaxInt) Then
  24.     Exit;
  25.   for i := Low(AValues) to High(Avalues) do
  26.       if (avalues[i] = AText) Then
  27.         exit(i);                                 // make sure it is the first val.
  28. end;
  29.  
  30. procedure ListDestinations;
  31. var
  32.   i, j: Integer;
  33.   travelsList: TStringList;
  34. begin
  35.   for  i := 0 to Length(TCities) - 1  do
  36.   begin
  37.     travelsList := TStringList.Create;
  38.     travelsList.Delimiter := ',';
  39.     travelsList.DelimitedText := Travels[i];
  40.     WriteLn('Destinations from ' + CityNames[ord(TCities[i])] + ': ');
  41.  
  42.     for  j := 0 to pred(travelsList.Count)  do
  43.     begin
  44.       // WriteLn(travelsList[j] + ' ');
  45.       WriteLn(travelsList[j] + ' ' + IntToStr(AnsiIndexStr(travelsList[j], CityNames)));
  46.     end;
  47.   end;
  48. end;
  49.  
  50. begin
  51.   ListDestinations;
  52. end.
  53.  
« Last Edit: April 16, 2020, 04:52:49 pm by quake004 »

 

TinyPortal © 2005-2018