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

时间:2015-08-19 21:07:36

标签: c

我试图理解指针并制作反向字符串函数 代码:

#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);

}

我的目标是扭转字符串&#34;小猫&#34;并打印反转的字符串。我期待输出&#34; nettik&#34;但我得到了&#34;nettik���&#34;。为什么我会得到这些奇怪的角色?

3 个答案:

答案 0 :(得分:11)

停止!首先,你在初学者学习指针时经常犯的经典错误。当你写:

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

你正在返回指向 所在位置的指针,而不是:当你离开这个函数时,内存实际上被释放了,所以你不能保证你想到的内存包含你的反向字符串已经没有被其他东西重用了。这样,您的程序将会灾难性地失败。

但是,您在返回之前打印了反向字符串,因此尚未这是一个很大的问题。那么,那里出了什么问题,就是你的字符串没有被正确地终止。

C语言中的字符串需要空间来存储其最终'\0'字节:char string[6] = "kitten";太小而无法容纳以零结尾的字符串{ 'k', 'i', 't', 't', 'e', 'n', '\0' }。同样,当您调用printf("%s", reversedString)时,您还没有使用'\0'正确终止字符串,因此printf会一直查找字符串的结尾并打印出内存中的垃圾分配reversedString的地方。

你应该尝试:

  • 让您的函数返回void
  • 为原始字符串分配7个字节,
  • 为新字符串分配strlen(string) + 1(也是7个)字节,
  • 在反向循环旧字符串后,将'\0'写入新字符串的末尾。

答案 1 :(得分:9)

您的代码中至少存在两个主要错误。还有更多。

首先,对strlen的调用会导致未定义的行为,因为您没有传递一个以null结尾的字符串。原因是你的char数组对于null终止符不够大:

char string[6] = "kitten";

你需要

char string[7] = "kitten";

char string[] = "kitten";

其次,您将返回指向本地数组的指针,即reversedString。取消引用也会导致未定义的行为。你可以通过将字符串就地反转,或者将指针传递给与输入相同长度的缓冲区来解决这个问题。请记住,反向字符串也必须以空值终止。

答案 2 :(得分:1)

功能错误。

它的全部返回指向退出函数

后将被销毁的本地数组的指针
//,,,
char reversedString[len];  
//...
return reversedString; //return pointer to first element of reversed string

其次,反向串应终止为零。但是,您声明一个没有空间用于终止零的数组。

此主数据中的数组也定义错误

char string[6] = "kitten";

因为它不包括终止零。

最后,这是一个糟糕的功能设计。

如果要在目标字符串中复制源字符串,则应将两个字符数组声明为函数参数。此外,源数组应声明为常量数组。

该功能可以按以下方式查看

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

考虑到字符串文字在C中是不可变的,可能不会被更改。任何更改字符串文字的尝试都会导致程序的未定义行为。

这是一个示范程序

#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 ) );
}    

程序输出

Hello gilianzz
zznailig olleH
Hello gilianzz