我必须编写一个程序来计算字符串中有多少个不同的字母。
例如,“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.