Recent

Author Topic: Replacing a single character in a PChar  (Read 6159 times)

Zvoni

  • Hero Member
  • *****
  • Posts: 2319
Replacing a single character in a PChar
« on: March 26, 2018, 09:52:12 am »
Hi Folks,

i'm new to the Forum, and pascal in general.

I'm coming from a 18-years background of Visual Basic 6 (classic, not .NET), and had to switch to FPC/Lazarus (reasons for it don't matter now).

I have an issue which puzzles me right now.

I have a PChar, which i pass to a Quicksort-Function to get it sorted
e.g.:
Source='klgbhter'
desired Result='behklrt'

I know that it works with an array, so that's not the issue, but since my other code uses PChar, i didn't want to change it to an array.
Never mind that an array of char is basically the same as a PChar (the array-variable is a pointer to the first element of the array, but it's still a pointer).

My first try was something along the lines

Code: Pascal  [Select][+][-]
  1. Var
  2. ch:=Char;
  3. //.......
  4. //Let's say i want to swap the third character with the fifth of source
  5. ch:=MyPChar[2];
  6. MyPChar[2]:=MyPChar[4];
  7. MyPChar[4]:=ch;
  8.  
Funny thing: The compiler's not complaining, but line 6 causes everything to go KABOOM!
I tried with memcpy, memmove, Move and what not

Since in Visual Basic i never had to bother with Memory-Management and pointers i'm kind of stuck.
I don't have a degree in computer science and i'm definitely not a Pro in programming (i'm just a hobby-programmer), i don't even know the difference what the stack and the heap is
(but wouldn't mind someone explaining that to me, or i'll just look it up on Wikipedia  :P)

I remember finding a thread on this forum during my research, where one of the Administrators even mentioned something along the lines, that in FPC/Lazarus you cannot modify a string in that way, but for the life of me i can't find that thread (i think it was from 2013).
Is that true?

Any ideas how to achieve what i want?
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

Thaddy

  • Hero Member
  • *****
  • Posts: 14205
  • Probably until I exterminate Putin.
Re: Replacing a single character in a PChar
« Reply #1 on: March 26, 2018, 11:06:12 am »
Simply use a string:
Code: Pascal  [Select][+][-]
  1. program testchars;
  2. {$mode delphi}{$ifndef linux}{$apptype console}{$endif}
  3. Var
  4.   ch:AnsiChar;
  5.   MyPchar:AnsiString = 'whateveryouwant';
  6. begin
  7.   ch:=MyPChar[2];
  8.   MyPChar[2]:=MyPChar[4];
  9.   MyPChar[4]:=ch;
  10.   writeln(MyPchar);
  11. end.

You can also do it like this:
Code: Pascal  [Select][+][-]
  1. program testchars;
  2. {$mode delphi}{$ifndef linux}{$apptype console}{$endif}
  3. Var
  4.   ch:AnsiChar;
  5.   MyPchar:array[1..15] of AnsiChar = 'whateveryouwant';
  6. begin
  7.   ch:=MyPChar[2];
  8.   MyPChar[2]:=MyPChar[4];
  9.   MyPChar[4]:=ch;
  10.   writeln(MyPchar);
  11. end.

Note I intentionally specify the string type.
« Last Edit: March 26, 2018, 11:18:01 am by Thaddy »
Specialize a type, not a var.

Zvoni

  • Hero Member
  • *****
  • Posts: 2319
Re: Replacing a single character in a PChar
« Reply #2 on: March 26, 2018, 12:40:38 pm »
Thanks, Thaddy.

Yeah, i know about the String-Type and the Array of Char, the problem is, that i would have liked to keep the PChar-Type, since later in the code the result of this Quicksort is getting passed to another function which uses c-functions extensively, and those c-functions need a pchar.

For now, it would be enough for me to know, if it's even possible, or if i'm missing something, why memcpy or memmove fail
(i even thought it might have to do with the null-terminator of my single Char i want to insert/replace in my PChar, but couldn't test it since i'm at work now).

Just now, i got an idea:
Is it possible to pass a PChar to a Function, which takes an array of Char as an argument (considering both are basically the same thing)?
Will have to test that.
As long as can keep that array inside this Quicksort i could live with it
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

Thaddy

  • Hero Member
  • *****
  • Posts: 14205
  • Probably until I exterminate Putin.
Re: Replacing a single character in a PChar
« Reply #3 on: March 26, 2018, 12:54:09 pm »
You can simply pass the string with a pchar typecast:
Code: Pascal  [Select][+][-]
  1. var a:string = 'testme';
  2. begin
  3.   CallSomeCFunc(PChar(a));
Specialize a type, not a var.

Zvoni

  • Hero Member
  • *****
  • Posts: 2319
Re: Replacing a single character in a PChar
« Reply #4 on: March 26, 2018, 01:28:58 pm »
Hmmm,

so if understood you correctly something like this.

Code: Pascal  [Select][+][-]
  1. Function QuickSort(argSource:String):PChar;
  2. Begin
  3. //DoSomething with argSource
  4. Result:=PChar(argSource);
  5. End;
  6.  
  7. Procedure MyProcedure;
  8. Var
  9. MyPChar:PChar;
  10. ResultPChar:PChar;
  11.  
  12. Begin
  13. //Do Something with MyPChar
  14. ResultPChar:=QuickSort(MyPChar);
  15. //Pass ResultPChar to next Function
  16. End;
  17.  
  18.  
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

Thaddy

  • Hero Member
  • *****
  • Posts: 14205
  • Probably until I exterminate Putin.
Re: Replacing a single character in a PChar
« Reply #5 on: March 26, 2018, 02:13:36 pm »
I meant something along these lines:
Code: Pascal  [Select][+][-]
  1. {$mode delphi}{$ifndef linux}{$apptype console}{$endif}
  2. Function QuickSort(const argSource:AnsiString):PAnsiChar;
  3. Begin
  4.   //DoSomething with argSource as it it were a PAnsiChar
  5.   Result:= PAnsiChar(argSource);
  6. End;
  7.  
  8. Var
  9.   MyPChar:AnsiString = 'sortme';
  10.   ResultPChar:PAnsiChar;
  11. Begin
  12.   //Do Something with MyPChar
  13.   ResultPChar:=QuickSort(MyPChar);
  14.   //Pass ResultPChar to next Function
  15.   writeln(ResultPChar);  
  16. end.

You only need the casts when interfacing with C code. Otherwise always use one of the Pascal string types.
These are PChar compatible through a typecast and much safer than a PChar.
« Last Edit: March 26, 2018, 02:19:42 pm by Thaddy »
Specialize a type, not a var.

Zvoni

  • Hero Member
  • *****
  • Posts: 2319
Re: Replacing a single character in a PChar
« Reply #6 on: March 26, 2018, 02:52:30 pm »
OK, thx Thaddy.

Will try that and report back
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

Zvoni

  • Hero Member
  • *****
  • Posts: 2319
Re: Replacing a single character in a PChar
« Reply #7 on: March 26, 2018, 04:23:09 pm »
Solved it.

I admit: Not really in the way i was envisioning it, but it works

I changed the argument of the receiving QuickSort to Array of Char
Code: Pascal  [Select][+][-]
  1. Procedure QuickSortInternal(var pString:Array of Char; lowPos:Integer; highPos:Integer; CaseSensitive:Boolean=False);
  2.  

The calling side looks like this:
Code: Pascal  [Select][+][-]
  1. Function QuickSortPChar(pString:PChar; lowPos:Integer; highPos:Integer; CaseSensitive:Boolean=False):PChar;
  2. Var
  3.   arrString:Array of Char;
  4. Begin
  5.  
  6.      SetLength(arrString,strlen(pString)+1);
  7.      strLCopy(PChar(@arrString[0]),pString,High(arrString));
  8.      QuickSortInternal(arrString, lowPos, highPos, CaseSensitive);
  9.      Result:=PChar(@arrString[0]);
  10.  
  11. end;        
  12.  

It works!

thx Thaddy.

You showed me the right direction
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

ASerge

  • Hero Member
  • *****
  • Posts: 2223
Re: Replacing a single character in a PChar
« Reply #8 on: March 26, 2018, 06:31:47 pm »
It works!
But it should not. Your procedure does the same:
  • Do something.
  • Remove this.
  • Return the pointer to the garbage received from the removal.
As pointed out by @Thaddy, use strings. And only when you call functions that require PChar, cast to PChar.
Code: Pascal  [Select][+][-]
  1. function QuickSortString(const S: string; LowPos, HighPos: Integer; CaseSensitive: Boolean = False): string;
  2. begin
  3.   Result := S;
  4.   UniqueString(Result);
  5.   QuickSortInternal(PChar(Result), LowPos - 1, HighPos - 1, CaseSensitive);
  6. end;

Zvoni

  • Hero Member
  • *****
  • Posts: 2319
Re: Replacing a single character in a PChar
« Reply #9 on: March 26, 2018, 09:50:05 pm »
True, i had to tweak it slightly, but it works.

I had the lengths wrong.

Code: Pascal  [Select][+][-]
  1. Function QuickSortPChar(pString:PChar; lowPos:Integer; highPos:Integer; CaseSensitive:Boolean=False):PChar;
  2. Var
  3.   arrString:Array of Char;
  4. Begin
  5.  
  6.      SetLength(arrString,strlen(pString));
  7.      strLCopy(@arrString[0],pString,High(arrString)+1);
  8.      QuickSortInternal(arrString, lowPos, highPos, CaseSensitive);
  9.      strLCopy(Result,@arrString[0],High(arrString)+1);
  10. end;                                
  11.  
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

ASerge

  • Hero Member
  • *****
  • Posts: 2223
Re: Replacing a single character in a PChar
« Reply #10 on: March 26, 2018, 10:21:36 pm »
True, i had to tweak it slightly, but it works.
Error again. The Result may not have enough space for the string.
Use strings!

 

TinyPortal © 2005-2018