Recent

Author Topic: String manipulation problem  (Read 645 times)

Bart

  • Hero Member
  • *****
  • Posts: 3516
    • Bart en Mariska's Webstek
Re: String manipulation problem
« Reply #15 on: October 09, 2019, 12:11:36 am »
A little adapatation to the code that extracts typeHtml, so it also extracts the number:

Code: Pascal  [Select]
  1. function TryExtractNumberAndTypeHtmlFromTag(Tag: String; var Number: Integer; var typeHtml: String): Boolean;
  2. {
  3. Precondition:
  4.   Tag is in the form of "<for SomeID='SomeValue' type='comma,separated,values'/>"
  5.   SomeId cannot be the string 'type'
  6.   SomeID='SomeValue' is the first Key/Value pair inside the tag.
  7.   None of the comma-separated values itself can contain a single quote as part of the value
  8.   There will be no space before or after the equals sign after "SomeID" an d"type"
  9. PostCondition:
  10.   The function returns True if both a number and a value for typeHtml are foud, otherwise it returns False
  11.   The Number is set to 'SomeValue'
  12.   The typeHtml is set to 'comma,separated,values'
  13. }
  14. var
  15.   p, ErrorCode: Integer;
  16.   NumberStr: String;
  17. begin
  18.   Result := False;
  19.   typeHtml := '';
  20.   Number := 0;
  21.   if Length(Tag) < Length('<type=''''/>') then Exit;
  22.   if (Copy(Tag, 1,5) <> '<for ') and (Tag[Length(Tag)] <> '>') and (Tag[Length(Tag)-1] <> '/') then Exit;
  23.  
  24.   Delete(Tag,1,5);
  25.   p := pos('=''', Tag); //also find the first single quote atfer the equals sign
  26.   if p = 0 then Exit;
  27.   Inc(p, Length('='''));
  28.   Delete(Tag, 1, p-1);
  29.   p := Pos('''', Tag);
  30.   if p = 0 then Exit;
  31.   NumberStr := Copy(Tag, 1, p-1);
  32.   Val(NumberStr, Number, ErrorCode);
  33.   if ErrorCode <> 0 then Exit;
  34.  
  35.   p := Pos('type=''', Tag);  //also find the first single quote atfer the equals sign
  36.   if p = 0 then Exit;
  37.   Inc(p, Length('type='''));
  38.   typeHtml := Copy(Tag, p, MaxInt);
  39.   p := Pos('''', typeHtml);
  40.   if p = 0 then Exit;
  41.   Delete(typeHtml, p, MaxInt);
  42.   Result := True;
  43. end;

And the program:
Code: Pascal  [Select]
  1. var
  2.   typeHtml: String;
  3.   Tag: string = '<for it=''123'' type=''password,button,text'' hidden=''true''/>';
  4.   tType: tab;
  5.   i, Count, Number: Integer;
  6. begin
  7.   if not TryExtractNumberAndTypeHtmlFromTag(Tag, Number, typeHtml) then
  8.   begin
  9.     writeln('Cannot extract Number and typeHtml from "',Tag,'"');
  10.     Exit;
  11.   end;
  12.   writeln('Number   = "',Number,'"');
  13.   writeln('typeHtml = "',typeHtml,'"');
  14.   Split(typeHtml, tType, Count);
  15.   writeln('Count    = ',Count);
  16.   for i := 1 to Count do writeln('"',tType[i],'"');
  17. end.

Outputs:
Code: [Select]
C:\Users\Bart\LazarusProjecten\bugs\forum\htmltag>test
Number   = "123"
typeHtml = "password,button,text"
Count    = 3
"password"
"button"
"text"

Bart
« Last Edit: October 09, 2019, 12:13:18 am by Bart »

Bart

  • Hero Member
  • *****
  • Posts: 3516
    • Bart en Mariska's Webstek
Re: String manipulation problem
« Reply #16 on: October 09, 2019, 11:29:57 am »
A shorter and simpler version to extract number and typeHtml.
It assumes the tag starts with <for it=' and it assumes that the text type=' is always the start of the typeHtml we are lokking for.
Tipically in homework assignments these assumptions are allowed though.

Code: Pascal  [Select]
  1. function TryExtractNumberAndTypeHtmlFromTagSimple(Tag: String; var Number: Integer; var typeHtml: String): Boolean;
  2. {
  3. Precondition:
  4.   Tag must be in the form of "<for it='SomeIntegerValue' type='comma,separated,values'/>"
  5.   None of the comma-separated values itself can contain a single quote as part of the value
  6.   There will be no space before or after any of the equals signs
  7. PostCondition:
  8.   The function returns True if both a number and a value for typeHtml are foud, otherwise it returns False
  9.   The Number is set to 'SomeValue'
  10.   The typeHtml is set to 'comma,separated,values'
  11. }
  12. var
  13.   p, ErrorCode: Integer;
  14.   NumberStr: String;
  15. const
  16.   ForLen =  9; //<for it='
  17.   TypeLen = 6; //type='
  18. begin
  19.   Result := False;
  20.   typeHtml := '';
  21.   Number := 0;
  22.   p := Pos('<for it=''', Tag);
  23.   if p = 0 then Exit;
  24.   Delete(Tag,1,p + ForLen - 1);
  25.   p := Pos('''', Tag);
  26.   if p = 0 then Exit;
  27.   NumberStr := Copy(Tag, 1, p-1);
  28.   Val(NumberStr, Number, ErrorCode);
  29.   if ErrorCode <> 0 then Exit;
  30.  
  31.  
  32.   p := Pos('type=''', Tag);  //also find the first single quote atfer the equals sign
  33.   if p = 0 then Exit;
  34.   typeHtml := Copy(Tag, p + TypeLen, MaxInt);
  35.   p := Pos('''', typeHtml);
  36.   if p = 0 then Exit;
  37.   Delete(typeHtml, p, MaxInt);
  38.   Result := True;
  39. end;

Bart

Bart

  • Hero Member
  • *****
  • Posts: 3516
    • Bart en Mariska's Webstek
Re: String manipulation problem
« Reply #17 on: October 09, 2019, 12:13:41 pm »
so this is my what i done dude and i get error

dude ????
I do have a name, you know.

I do not really understand the flow of your program.
You seem to ask the user to input an array of html tags, is that really what you want? B.t.w. n and i will be wrong when the procedure exits.
Also this crashes if somebody inputs more than 20 tags.
It really might be easier to just write a procedure that asks for one html tag.
If you really need to ask for multipel tags, just call that procedure in a loop of some kind.

Then your getNumber tries to iterate throught this array, but it only ever returns the first numer it finds.
Also it assumes that the number will only ever be a single digit (for it='123' -> 1 instead of 123).

Then you repeatedly write down that number until the user presses *, why?

The procedure cleanTag simply crashes:
Code: Pascal  [Select]
  1.   for j:=1 to NumberVergul do
  2.   begin
  3.     for i:=1 to length(tag) do
  4.     if tag[i] <> ',' then
  5.       tTag[j]:=tag[i] <<-- crash: Runtime error 201 at $00401A5B

Please use proper indentation.
When you expect user input then tell the user.
Also tell the user what condition ends the input (e.g. pressing *, which b.t.w. does NOT work as you seem to expect in procedure remplire).

I cleaned up your code.
Fixed some issues in remplire, added writeln statements for debugging and to inform the user what he is expected to do.

Code: Pascal  [Select]
  1. program whitehat;
  2.  
  3. uses
  4.   crt;
  5.  
  6. type
  7.   tab= array[1..20] of string;
  8. var
  9.   t,tTag:tab;
  10.   n:integer;
  11.   numberFor:string;
  12.   tag:string;
  13.  
  14. procedure remplire (var t:tab;var n:integer);
  15. var
  16.   i:integer;
  17.   s: string;
  18. begin
  19.   writeln('procedure remplire A');
  20.   i:=0;
  21.   n:=0;
  22.   repeat
  23.     write('Enter tag # ',i+1,' (empty line quits input): ');
  24.     readln(s);
  25.     if s<> '' then
  26.     begin
  27.       i:=i+1;
  28.       t[i] := s;
  29.       n:=n+1;
  30.     end;
  31.   until s='';
  32.   writeln('procedure remplire End: n=',n,', i=',i);
  33. end;
  34.  
  35. // this procedure used to get  the 5 number after it='  <for it='5' type='text,password'>
  36. procedure getNumber (t:tab;n:integer;var numberFor:string;var tag:string);
  37. var
  38.   i:integer;
  39. begin
  40.   writeln('procedure GetNumber A: n=',n);
  41.   for i:=1 to n do
  42.   begin
  43.     if pos('for',t[i])<>0 then
  44.     tag:=t[i];
  45.     numberFor:=copy(t[i],10,1);
  46.   end;
  47.   repeat
  48.     writeln('numberFor = ',numberFor,' Press * to stop (why??)');
  49.   until ReadKey=#42;
  50.   writeln('procedure GetNumber End');
  51. end;
  52.  
  53. //this function is for cleaning tag like if i find <for it='5' type='text,password'>  / the tTag (table) value is  :text,password
  54. procedure cleanTag (tag:string;var tTag:tab);
  55. var
  56.   j,i,NumberVergul:integer;
  57. begin
  58.   writeln('procedure cleanTag A: Tag=',Tag);
  59.  
  60.   NumberVergul:=1;
  61.   for i:=1 to length(tag) do
  62.   begin
  63.     if tag[i] <> ',' then
  64.     NumberVergul:=NumberVergul+1;
  65.   end;
  66.  
  67.   for j:=1 to NumberVergul do
  68.   begin
  69.     for i:=1 to length(tag) do
  70.     if tag[i] <> ',' then
  71.       tTag[j]:=tag[i]
  72.     else
  73.       tTag[j]:=tag[i+1];
  74.   end;
  75.  
  76.  
  77.   repeat
  78.     for i:=1 to NumberVergul do
  79.     begin
  80.       writeln(tTag[i]);
  81.     end;
  82.    until ReadKey=#42;
  83.    writeln('procedure cleanTag End');
  84. end;
  85.  
  86. begin
  87.   remplire (t,n);
  88.   getNumber(t,n,numberFor,tag);
  89.   cleanTag (tag,tTag);
  90. end.

Still does not do what you want, but at least you can folow the code flow:
Code: [Select]
C:\Users\Bart\LazarusProjecten\bugs\forum\htmltag>whitehat
procedure remplire A
Enter tag # 1 (empty line quits input): <for it='123' type='foo,bar,foobar'/>
Enter tag # 2 (empty line quits input):
procedure remplire End: n=1, i=1
procedure GetNumber A: n=1
numberFor = 1 Press * to stop (why??)
numberFor = 1 Press * to stop (why??)
numberFor = 1 Press * to stop (why??)
numberFor = 1 Press * to stop (why??)
numberFor = 1 Press * to stop (why??)
numberFor = 1 Press * to stop (why??)
procedure GetNumber End
procedure cleanTag A: Tag=<for it='123' type='foo,bar,foobar'/>
Runtime error 201 at $00401A5B
  $00401A5B  CLEANTAG,  line 71 of whitehat.lpr
  $00401BD0  main,  line 89 of whitehat.lpr
  $00409711

No heap dump by heaptrc unit
Exitcode = 201

Runtime error 201 is a range check error b.t.w.

Bart

Bart

  • Hero Member
  • *****
  • Posts: 3516
    • Bart en Mariska's Webstek
Re: String manipulation problem
« Reply #18 on: October 09, 2019, 12:42:18 pm »
My program adapted to ask for multipe Tags as input:

Code: Pascal  [Select]
  1. const
  2.   Max = 50;
  3. type
  4.   Tab= array[1..Max] of string;
  5.  
  6. procedure ClearTab(var T: Tab);
  7. var
  8.   i: Integer;
  9. begin
  10.   for i := 1 to Max do T[i] := '';
  11. end;
  12.  
  13. procedure Split(S: String; var T: Tab; var Count: Integer); //or : ; out Count); if that syntax is allowed for you
  14. {
  15. Preconditions:
  16.   Comma (',') is used as separator
  17.   S is not allowed to end in a comma
  18. Postconditions:
  19.   Count is set to the number of strings found
  20.   T[1]..T[Count] hold the respective strings
  21.   T[Count+1]..T[50] are empty strings
  22. }
  23.  
  24. var
  25.   p: Integer;
  26. begin
  27.   ClearTab(T);
  28.   Count := 1;
  29.   while S <> '' do
  30.   begin
  31.     p := Pos(',', S);
  32.     if p = 0 then
  33.     begin
  34.       T[Count] := S;
  35.       Break;
  36.     end;
  37.     T[Count] := copy(S,1,p-1);
  38.     Delete(S, 1, p);
  39.     Inc(Count);
  40.   end;
  41. end;
  42.  
  43.  
  44. function TryExtractNumberAndTypeHtmlFromTag(Tag: String; var Number: Integer; var typeHtml: String): Boolean;
  45. {
  46. Precondition:
  47.   Tag is in the form of "<for SomeID='SomeValue' type='comma,separated,values'/>"
  48.   SomeId cannot be the string 'type'
  49.   SomeID='SomeValue' is the first Key/Value pair inside the tag.
  50.   None of the comma-separated values itself can contain a single quote as part of the value
  51.   There will be no space before or after the equals sign after "SomeID" an d"type"
  52. PostCondition:
  53.   The function returns True if both a number and a value for typeHtml are foud, otherwise it returns False
  54.   The Number is set to 'SomeValue'
  55.   The typeHtml is set to 'comma,separated,values'
  56. }
  57. var
  58.   p, ErrorCode: Integer;
  59.   NumberStr: String;
  60. begin
  61.   Result := False;
  62.   typeHtml := '';
  63.   Number := 0;
  64.   if Length(Tag) < Length('<type=''''/>') then Exit;
  65.   if (Copy(Tag, 1,5) <> '<for ') and (Tag[Length(Tag)] <> '>') and (Tag[Length(Tag)-1] <> '/') then Exit;
  66.  
  67.   Delete(Tag,1,5);
  68.   p := pos('=''', Tag); //also find the first single quote atfer the equals sign
  69.   if p = 0 then Exit;
  70.   Inc(p, Length('='''));
  71.   Delete(Tag, 1, p-1);
  72.   p := Pos('''', Tag);
  73.   if p = 0 then Exit;
  74.   NumberStr := Copy(Tag, 1, p-1);
  75.   Val(NumberStr, Number, ErrorCode);
  76.   if ErrorCode <> 0 then Exit;
  77.  
  78.   p := Pos('type=''', Tag);  //also find the first single quote atfer the equals sign
  79.   if p = 0 then Exit;
  80.   Inc(p, Length('type='''));
  81.   typeHtml := Copy(Tag, p, MaxInt);
  82.   p := Pos('''', typeHtml);
  83.   if p = 0 then Exit;
  84.   Delete(typeHtml, p, MaxInt);
  85.   Result := True;
  86. end;
  87.  
  88. function TryExtractNumberAndTypeHtmlFromTagSimple(Tag: String; var Number: Integer; var typeHtml: String): Boolean;
  89. {
  90. Precondition:
  91.   Tag must be in the form of "<for it='SomeIntegerValue' type='comma,separated,values'/>"
  92.   None of the comma-separated values itself can contain a single quote as part of the value
  93.   There will be no space before or after any of the equals signs
  94. PostCondition:
  95.   The function returns True if both a number and a value for typeHtml are foud, otherwise it returns False
  96.   The Number is set to 'SomeValue'
  97.   The typeHtml is set to 'comma,separated,values'
  98. }
  99. var
  100.   p, ErrorCode: Integer;
  101.   NumberStr: String;
  102. const
  103.   ForLen =  9; //<for it='
  104.   TypeLen = 6; //type='
  105. begin
  106.   Result := False;
  107.   typeHtml := '';
  108.   Number := 0;
  109.   p := Pos('<for it=''', Tag);
  110.   if p = 0 then Exit;
  111.   Delete(Tag,1,p + ForLen - 1);
  112.   p := Pos('''', Tag);
  113.   if p = 0 then Exit;
  114.   NumberStr := Copy(Tag, 1, p-1);
  115.   Val(NumberStr, Number, ErrorCode);
  116.   if ErrorCode <> 0 then Exit;
  117.  
  118.  
  119.   p := Pos('type=''', Tag);  //also find the first single quote atfer the equals sign
  120.   if p = 0 then Exit;
  121.   typeHtml := Copy(Tag, p + TypeLen, MaxInt);
  122.   p := Pos('''', typeHtml);
  123.   if p = 0 then Exit;
  124.   Delete(typeHtml, p, MaxInt);
  125.   Result := True;
  126. end;
  127.  
  128. procedure AskTags(var Tags: Tab; var NrOfTags: Integer);
  129. var
  130.   Tag: String;
  131. begin
  132.   ClearTab(Tags); //Clear the array
  133.   NrOfTags := 0;
  134.   repeat
  135.     write('Tag # ',NrOfTags+1,': (empty line quits input): ');
  136.     readln(Tag);
  137.     if Tag <> '' then
  138.     begin
  139.       Inc(NrOfTags);
  140.       Tags[NrOfTags] := Tag;
  141.     end;
  142.   until (Tag = '') or (NrOfTags = Max);
  143. end;
  144.  
  145. var
  146.   typeHtml: String;
  147.   Tag: string = '<for it=''123'' type=''password,button,text'' hidden=''true''/>';
  148.   tType, Tags: tab;
  149.   i, j, NrOfTags, Count, Number: Integer;
  150. begin
  151.   AskTags(Tags, NrOfTags);
  152.   for i := 1 to NrOfTags do
  153.   begin
  154.     if not TryExtractNumberAndTypeHtmlFromTagSimple(Tags[i], Number, typeHtml) then
  155.     begin
  156.       writeln('Cannot extract Number and typeHtml from "',Tags[i],'"');
  157.       Continue; //skip rest of the loop code, go to the next value of i
  158.     end;
  159.     writeln('Number   = "',Number,'"');
  160.     writeln('typeHtml = "',typeHtml,'"');
  161.     Split(typeHtml, tType, Count);
  162.     writeln('Count    = ',Count);
  163.     //write the seperate strings we found for this typeHtml
  164.     for j := 1 to Count do writeln('  "',tType[j],'"');
  165.   end;
  166. end.

Code: [Select]
C:\Users\Bart\LazarusProjecten\bugs\forum\htmltag>test
Tag # 1: (empty line quits input): <for it='123' type='foo,bar,foobar'/>
Tag # 2: (empty line quits input): <for it='-32767' type='jan,klaas'/>
Tag # 3: (empty line quits input): >invalid input type=' ,,,,'
Tag # 4: (empty line quits input):
Number   = "123"
typeHtml = "foo,bar,foobar"
Count    = 3
  "foo"
  "bar"
  "foobar"
Number   = "-32767"
typeHtml = "jan,klaas"
Count    = 2
  "jan"
  "klaas"
Cannot extract Number and typeHtml from ">invalid input type=' ,,,,'"

Bart

Bart

  • Hero Member
  • *****
  • Posts: 3516
    • Bart en Mariska's Webstek
Re: String manipulation problem
« Reply #19 on: October 09, 2019, 05:34:05 pm »
The procedure cleanTag simply crashes:
Code: Pascal  [Select]
  1.   for j:=1 to NumberVergul do
  2.   begin
  3.     for i:=1 to length(tag) do
  4.     if tag[i] <> ',' then
  5.       tTag[j]:=tag[i] <<-- crash: Runtime error 201 at $00401A5B


In cleanTag what the beginning of the code essentially does is find the position of the first comma and set NumberVergul to that value minus 1.
Then in the next loop you seem to assume that NumberVergul is the amount of strings inside the 'text,password' part of the tag.
This is obviously wrong (and it will crash the program if NumberVergul is > 20).

Assuming that procedure remplire gives you an array of strings, where presumably only one line has an appropriate tag in it, then with little modifications procedure getNumber will be OK.
Note however that "<for it='QWERTY" will set numberFor to 'Q'.
(This may not be relevant if the assignment states that tags are always correctly formed as your example tag).

For the cleanTag() procedure you need to write down the algorithm (no code) on how you would solve this problem e.g. if you had only paper and pencil.
What steps are involved?
E.g.
  • Part 1: Extract the 'password,text' part
  • Part 2: Split the found 'password,text' into an array so that array[1]='password' and array[2]='text'

Step 1 for step 1 surely is: find the position of "type='"
What would you do logically next?

Once you have written this down tranlate the algorithm to pseudo-code
E.g.
Code: [Select]
  Find p: position of "type='" in the Tag
  if not found: exit with some indication of error
  etc.

This will make implementiong in code easy:
Code: Pascal  [Select]
  1.   p := Pos('type=''', Tag);
  2.   if p = 0 then ...

B.t.w. using tag and tTag as variable names inside one procedure is really confusing.
Using understandable type names can also help. Consider:
Code: Pascal  [Select]
  1. const
  2.   Max = 20;  //need the max amount allowed in the procedure that dos the user input
  3.  
  4. type
  5.   TStringArray= array[1..Max] of string;
  6.   // versus
  7.   Tab= array[1..Max] of string;


Bart

whitehat

  • Jr. Member
  • **
  • Posts: 93
Re: String manipulation problem
« Reply #20 on: October 09, 2019, 08:55:43 pm »
bart you are the best i hope one day i will be like you i mean it <3