* * *

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

Zvoni

  • Jr. Member
  • **
  • Posts: 57
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?
People call me crazy because i'm jumping out of perfectly fine airplanes.
I say you're crazy not to!
--------------------------------------------------------------------------------------------------
For health reasons i try to avoid reading unformatted Code

Thaddy

  • Hero Member
  • *****
  • Posts: 6568
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 »
Ada's daddy wrote this:"Fools are my theme, let satire be my song."

Zvoni

  • Jr. Member
  • **
  • Posts: 57
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
People call me crazy because i'm jumping out of perfectly fine airplanes.
I say you're crazy not to!
--------------------------------------------------------------------------------------------------
For health reasons i try to avoid reading unformatted Code

Thaddy

  • Hero Member
  • *****
  • Posts: 6568
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));
Ada's daddy wrote this:"Fools are my theme, let satire be my song."

Zvoni

  • Jr. Member
  • **
  • Posts: 57
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.  
People call me crazy because i'm jumping out of perfectly fine airplanes.
I say you're crazy not to!
--------------------------------------------------------------------------------------------------
For health reasons i try to avoid reading unformatted Code

Thaddy

  • Hero Member
  • *****
  • Posts: 6568
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 »
Ada's daddy wrote this:"Fools are my theme, let satire be my song."

Zvoni

  • Jr. Member
  • **
  • Posts: 57
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
People call me crazy because i'm jumping out of perfectly fine airplanes.
I say you're crazy not to!
--------------------------------------------------------------------------------------------------
For health reasons i try to avoid reading unformatted Code

Zvoni

  • Jr. Member
  • **
  • Posts: 57
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
People call me crazy because i'm jumping out of perfectly fine airplanes.
I say you're crazy not to!
--------------------------------------------------------------------------------------------------
For health reasons i try to avoid reading unformatted Code

ASerge

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

  • Jr. Member
  • **
  • Posts: 57
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.  
People call me crazy because i'm jumping out of perfectly fine airplanes.
I say you're crazy not to!
--------------------------------------------------------------------------------------------------
For health reasons i try to avoid reading unformatted Code

ASerge

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

 

Recent

Get Lazarus at SourceForge.net. Fast, secure and Free Open Source software downloads Open Hub project report for Lazarus