将字符数组作为函数参数传递

时间:2018-10-03 20:03:43

标签: c arrays string function

我正在尝试将字符串作为参数传递给函数,它引发了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);

}

2 个答案:

答案 0 :(得分:2)

这里有两个问题。

首先,当您遍历strsChar时:

  

我正在尝试将字符串作为参数传递给函数,它引发了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