【问题标题】:Create function which copy all values from one char array to another char array in C (segmentation fault)创建函数,将所有值从一个 char 数组复制到 C 中的另一个 char 数组(分段错误)
【发布时间】:2020-04-03 11:26:11
【问题描述】:

我有一个任务。我必须将所有值从一个 char 数组 (sentence[]) 复制到另一个空 char 数组 sentence2[]),但我不知道为什么会出现分段错误。他们还告诉我们,我们必须创建自己的 strlen 函数来检查字符串的长度。

这是我的代码

#include <stdio.h>
#include <stdlib.h>

int new_strlen (char *tab)
{
    int i;
    for (i = 0; tab[i] != '\0'; ++i);    
    return i;
}

int copyText(char from[],char to[],int max)
{
    int i, j;
    if (new_strlen(from) <= max)
    {
        for(int i = 0; i != '\0'; i++) {
            to[i] = from[i];
        }
        to[i+1] = '\0'; 
    }
    return 0;
}


int main (int argc, char *argv[])
{
    char sentence[] = "C is \n a \n programming \t language";
    char sentence2[1000];

    copyText(sentence, sentence2, 1000);
    printf("Show my array: %s \n", sentence2);

    return 0;
}

【问题讨论】:

  • 这个i != '\0' 应该是from[i] != '\0'。也只在那个 for 循环中执行 i = 0 而不是 int i = 0。并将to[i+1] 更改为to[i]
  • @Eraklon 这是对这个问题的一个非常完整的答案。你应该这样发布。

标签: c arrays


【解决方案1】:

以下是错误:

int copyText(char from[],char to[],int max)
{
    int i, j;  // minor problem: j is useless

    if (new_strlen(from) <= max)  //  should be < instead of <=
    {
        for(int i = 0; i != '\0'; i++) {  // here you declare a new i variable
                                          // unrelated to the i declared at the beginning
            to[i] = from[i];
        }

        to[i+1] = '\0';        // here you use again the i declared at the beginning
                               // which hasn't been initialized
                               // and i already is the index of the terminator
                               // therefore it should be to[i]
    }

    return 0;
}

此行包含两个错误:

for(int i = 0; i != '\0'; i++)
  1. i != '\0' 等价于i != 0。现在你可能已经意识到你的错误了。其实你需要测试from[i]是否为0。

  2. to[i+1] = '\0':这里i已经被for循环递增,i已经包含了\0终止符的索引,因此它应该是to[i] = '\0'

  3. 最后,在这一行中,您在函数的开头使用了 i 变量声明,因为您从未为其分配任何内容,因此该函数的内容是不确定的,这很可能是导致分段错误的这一行: to[i+1] = '\0';

最后还有一个问题,如果字符串的长度是max的话会出问题:

if (new_strlen(from) <= max)  //  should be < instead of <=

如果字符串的长度为最大值,那么\0 将被放在缓冲区末尾之外,因此缓冲区溢出。

你想要这个:

int copyText(char from[],char to[],int max)
{
    if (new_strlen(from) < max)
    {
        int i;
        for(i = 0; from[i] != '\0'; i++)
            to[i] = from[i];
        }

        to[i] = '\0';
    }

    return 0;
}

【讨论】:

  • 最后一个代码有bug。 for(int i = 0; ... --> for(i = 0; ....
  • 您在第一个示例中修复了它,但在最后一个示例中没有修复
【解决方案2】:

copyText的三个问题

  1. i != '\0' 应该是from[i] != '\0'

  2. int i = 0 应该只是 i = 0for 循环中,以免影响另一个 i 并且这样做也毫无意义。

  3. to[i+1] 应该只是to[i]

【讨论】:

    【解决方案3】:

    我像你说的那样修改了我的程序。 我的程序

    #include <stdio.h>
    #include <stdlib.h>
    
    int new_strlen (char *tab)
    {
        int i;
        for (i = 0; tab[i] != '\0'; ++i);    
        return i;
    }
    
    int copyText(char from[],char to[],int max)
    {
        if (new_strlen(from) < max)
        {
            int i;
            for(int i = 0; from[i] != '\0'; i++)
            {
                to[i] = from[i];
            }
    
            to[i] = '\0';
        }
    
        return 0;
    }
    
    int main (int argc, char *argv[])
    {
        char sentence[] = "C is \n a \n programming \t language";
        char sentence2[30];
    
        copyText(sentence, sentence2, 30);
        printf("Show my array: %s \n", sentence2);
    
        return 0;
    }
    

    输出

    Show my array: h�ܙ� 
    

    为什么我的输出是错误的?

    【讨论】:

      【解决方案4】:

      我解决了你的问题。您刚刚在 copytext() 函数的 for 循环中错过了 'form[i]'。并使用 (new_strlen(from)

      #include <stdio.h>
      #include <stdlib.h>
      
      int new_strlen (char *tab)
      {
          int i;
          for (i = 0; tab[i] != '\0'; ++i);
          return i;
      }
      int copyText(char from[],char to[],int max)
      {
          if (new_strlen(from) <= max)
          {
              for(int i = 0; from[i] != '\0'; i++)
              {
                  to[i] = from[i];
              }
          }
          return 0;
      }
      int main (int argc, char *argv[])
      {
          char sentence[] = "C is \n a \n programming \t language";
          char sentence2[1000];
          copyText(sentence, sentence2, 1000);
          printf("Show my array: %s \n", sentence2);
          return 0;
      }
      

      【讨论】:

        【解决方案5】:

        我有一个任务。我必须从一个字符数组中复制 所有值 (sentence[]) 到另一个空字符数组 sentence2[]),

        你必须复制所有值然后是函数的第三个参数copyText

        int copyText(char from[],char to[],int max);
        

        是多余的。一般来说,它确实允许复制所有值

        我认为“所有值”是指存储在源数组中的字符串的所有字符。

        要将字符串从一个字符数组复制到另一个字符数组,不需要计算字符串长度的函数。这也是多余的。

        函数copyText的返回类型int没有意义。从中复制存储字符串的字符数组应具有限定符const

        标准 C 字符串函数遵循目标字符数组应该是第一个函数参数并且函数应该返回指向目标字符数组的指针的约定。

        在函数中声明的变量j没有被使用

        int i, j;
        

        分段错误的原因是您使用未初始化的变量 i 来设置目标数组中的终止零字符。那就是你声明了一个未初始化的变量 i

        int i, j;
        

        然后在其内部循环中的 if 语句中

        if (new_strlen(from) <= max)
        {
            for(int i = 0; i != '\0'; i++) {
                ^^^^^^^^^
                to[i] = from[i];
            }
            to[i+1] = '\0'; 
        }
        

        您又声明了一个变量 i,它在循环外不会存在。循环本身永远不会迭代,因为循环的条件

        i != '\0'
        

        不满意。变量 i 由 0 初始化,并与写入为八进制字符文字的相同 0 进行比较。

        所以在这个声明中

            to[i+1] = '\0'; 
        

        这里使用了我在if语句之前在函数开头声明的初始化变量。

        我确信你需要写的是一个类似于标准 C 函数 strcpy 的东西。

        在这种情况下,程序可以如下所示

        #include <stdio.h>
        
        char * copyText( char to[], const char from[] )
        {
            for ( char *p = to; ( *p++ = *from++ ) != 0; ) { /* empty */ }
        
            return to;
        }
        
        
        int main (void)
        {
            enum { N = 1000 };
            char sentence[] = "C is \n a \n programming \t language";
            char sentence2[N];
        
            printf("Show my array: %s \n", copyText(sentence2, sentence ) );
        
            return 0;
        }
        

        程序输出是

        Show my array: C is 
         a 
         programming     language 
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-01-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多