我写了这个练习,它应该删除第一个参数字符串中出现在第二个字符串中的任何字符。但对于下面的论点来说,结果是一个分段错误。有人能向我解释一下我缺了什么吗?
#include <stdio.h>
void squeez(char s1[], char s2[])
{
int i, j, k, match;
while (s1[i] != ' ') {
match = 0;
for (k = 0; s2[k] != ' '; ++k) {
if (s1[i] == s2[k]) {
match = 1;
break;
}
}
if (match) {
i++;
} else {
s1[j++] = s1[i++];
}
}
s1[j] = ' ';
}
int main()
{
char s[] = "asdsffffsffsk";
char x[] = "sf";
squeez(s, x);
printf("%s %s", s, x);
return 0;
}
对于初学者来说,函数应该以以下方式声明
char * squeez( char s1[], const char s2[] );
这是第二个参数应该具有限定符const
,因为此参数指定的字符串在函数中不会更改。
该函数应遵循C标准字符串函数的一般约定,并返回指向结果字符串的指针。
在函数内,变量i
和j
未被初始化并且具有不确定的值。所以即使是第一次循环
int i, j, k, match;
while (s1[i] != ' ') {
// ...
调用未定义的行为。
您应该使用类型size_t
而不是这些变量的类型int
,因为类型int
可能不够大,无法存储字符串的长度。
您应该在使用变量的最小作用域中声明变量。
保持你对函数定义的方法,它可以看起来像下面的演示程序中所示的那样。
#include <stdio.h>
char * squeez( char s1[], const char s2[] )
{
size_t i = 0, j = 0;
while ( s1[i] != ' ' )
{
int match = 0;
for ( size_t k = 0; !match && s2[k] != ' '; ++k )
{
if ( s1[i] == s2[k] ) match = 1;
}
if ( !match ) s1[j++] = s1[i];
i++;
}
s1[j] = ' ';
return s1;
}
int main(void)
{
char s[] = "asdsffffsffsk";
char x[] = "sf";
puts( squeez( s, x ) );
return 0;
}
程序输出为
adk
此外,由于变量i
没有在while循环之外使用,则while循环可以替换将声明变量i
的for循环。例如
char * squeez( char s1[], const char s2[] )
{
size_t j = 0;
for ( size_t i = 0; s1[i] != ' '; i++ )
{
int match = 0;
for ( size_t k = 0; !match && s2[k] != ' '; ++k )
{
if ( s1[i] == s2[k] ) match = 1;
}
if ( !match ) s1[j++] = s1[i];
}
s1[j] = ' ';
return s1;
}
我注意到I和j没有初始化。事实上,您的代码是可行的,没有我提出的问题。这是我试过的代码。
#include <stdio.h>
void squeez(char s1[], char s2[])
{
int index1 = 0, position = index1, index2 = 0;
int match = 0;
while (s1[index1] != ' ')
{
match = 0;
for (index2 = 0; s2[index2] != ' '; index2++)
{
if (s1[index1] == s2[index2])
{
match = 1;
break;
}
}
if (match)
index1++;
else
s1[position++] = s1[index1++];
}
s1[position] = ' ';
}
int main()
{
char s[] = "asdsffffsffsk";
char x[] = "sf";
squeez(s, x);
printf("%s %s", s, x);
return 0;
}