在 Object pascal 中计算字符串中的不同字符

Count distinct characters in a string in Object pascal

美好的一天, 我制作的代码应该计算字符串中的不同字符,我的代码已通过多个输入进行测试,但无法计算此输入中的字符:

zcinitufxoldnokacdvtmdohsfdjepyfioyvclhmujiqwvmudbfjzxjfqqxjmoiyxrfsbvseawwoyynn 

它有将近80个字符,Pascal可以读取的最大字符串长度为256个字符。 我找不到更好的算法来解决这个问题,所以我正在寻求该领域专家或任何愿意分享知识的人的帮助。

我想我的代码在每个循环中都跳转了一个字符。

这是我的代码:

function freq(char: char; username : String): Integer;
var 
   i, auxfreq: Integer;
begin
    auxfreq:= 0;
    for i:= 1 to length(username) do
        if char = username[i] then
            auxfreq:= auxfreq + 1;
            //writeln(freq);    
    freq:= auxfreq;         
end; 

function OddUserName(username : String): Boolean;
var
    usernameaux : String;
    length_usernameaux, i : Integer;
    Result : Boolean;

begin
    Result:= false;
    usernameaux:= username;
    i:= 0;
    repeat
        i +=1; 
        length_usernameaux:= length(usernameaux);
        if freq(usernameaux[i], usernameaux) <> 1 then 
            delete(usernameaux, i, 1);
    until i = length_usernameaux;
    // length(usernameaux) is supposed to be the number of the distinct characters.
    
    {if length(usernameaux) mod 2 <> 0 then // you will have to ignore this.
        Result:= true; // odd}

    //writeln(usernameaux); 
    //writeln(length(usernameaux));
    OddUserName:= Result; // ignore this too    
end; 

非常感谢您的帮助。

当您从字符串中 delete() 个字符时,您没有正确考虑字符串长度的变化。

如果 username 为空,您最终会访问无效字符,因为您的 repeat 循环试图访问索引 1 处的字符,该字符不存在。实际上,您最终陷入无限循环,因为 i = length_usernameaux 将始终为 False,因为 i 从 1 开始并向上递增,但 length_usernameaux 始终为 0(好吧,至少,循环运行直到i 溢出为负值并最终递增回 0,但到那时您可能已经在这种情况发生之前崩溃了您的代码。

如果 username 不为空,则在 每个 循环迭代中递增 i,这将跳过 next 字符时 delete()i 处输入一个字符。 i 需要在字符被 delete() 时保持相同的索引,因为 下一个 字符将向下滑动以占据字符的索引刚刚 delete'。仅当不是 delete() 字符时才增加 i

试试这个:

function freq(charToFind: char; username : String): Integer;
var 
  i, auxfreq: Integer;
begin
  auxfreq := 0;
  for i := 1 to Length(username) do
  begin
    if charToFind = username[i] then
      auxfreq := auxfreq + 1;
  end;
  //writeln(freq);    
  freq := auxfreq;         
end; 

function OddUserName(username : String): Boolean;
var
  usernameaux : String;
  length_usernameaux, i : Integer;
  Result : Boolean;
begin
  Result := false;
  usernameaux := username;
  length_usernameaux := Length(usernameaux);
  i := 1;
  while i <= length_usernameaux do
  begin
    if freq(usernameaux[i], usernameaux) > 1 then
    begin
      Delete(usernameaux, i, 1);
      length_usernameaux := length_usernameaux - 1;
    end else
    begin
      i = i + 1;
    end;
  end;
  // length_usernameaux is supposed to be the number of the distinct characters.
    
  {if length_usernameaux mod 2 <> 0 then // you will have to ignore this.
    Result := true; // odd}

  //writeln(usernameaux); 
  //writeln(length_usernameaux);
  OddUserName := Result; // ignore this too    
end;

如果您只需要获取某个字符串中不同字符的数量,您可以使用如下简单的方法:

function CountDistinctCharacters(InputString: string): Integer;
var I: Integer;
    //String for storing all distinct characters
    DistinctChars: string;
begin
  //Loop trough every character in input string
  for I := 1 to Length(InputString) do
  begin
    //Use Pos function to find position of specific character in DistinctChars string
    //Function returns 0 if character is not found
    if Pos(InputString[I], DistinctChars) = 0 then
    begin
      //If character isn't found in DistinctChars string add it to it
      DistinctChars := DistinctChars+InputString[I];
    end;
  end;
  //Finaly check the lenght of DistinctChars string to get the number of distinct character
  //found and return it as function result
  Result := Length(DistinctChars);
end;

如果您还需要有关输入字符串中存在哪些字符的信息,您可以不使用本地 DistinctChars 字符串变量,而是将字符串作为 var pamaeter 传递给您的函数,如下所示:

//Pass external string as var parameter to your function in order to allow function to
//fill it with all distinct characters
function CountDistinctCharacters(InputString: string; var DistinctChars: string): Integer;
var I: Integer;
begin
  //Loop trough every character in input string
  for I := 1 to Length(InputString) do
  begin
    //Use Pos function to find position of specific character in DistinctChars string
    //Function returns 0 if character is not found
    if Pos(InputString[I], DistinctChars) = 0 then
    begin
      //If character isn't found in DistinctChars string add it to it
      DistinctChars := DistinctChars+InputString[I];
    end;
  end;
  //Finaly check the lenght of DistinctChars string to get the number of distinct character
  //found and return it as function result
  Result := Length(DistinctChars);
end;

但是,如果您还想了解输入字符串中每个字符的数量,那么您将不得不为结果使用一些数据结构,以允许存储成对的数据,例如 TDictionary 或者记录数组,其中每个记录存储一对信息(字符和出现次数)。

我已经设法用我的方式修复它,多亏了你的帮助。 我所做的只是在删除重复字符后将索引减一。 像这样:

function OddUserName(username : String): Boolean;
var
    usernameaux : String;
    length_usernameaux, i : Integer;
    //Result : Boolean;

begin
    Result:= false;
    usernameaux:= username;
    i:= 0;
    repeat
        i +=1; 
        length_usernameaux:= length(usernameaux);
        if freq(usernameaux[i], usernameaux) <> 1 then 
        begin   
            delete(usernameaux, i, 1);
            i-=1; // <----- added 
        end;    
    until i = length_usernameaux;
    
    if length(usernameaux) mod 2 <> 0 then
        Result:= true; // odd

    //writeln(usernameaux); 
    //writeln(length(usernameaux));
    OddUserName:= Result;   
end;