简体   繁体   English

C反向字符串函数得到奇怪的输出

[英]C reverse string function getting weird output

I'm trying to understand pointers and made a reverse string function. 我正在尝试理解指针并制作了反向字符串函数。
code: 码:

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

char *reverseString(char string[]){
    int i;
    int len = strlen(string);
    char reversedString[len];  
    for (i = 0; i < len; i++){
        reversedString[i] = string[(len - 1) - i];
    }
    printf("%s", reversedString); //print it out

    return reversedString; //return pointer to first element of reversed string
}

int main (){
    char string[6] = "kitten";
    int i;
    char *p = reverseString(string);
    return (0);

}

My goal is to reverse the string "kitten" and print the reversed string. 我的目标是扭转字符串“小猫”并打印反转的字符串。 I expect the output "nettik" but I get "nettik ". 我希望输出“nettik”,但我得到“nettik ”。 Why am I getting these weird characters? 为什么我会得到这些奇怪的角色?

Stop! 停止! First of all, you're making a classic mistake beginners often make when they learn about pointers. 首先,你在初学者学习指针时经常会犯一个经典的错误。 When you write: 当你写:

char *reverseString(char string[]) {
    ...
    char reversedString[len];
    return reversedString;
}

You're returning a pointer to where it was , not is: the memory actually gets freed when you leave the function, so there's no guarantee that the memory you think contains your reversed string isn't already getting reused by something else. 你返回一个指针, 在那里,不就是:记忆,当你离开的功能,所以没有保证你觉得内存包含您的反向字符串尚未得到别的东西再利用实际上得到释放。 This way, your program will fail catastrophically. 这样,您的程序将灾难性地失败。

However, you're printing the reversed string before returning it, so it's no huge problem yet . 但是,你打印的逆转字符串返回之前,所以它是没有大问题 What's going wrong there, then, is that your string isn't properly zero-terminated. 那么,那里出现的问题是你的字符串没有被正确地终止。

A string in the C language needs room to store its final '\\0' byte: char string[6] = "kitten"; C语言中的字符串需要空间来存储其最后的'\\0'字节: char string[6] = "kitten"; is too small to hold the zero-terminated string { 'k', 'i', 't', 't', 'e', 'n', '\\0' } . 太小而不能保持零终止字符串{ 'k', 'i', 't', 't', 'e', 'n', '\\0' } Similarly, when you call printf("%s", reversedString) , you haven't properly terminated the string with '\\0' , so printf keeps looking for the end of the string and prints out whatever junk is in memory where reversedString is allocated. 类似地,当你调用printf("%s", reversedString) ,你还没有用'\\0'正确终止字符串,所以printf一直在查找字符串的结尾并打印出内存中的任何垃圾,其中reversedString是分配。

You should try: 你应该试试:

  • making your function return void , 让你的函数返回void
  • allocating 7 bytes for your original string, 为原始字符串分配7个字节,
  • allocating strlen(string) + 1 (which will also be 7) bytes for your new string, and 为新字符串分配strlen(string) + 1 (也将是7)个字节,和
  • writing a '\\0' to the end of your new string after looping through the old one in reverse. 在反向循环旧字符串之后,将'\\0'写入新字符串的末尾。

There are at least two major bugs in your code. 您的代码中至少存在两个主要错误。 There could be more. 还有更多。

First, the call to strlen causes undefined behaviour because you aren't passing it a null-terminated string. 首先,对strlen的调用会导致未定义的行为,因为您没有将它传递给以null结尾的字符串。 The reason for this is that your char array isn't large enough for the null terminator character: 原因是你的char数组不足以容纳null终止符:

char string[6] = "kitten";

You need 你需要

char string[7] = "kitten";

or 要么

char string[] = "kitten";

Second, you are returning a pointer to a local array, namely reversedString . 其次,您将返回指向本地数组的指针,即reversedString De-referencing that would also cause undefined behaviour. 取消引用也会导致未定义的行为。 You can solve this by wither reversing the string in-place, or passing a pointer to a buffer of the same length as the input. 你可以通过将字符串就地反转,或者将指针传递给与输入相同长度的缓冲区来解决这个问题。 Remember that the reversed string must also be null-terminated. 请记住,反向字符串也必须以空值终止。

The function is wrong. 功能错了。

Firts of all it returns pointer to a local array that will be destroyed after exiting the function 所有它的第一个返回指向退出函数后将被销毁的本地数组的指针

//,,,
char reversedString[len];  
//...
return reversedString; //return pointer to first element of reversed string

Secondly the reversed string shall have terminating zero. 其次,反向串应终止为零。 However you declare an array that has no space for the terminating zero. 但是,您声明一个没有空间用于终止零的数组。

Also this array in main defined incorrectly 此主数组中的此数组也定义错误

char string[6] = "kitten";

because it does not include terminating zero. 因为它不包括终止零。

And at last it is a bad design of the function. 最后,这是一个糟糕的功能设计。

If you want to copy the source string in the destination string then the both character arrays should be declared as function parameters. 如果要在目标字符串中复制源字符串,则应将两个字符数组声明为函数参数。 Moreover the source array should be declared as a constant array. 此外,源数组应声明为常量数组。

The function can look the following way 该功能可以通过以下方式查看

char *reverseCopyString( char s1[], const char s2[] )
{
    size_t n = strlen( s2 );

    for ( size_t i = 0; i < n; i++ ) s1[i] = s2[n - i - 1];
    s1[n] = '\0';

    return s1;
}

Or you could define the function such a way that ir reverse the source string. 或者您可以定义函数,以便反转源字符串。 For example 例如

char *reverseString( char s[] )
{
    size_t n = strlen( s );

    for ( size_t i = 0; i < n / 2; i++ )
    {
        char c = s[i];
        s[i] = s[n - i - 1];
        s[n - i - 1] = c;
    }        

    return s;
}

Take into account that string literals are immutable in C and may not be changed. 考虑到字符串文字在C中是不可变的,可能不会被更改。 Any attempt to change a string literal results in undefined behaviour of the program. 任何更改字符串文字的尝试都会导致程序的未定义行为。

Here is a demonstrative program 这是一个示范计划

#include <stdio.h>
#include <string.h>

char *reverseCopyString( char s1[], const char s2[] )
{
    size_t n = strlen( s2 );

    for ( size_t i = 0; i < n; i++ ) s1[i] = s2[n - i - 1];
    s1[n] = '\0';

    return s1;
}

char *reverseString( char s[] )
{
    size_t n = strlen( s );

    for ( size_t i = 0; i < n / 2; i++ )
    {
        char c = s[i];
        s[i] = s[n - i - 1];
        s[n - i - 1] = c;
    }        

    return s;
}

int main( void )
{
    char *s1 = "Hello gilianzz";
    char s2[16];

    puts( s1 );
    puts( reverseCopyString( s2, s1 ) );
    puts( reverseString( s2 ) );
}    

The program output is 程序输出是

Hello gilianzz
zznailig olleH
Hello gilianzz

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

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