How to remove the space around a character?

Let's say I have the following line:

s := 'This , is, the Delphi , World!'; 

I need the following output:

 Result := 'This,is,the Delphi,World!'; 

Basically, I need a procedure that allows ALL occurrences of spaces ONLY if they appear before or after the char comma (which is my separator), leaving intact spaces between other words.

Any help is greatly appreciated.

What do you think of this decision?

 function RemoveSpacesAroundDelimiter(var aString: string; aDelimiter: string): string; begin while AnsiContainsText(aString, aDelimiter + ' ') do begin aString := StringReplace(aString, ', ', aDelimiter, [rfReplaceAll, rfIgnoreCase]); end; while AnsiContainsText(aString, ' ' + aDelimiter) do begin aString := StringReplace(aString, ' ' + aDelimiter, aDelimiter, [rfReplaceAll, rfIgnoreCase]); end; Result := aString; end; 

thanks

Fabio

+8
string delphi
source share
10 answers

Sounds like a task to a TStringList.

 function UltraTrim(Value: string): string; var sl: TStringList; i: Integer; begin sl := TStringList.Create; try // Prevent the stringlist from using spaces as delimiters too. sl.StrictDelimiter := True; // Set the comma separated text. sl.CommaText := Value; // Trim each item. for i := 0 to sl.Count -1 do sl[i] := Trim(sl[i]); // Concat back to comma separated string. Result := sl.CommaText; finally sl.Free; end; end; 
+9
source share

The quick version may be:

 function RemoveSpacesAroundDelimiter(const aString: string; aDelimiter: char = ','): string; var S, D, D2: PChar; begin SetLength(result,length(aString)); if aString<>'' then begin S := pointer(aString); D := pointer(result); while S^<>#0 do begin if S^=' ' then begin D2 := D; repeat inc(S); D^ := ' '; inc(D); until S^<>' '; if S^=#0 then break; if S^=aDelimiter then D := D2; // trim spaces before comma end; D^ := S^; if (S[0]=aDelimiter) and (S[1]=' ') then repeat inc(S) until S^<>' ' else // trim spaces after comma inc(S); inc(D); end; SetLength(result,D-pointer(result)); end; end; 

Some test codes:

  assert(RemoveSpacesAroundDelimiter('one two,three')='one two,three'); assert(RemoveSpacesAroundDelimiter('one two , three')='one two,three'); assert(RemoveSpacesAroundDelimiter('one,two,three')='one,two,three'); assert(RemoveSpacesAroundDelimiter('one , two, three')='one,two,three'); 
+4
source share

Copy the characters one by one to the destination buffer, but find the spaces and delimiters and remember the last place you copied the non-spatial character to. If you see a space and the last non-space that you copied is a delimiter, then skip the space. If this is a space and the last character you copied is not a separator, then copy it to the destination, but remember the last space added. That way, if you see the delimiter later, you can go back and overwrite it.

 function RemoveSpacesAroundDelimiter(const AString: string; ADelimiter: Char): string; var c: Char; dest: Integer; LastNonSpace: Integer; HaveDelimiter: Boolean; begin Assert(ADelimiter <> ' '); SetLength(Result, Length(AString)); dest := 1; LastNonSpace := 0; HaveDelimiter := False; for c in AString do begin if (c = ' ') and HaveDelimiter then continue; // Skip this character if c = ADelimiter then begin dest := LastNonSpace + 1; HaveDelimiter := True; end else HaveDelimiter := False; Result[dest] := c; if c <> ' ' then LastNonSpace := dest; Inc(dest); end; SetLength(Result, dest - 1); end; 
+3
source share

If you use Delphi XE or higher, you can do this trivially in one line of code using a regular expression.

 program regex; {$APPTYPE CONSOLE} uses RegularExpressions; const Input = 'This , is, the Delphi , World!'; begin Writeln(TRegEx.Replace(Input, ' *, *', ',')); Readln; end. 

Naturally, this is not the fastest launch of the proposed solutions, but perhaps it does not matter to you.

+3
source share

You can use regular expressions. You want to find a separator that is preceded or followed by any number of spaces, and replace it with one copy of the separator.

 function RemoveSpacesAroundDelimiter(const AString: string; const ADelimiter: string): string; var re: TPerlRexEx; begin re := TPerlRegEx.Create; try re.RegEx := '\s*' + TPerlRegEx.EscapeRegExChars(ADelimiter) + '\s*'; re.Subject := AString; re.Replacement := TPerlRegEx.EscapeRegExChars(ADelimiter); re.ReplaceAll; Result := re.Subject; finally re.Free; end; end; 

In newer versions of Delphi, you can use the built-in RegularExpressionCore . Older versions may use the equivalent PerlRegEx module from Jan Goewaerts .

Mick previously posted an answer demonstrating this, but he deleted it because he received a regular incorrect expression (removing all spaces instead of those that are adjacent to the delimiter).

+1
source share

The easiest and easiest way is to use regular expressions. The last thing you need is a huge complex block of code to solve such a simple problem. Unfortunately, I do not have Delphi with me right now, I can not check this code, but if it is not, then it is very very close:

 s := 'This , is, the Delphi , World!'; RegEx := TRegEx.Create('[ ]*,[ ]*'); CleanStr := RegEx.Replace(s, ','); 
+1
source share

I thought it was worth adding because it would work with earlier versions of Delphi, which the solution to the string list (which I liked) does not.

It is fast enough, I believe, and quite simple to read and understand.

 function TForm1.UltraTrim(const InString : String; Delim : Char) : String; var Buf : String; i : Integer; Token : String; begin Result := ''; if Trim(InString) <> '' then begin i := 1; Buf := StringReplace(InString, Delim, #0, [rfReplaceAll]) + #0; while i < Length(Buf) do begin Token := StrPas(@Buf[i]); i := i + Length(Token) + 1; Result := Result + Delim + Trim(Token); end; Result := Copy(Result,2,Length(Result)); end; end; 
0
source share

Using the Jedi code library, @GolezTrol's answer can be reformulated using a single-line interface.

 function UltraTrim(Value: string): string; begin Result := JclStringList.Split(Value, ',').Trim.Join(',') end; 
0
source share

using this function:

 function MBTrim(iStr :string):string; const CTc= 3{Conditions Count}; CT :array[0..(CTc-1),0..1]of string= ( (' ,', ','), (', ', ','), (' ', ' ') ); var i :Integer; begin for i := 0 to CTc-1 do while Pos(CT[i,0], iStr) > 0 do iStr:= StringReplace(iStr, CT[i,0], CT[i,1], [rfReplaceAll, rfIgnoreCase]); Result:= Trim(iStr); end; 

you can just add other conditions.

for example, I add (' ', ' ') to convert a space between words like:

 'This , is, the Delphi , World!' 
0
source share

Changed again.

  while (pos(', ',s)>0) or (pos(' ,',s)>0) do begin s := StringReplace(s, ', ', ',', [rfReplaceAll]); s := StringReplace(s, ' ,', ',', [rfReplaceAll]); end; 

OK for all versions of Delphi.

-2
source share

All Articles