我必须编写一个程序来计算字符串中有多少个不同的字母。
例如,“abc”将给出3;和“abcabc”也将给出3,因为只有3个不同的字母。

我需要使用pascal,但是如果您可以帮助使用不同语言的代码,那也将非常好。

这是我的代码不起作用:

var s:string;
    i,j,x,count:integer;
    c:char;
begin
  clrscr;

  Readln(s);
  c:=s[1];
  x:=1;

  Repeat
  For i:=1 to (length(s)) do
  begin
    If (c=s[i]) then
    begin
      delete(s,i,1);
      writeln(s);
    end;
  end;
  c:=s[1];
  x:=x+1;
  Until length(s)=1;

  Writeln(x);

x是不同的字母计数器;
也许我的算法很不好..有什么想法吗?谢谢你。

最佳答案

您已经找到了解决方法,这就是为什么您的方法行不通的原因。

首先,从直觉上来说,您有一个好主意:从字符串中的第一个char开始,对其进行计数(您忘了包括计数代码),删除字符串中所有相同char的出现。这个想法效率不高,但可以奏效。您在这段代码中遇到了麻烦:

For i:=1 to (length(s)) do
begin
  If (c=s[i]) then
  begin
    delete(s,i,1);
  end;
end;

问题在于,Pascal在设置循环时将采用Length(s)值,但是您的代码通过删除字符(使用delete(s,i,1))来更改字符串的长度。您最终将看到内存不足。第二个问题是i将会发展,它是否匹配并删除了一个字符并不重要。这就是为什么不好。
Index:  12345
String: aabbb

您将测试i = 1,2,3,4,5,寻找a。当i为1时,您将找到一个匹配项,删除第一个字符,您的字符串将如下所示:
Index:  1234
String: abbb

您现在使用i = 2进行测试,这不是匹配项,因为s [2] = b。您只是跳过了一个a,并且给定的a将在数组中保留另一轮,并使您的算法对其进行两次计数。 “固定”算法如下所示:
i := 1;
while i <= Length(s) do
  if (c=s[i]) then
    Delete(s,i,1)
  else
    Inc(i);

这是不同的:在给定的示例中,如果我在1处找到匹配项,则光标不会前进,因此它将看到第二个a。另外,因为我使用的是while循环,而不是for循环,所以我不会为for循环的可能实现细节烦恼。

您的算法还有另一个问题。在删除字符串中所有出现的第一个字符的循环之后,您正在使用以下代码准备下一个循环:

c:= s [1];

问题是,如果您向该算法输入格式为aa(长度= 2,两个相同字符)的字符串,它将进入循环,删除或出现a(将s变成EMPTY字符串),然后尝试读取EMPTY字符串的第一个字符。

最后一句话:您的算法应处理输入的空字符串,返回count = 0。这是固定的算法:
var s:string;
    i,count:integer;
    c:char;
begin
  Readln(s);
  count:=0;

  while Length(s) > 0 do
  begin
    Inc(Count);
    c := s[1];
    i := 1;
    while i <= Length(s) do
    begin
      If (c=s[i]) then
        delete(s,i,1)
      else
        Inc(i);
    end;
  end;

  Writeln(Count);

  Readln;
end.

10-06 14:02
查看更多