23

How can I count the number of occurrences of a certain character in a string in Delphi?

For instance, assume that I have the following string and would like to count the number of commas in it:

S := '1,2,3';

Then I would like to obtain 2 as the result.

Andreas Rejbrand
  • 105,602
  • 8
  • 282
  • 384

7 Answers7

40

You can use this simple function:

function OccurrencesOfChar(const S: string; const C: char): integer;
var
  i: Integer;
begin
  result := 0;
  for i := 1 to Length(S) do
    if S[i] = C then
      inc(result);
end;
Andreas Rejbrand
  • 105,602
  • 8
  • 282
  • 384
20

Even though an answer has already been accepted, I'm posting the more general function below because I find it so elegant. This solution is for counting the occurrences of a string rather than a character.

{ Returns a count of the number of occurences of SubText in Text }
function CountOccurences( const SubText: string;
                          const Text: string): Integer;
begin
  Result := Pos(SubText, Text); 
  if Result > 0 then
    Result := (Length(Text) - Length(StringReplace(Text, SubText, '', [rfReplaceAll]))) div  Length(subtext);
end;  { CountOccurences }
RobertFrank
  • 7,332
  • 11
  • 53
  • 99
  • 1
    Interesting point of view! Maybe you could simplify the first statement to `Result := Pos(SubText, Text); if Result > 0 then...` [+1] – TLama Mar 08 '13 at 19:07
  • That's beautiful Robert. – Sam Dec 18 '13 at 00:08
  • This is sick and beautiful :) Obviously it's not very efficient but the trick itself behind the code is something programming should be about! – dkellner Apr 20 '18 at 14:53
  • 4
    Cute, but I'd hate finding this in code. If you're reading someone's code and run into this, you have to stop and think about how it works, then check to see if it's right. Code Should Be Clear. Sorry, but I don't find this elegant. To me, elegant means concise and obviously correct with a small + for clever. – Guy Gordon Jun 13 '18 at 13:55
  • 1
    It is also significantly slower than a simple loop over the characters. – Andreas Rejbrand Nov 06 '19 at 11:48
18

And for those who prefer the enumerator loop in modern Delphi versions (not any better than the accepted solution by Andreas, just an alternative solution):

function OccurrencesOfChar(const ContentString: string;
  const CharToCount: char): integer;
var
  C: Char;
begin
  result := 0;
  for C in ContentString do
    if C = CharToCount then
      Inc(result);
end;
Ken White
  • 123,280
  • 14
  • 225
  • 444
12

This one can do the work for if you're not handling large text

...

uses RegularExpressions;

...

function CountChar(const s: string; const c: char): integer;
begin
 Result:= TRegEx.Matches(s, c).Count
end;
Raul
  • 656
  • 5
  • 17
2

You can use the benefit of StringReplace function as:

function OccurencesOfChar(ContentString:string; CharToCount:char):integer;
begin
   Result:= Length(ContentString)-Length(StringReplace(ContentString, CharToCount,'', [rfReplaceAll, rfIgnoreCase]));
end;
Marwan Almukh
  • 201
  • 3
  • 12
1

Simple solution and good performance (I wrote for Delphi 7, but should work for other versions as well):

function CountOccurences(const ASubString: string; const AString: string): Integer;
var
  iOffset: Integer;
  iSubStrLen: Integer;
begin
  Result := 0;

  if (ASubString = '') or (AString = '') then
    Exit;

  iOffset := 1;
  iSubStrLen := Length(ASubString);
  while (True) do
  begin
    iOffset := PosEx(ASubString, AString, iOffset);
    if (iOffset = 0) then
      Break;
    Inc(Result);
    Inc(iOffset, iSubStrLen);
  end;
end;
Alieh S
  • 170
  • 2
  • 8
  • 1
    That Copy will make the loop slower. You can do without it if you use [System.Pos](http://docwiki.embarcadero.com/Libraries/en/System.Pos) or [AnsiStrings.PosEx](http://docwiki.embarcadero.com/Libraries/en/System.AnsiStrings.PosEx) with the offset option. – LU RD Sep 10 '20 at 09:32
  • Correct remark, thanks. Unfortunately in Delphi 7 the Pos function does not have an Offset parameter. – Alieh S Sep 10 '20 at 10:54
  • 1
    If you look in StrUtils, you will find the PosEx function in Delphi 7. – LU RD Sep 10 '20 at 12:38
0

Ummm... Am I missing something? Why not just...

      kSepChar:=',';//to count commas
      bLen:=length(sLineToCheck);
      bCount:=0;//The numer of kSepChars seen so far.
      bPosn:=1;//First character in string is at position 1
      for bPosn:=1 to bLen do begin
         if sLineToCheck[bPosn]=kSepChar then inc(bCount);
         end;//
  • This is more or less identical to the accepted answer. – LU RD Feb 10 '21 at 15:55
  • 1
    LU RD... Ummm...You're quite right, of course it is. Sorry I missed its previous appearance here. (I've used forums for years, do have SOME idea. Apologies for missing that.) – wywtk-com Feb 11 '21 at 17:12