在C语言中反转字符串

3
以下代码有什么问题?
#define N 30
int main() {
    char str[N], new_str[N];
    int i,len;
    printf("Please enter 20 letters. \n");
    scanf("%s", str);
    len = strlen(str);
    printf("The length of str is  %d ", len);
    for (i=0; i< len; i++)
        new_str[i]=str[len-1-i];
    printf("The result is: %s\n", new_str);
    return 1;
}

我检查了程序,对于长度小于16个字符的字符串,程序运行正常。而对于长度大于16个字符的字符串,在末尾会返回未定义的字符:
  Please enter 20 letters.
  1234567891111111

  The result is: 1111111987654321q=V?.

然而,如果我用 "" 初始化 str, new_str,问题就解决了。我仍然想知道是什么导致了这个问题。

1
在for循环完成后,您必须为new_str添加\0字符,例如new_str[i] = '\0'。 - Raghuram
4个回答

10

你需要添加空终止符:

new_str[len] = '\0';

否则,在最后一个字符之后有垃圾,因此该字符串没有结束


strlen(str) 函数不考虑空终止符。您正在处理字符串的字符,不包括空终止符。 - dda
1
@dda:即使它被包含在内,反转也会将终止符放置在开头。 :-) - Vlad
2
请注意,许多字符串函数也会添加\0,例如strcpystrcat等。对于常量赋值,例如const char* s = "string";也是如此。但是,在手动操作字符串中的单个字符时不需要添加! - Mr Lister
printf函数将仅打印'\0'之前的字符,因为%s表示字符串,在C语言中,字符串被定义为char缓冲区直到\0 - MByD
那么我应该在哪里添加空字符终止符? - Numerator
显示剩余8条评论

9

您需要在new_str中添加一个空终止符,否则printf不知道何时停止。或者您可以像这样原地反转字符串。

char s[] = "StackOverflow";
size_t l = strlen(s);
int i, j, k;
k = l/2;
// Work with half the length
for (i=0; i<k; i++) {
  // swap the two bytes
  j=s[i];
  s[i]=s[l-1-i];
  s[l-1-i]=j;
}

谢谢大家 :-) 我想要最快的反转。但是如果你在2字节以上的编码上使用它,这段代码就会像幼儿园杂耍比赛中的玻璃一样破碎 :-) - dda
@dda:复制反转的变体也是如此。实际上,UTF-8等完全是另一回事:这样的“字符串”不应该被称为“字符串”,并且我认为只应该使用特殊库(也许是自制的)来处理它们,手动处理太容易出错了。(也许有人知道C语言的这样一个库吗?) - Vlad
因为很多原因。例如:说s++并不会将你移到下一个字符;strlen(s)并不能给出真正的长度;并非每个非NULL字符在任意位置都是有效的 - Vlad
1
@Vlad 对于严肃的商业目的,你需要使用IBM的ICU库。不过对于简单的事情来说,可能有点过头了。 - Mr Lister
1
我同意@Vlad的观点。UTF-8字符串是字节数组,其中每个元素的长度可变。要获取下一个字符,您需要查看每个字节,并根据其值将其添加到堆栈中或继续前进。 - dda
显示剩余3条评论

2

字符串应该以零结尾。在scanf之后,str已经被赋值了,但是new_str没有被赋值,所以它仍然包含垃圾值。在循环之后,前20个字符已经被设置,但是你仍然需要添加一个\0


1

new_str 没有以 NUL 结尾。

在从 str 复制所有字符后,您需要像这样在 new_str 的末尾添加 '\0':

new_str[i] = '\0';

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接