我正在尝试将字符串作为参数传递给函数,它引发了Segmentation Fault(Core Dumped)错误。您能告诉我我在这里犯了什么错误吗?这是代码:
replaceChars(char str[], char sChar[], char rChar)
{
int i,j;
printf("rChar is %c", rChar);
printf("sChar is %s", sChar);
for(i = 0; i <= strlen(str); i++)
{
for(j = 0; j <= strlen(sChar); j++)
{
if(str[i] == sChar[j])
{
str[i] = rChar;
//printf("The New String is %c", str[i]);
}
}
}
printf("The New String is %s", str);
}
void main()
{
char myString[36], schar[36], rchar;
printf("Please enter a string:");
scanf("%[^\n]s", &myString);
printf("Which characters to replace?");
scanf(" %[^\n]c", &schar);
printf("With which character?");
scanf(" %[^\n]c", &rchar);
replaceChars(myString, schar, rchar);
}
答案 0 :(得分:2)
这里有两个问题。
首先,当您遍历str
和sChar
时:
我正在尝试将字符串作为参数传递给函数,它引发了Segmentation Fault(Core Dumped)错误。您能告诉我我在这里犯了什么错误吗?这是代码:
for(i = 0; i <= strlen(str); i++)
{
for(j = 0; j <= strlen(sChar); j++)
{
您使用<=
作为退出条件。数组索引从0开始,因此有效索引从0到length-1。您要从0到长度,所以要步进数组的末尾。读取数组末尾会调用undefined behavior。
更改条件以使用<
:
for(i = 0; i < strlen(str); i++)
{
for(j = 0; j < strlen(sChar); j++)
{
第二个问题是如何读取值:
scanf("%[^\n]s", &myString);
...
scanf(" %[^\n]c", &schar);
...
scanf(" %[^\n]c", &rchar);
%[]
格式说明符后面不需要任何字符,并且它需要一个char *
作为参数,它指向char
数组的第一个元素。在前两种情况下,您传递的是数组的地址,而不是数组本身(它会衰减为指针),并且在%[]
格式之后还有一个多余的字符。在第三种情况下,如果格式需要指向多个字符的指针,则将指针传递给单个char
。因为您只想读取一个字符,所以您想使用%c
格式说明符。
scanf("%35[^\n]", myString);
...
scanf(" %35[^\n]", schar);
...
scanf(" %c", &rchar);
还请注意,前两个字段的字段宽度限制了读取的字符数,因此您不会溢出数组。
答案 1 :(得分:0)
能否让我知道我在这里犯了什么错误?
除了@dbush个好答案之外,OP的代码也不必要地效率低下。
使用下面的更正代码,并假设str, sChar
的初始长度分别为S,C
。
for(i = 0; i < strlen(str); i++) {
for(j = 0; j < strlen(sChar); j++) {
if(str[i] == sChar[j]) {
str[i] = rChar;
}
}
}
for(i = 0; i < strlen(str); i++) {
及其后的str[i] = rChar;
要求代码查找str
的长度最多S倍,并且每个strlen(str)
都需要O(S)操作。
如果S
是一个非平凡的值,例如1000,则此1000 * 1000会很容易影响整体性能。一种简单的解决方案是只计算一次长度,或者寻找空字符。
// for(i = 0; i < strlen(str); i++) {
S = strlen(str);
for(i = 0; i < S; i++) {
// or
for(i = 0; str[i]; i++) {
内部循环也发生同样的事情。但是,精明的编译器可以看到sChar
并没有改变,并且可以利用对strlen()
的理解而不会产生会导致不同结果的副作用。通过这种优化,即使strlen(sChar)
位于较高的strlen(sChar)
循环中,也可以真正调用一次for (i...)
。
仅测试空字符仍然很容易且习惯。
// for(j = 0; j < strlen(sChar); j++)
// better as
for(j = 0; sChar[j]; j++)
但是为什么这不适用于for(i = 0; i < strlen(str); i++)
循环?
在该循环中,代码可以修改str[]
,因此编译器无法像for(j = 0; sChar[j]; j++)
那样进行优化。
这也引出了一个问题,如果替换字符rChar
是 null字符,代码应该怎么做?
如我所见,代码可以继续执行,可以多次替换为'\0
,也可以在第一次之后简单返回。
str[i] = rChar;
if (rChar == '\0') return; // Possible way to handle \0