简体   繁体   English

C:可以反转字符数组,但不能反转字符串

[英]C: Can reverse array of chars, but not string

I made a simple program to reverse a string in C. Here is my code: 我做了一个简单的程序来反转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;
  }

and my result is, as expected raboof . 我的结果是,正如预期的raboof

Now, if I swap char istring[] = {'f','o','o','b','a','r'}; 现在,如果我交换char istring[] = {'f','o','o','b','a','r'}; , with char istring[] = "foobar"; ,用char istring[] = "foobar"; , I get nothing as my output. ,我的输出没有任何结果。 What's wrong? 怎么了?

Thanks in advance. 提前致谢。

(Sorry if this is a total newbie question) (对不起,如果这是一个总的新手问题)

sizeof "foobar" is 7 , not 6 . sizeof "foobar"7 ,而不是6 C strings are NUL terminated with the '\\0' character. C字符串以'\\0'字符终止。

Your first example works because you fail to NUL terminate your string, and so the 'r' and 'f' swap. 你的第一个例子是有效的,因为你没有NUL终止你的字符串,所以'r''f'交换。 You're likely lucking out in that the address space following the reversed string evaluates to a zero (which equates '\\0' ), terminating the string. 您可能会幸运的是,反向字符串后面的地址空间评估为零(等于'\\0' ),终止字符串。 Otherwise, printing a non-terminated string invokes undefined behaviour. 否则,打印未终止的字符串会调用未定义的行为。

With "foobar" , the 'f' and '\\0' will be swapped, and your resulting C string will effectively be zero-length. 使用"foobar" ,将交换'f''\\0' ,并且生成的C字符串实际上将为零长度。

Solve this by using strlen to get the length of a string, not sizeof which gets the length of the block of memory. 通过使用strlen获取字符串的长度来解决这个问题,而不是获取内存块长度的sizeof You'll need to include the string.h header. 您需要包含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);

In C, a string is a null terminated array of characters. 在C中,字符串是以空字符结尾的字符数组。 In your original program, istring is not a string but an array of characters with no null byte at the end. 在原始程序中, istring不是字符串,而是一个字符数组,最后没有空字节。

While you successfully reverse the characters, revstring is not a string because there is no terminating null byte at the end. 在成功反转字符时, revstring不是字符串,因为末尾没有终止空字节。 As such, when you attempt to print it as a string using the %s format specifier for printf , it searches past the end of the array. 因此,当您尝试使用printf%s格式说明符将其作为字符串打印时,它会搜索超出数组末尾的内容。 Reading beyond the bounds of an array is undefined behavior . 超出数组边界的读取是未定义的行为

One of the ways undefined behavior can manifest itself is that the program appears to work properly. 未定义行为可以表现出来的一种方式是程序似乎正常工作。 In your case, you got "lucky" and got the expected result. 在你的情况下,你得到了“幸运”并获得了预期的结果。

When you define istring as istring[] = "foobar"; 当你将istring定义为istring[] = "foobar"; you initialize it with a string constant which contains a null terminating byte. 使用包含空终止字节的字符串常量初始化它。 So this definition is actually one byte larger then the prior one. 所以这个定义实际上比前一个大一个字节。

When you reverse the characters, you're actually including the null byte. 当你反转字符时,你实际上包括空字节。 So the resulting array contains the null byte first followed by the other characters. 因此,结果数组首先包含空字节,然后是其他字符。 Then when you print it, the null byte is seen first so what you have is an empty string. 然后当你打印它时,首先看到空字节,所以你拥有的是一个空字符串。

In your loop, use strlen(istring) instead of sizeof(istring) as the upper bound. 在循环中,使用strlen(istring)而不是sizeof(istring)作为上限。 Then add the null byte at the end. 然后在末尾添加空字节。

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';

If you define istring as an array of characters, you need to allocate an extra byte to revstring and keep sizeof when checking the upper bound: 如果将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';

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM