【问题标题】:C: Can reverse array of chars, but not stringC:可以反转字符数组,但不能反转字符串
【发布时间】:2016-09-04 03:08:06
【问题描述】:

我用 C 编写了一个简单的程序来反转字符串。这是我的代码:

  #include <stdio.h>

  int main(){
          char istring[] = {'f','o','o','b','a','r'};

          char revstring[sizeof(istring)];

          for(int i = 0; i < sizeof(istring); i++){
                  int cplace = sizeof(istring)-i-1;
                  revstring[cplace] = istring[i];
          }
          printf("%s",revstring);
          return 0;
  }

我的结果正如预期的那样是raboof

现在,如果我将char istring[] = {'f','o','o','b','a','r'};char istring[] = "foobar"; 交换,我将一无所获。怎么了?

提前致谢。

(对不起,如果这是一个新手问题)

【问题讨论】:

    标签: c arrays string char


    【解决方案1】:

    sizeof "foobar"7,而不是 6。 C 字符串以 '\0' 字符为 NUL。

    您的第一个示例有效,因为您未能 NUL 终止您的字符串,因此 'r''f' 交换。您可能很幸运,在反转字符串 评估 之后的地址空间为零(相当于'\0'),终止了字符串。否则,打印未终止的字符串会调用未定义的行为。

    使用"foobar"'f''\0' 将被交换,并且生成的 C 字符串实际上是零长度。

    通过使用strlen 来获取字符串的长度来解决这个问题,而不是使用sizeof 来获取内存块的长度。您需要包含 string.h 标头。

    char str[] = "foobar";
    size_t str_len = strlen(str);
    
    char rev[str_len + 1];
    rev[str_len] = '\0';
    
    for (int i = 0; i < str_len; i++)
        rev[i] = str[str_len - i - 1];
    
    printf("%s\n", rev);
    

    【讨论】:

      【解决方案2】:

      在 C 中,字符串是一个以空字符结尾的字符数组。在您的原始程序中,istring 不是字符串,而是末尾没有空字节的字符数组。

      当您成功反转字符时,revstring 不是字符串,因为末尾没有终止空字节。因此,当您尝试使用%s 格式说明符将其作为字符串打印为printf 时,它会搜索到数组的末尾。超出数组范围的读取是undefined behavior

      未定义行为的一种表现方式是程序似乎可以正常工作。在你的情况下,你得到了“幸运”并得到了预期的结果。

      当您将istring 定义为istring[] = "foobar"; 时,您使用包含空终止字节的字符串常量对其进行初始化。所以这个定义实际上比前一个大一个字节。

      当您反转字符时,您实际上包含了空字节。因此,结果数组首先包含空字节,然后是其他字符。然后当你打印它时,首先看到的是空字节,所以你得到的是一个空字符串。

      在您的循环中,使用strlen(istring) 而不是sizeof(istring) 作为上限。然后在末尾添加空字节。

      char istring[] = "foobar";
      char revstring[sizeof(istring)];
      
      for(int i = 0; i < strlen(istring); i++){
          int cplace = strlen(istring)-i-1;
          revstring[cplace] = istring[i];
      }
      revstring[strlen(istring)] = '\0';
      

      如果将istring定义为字符数组,则需要为revstring分配一个额外的字节,并在检查上限时保留sizeof

      char istring[] = {'f','o','o','b','a','r'};
      char revstring[sizeof(istring)+1];
      
      for(int i = 0; i < sizeof(istring); i++){
          int cplace = sizeof(istring)-i-1;
          revstring[cplace] = istring[i];
      }     
      revstring[sizeof(istring)] = '\0';
      

      【讨论】:

        猜你喜欢
        • 2022-11-05
        • 1970-01-01
        • 2020-02-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多