关于C中的字符串[重复]

2o7dmzc5  于 2023-10-16  发布在  其他
关注(0)|答案(2)|浏览(121)

此问题已在此处有答案

How to access a local variable from a different function using pointers?(10个答案)
25天前关闭
我是一个初学C的人,我试着写一个函数,它应该返回一个字符串,但当我试图打印从函数获得的结果时,我只得到(null)
下面是我的代码:

char *reverse(char *str) {
    char result[20];

    /* logic */

    return result;
}

int main() {
    char str[20];
    printf("Enter a string: ");
    scanf("%[^\n]s", str);
    printf("The string reversed is: %s", reverse(str));
}

为什么这个打印(null),当我注意到这样的东西工作得很好:

char *func() {
    return "hello";
}

int main() {
    printf("%s", func());
}
hjqgdpho

hjqgdpho1#

函数reverse()返回一个指针,指向在函数体中使用局部作用域定义的数组:当函数返回并且指针变为无效(悬空指针)时,此数组将超出作用域。从无效指针进行阅读具有未定义的行为。令人惊讶的是,printf为此输出(null),但未定义的行为意味着任何事情都可能发生,不要感到惊讶,不要期望下一次发生同样的行为,试图解释实际观察到的行为是徒劳的。
你应该使数组static或从堆中分配它,或者更好地,把目标数组作为参数。
注意scanf("%[^\n]s", str)是不正确的:

  • 后面的s没有意义,应该删除;
  • 应该指定要存储到str中的最大字符数,以避免潜在的缓冲区溢出:scanf("%19[^\n]", str)
  • 你应该测试scanf()的返回值来检测无效或丢失的输入,比如一个空行。

以下是修改后的版本:

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

char *reverse(char *result, const char *str) {
    size_t len = strlen(str);
    
    for (size_t i = 0; i < len; i++) {
        result[i] = str[len - 1 - i];
    }
    result[len] = '\0';
    return result;
}

int main(void) {
    char str[20];
    char output[20];
    printf("Enter a string: ");
    if (scanf("%19[^\n]", str) == 1) {
        printf("The string reversed is: %s\n", reverse(output, str));
        return 0;
    } else {
        return 1;
    }
}
k5ifujac

k5ifujac2#

您的代码段打印(null)的原因是您从reverse函数返回了一个本地数组结果,这是一个堆栈分配的数组。一旦reverse函数返回,结果数组的内存将被释放,并留下一个悬空指针。如果忽略此指针,则会导致未定义的行为,在您的情况下,它恰好是print(null)。

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

char* reverse(const char* str) {
    int length = strlen(str);
    char* result = (char*)malloc((length + 1) * sizeof(char));

    if (result == NULL) {
        fprintf(stderr, "Memory allocation failed.\n");
        exit(1);
    }

    for (int i = 0; i < length; i++) {
        result[i] = str[length - 1 - i];
    }
    result[length] = '\0';

    return result;
}

int main() {
    char str[20];
    printf("Enter a string: ");
    scanf("%19[^\n]", str);  // Limit input length to avoid buffer overflow
    char* reversed = reverse(str);
    printf("The string reversed is: %s\n", reversed);

    // Don't forget to free the dynamically allocated memory when done
    free(reversed);

    return 0;
}

1.我们使用malloc为结果字符串动态分配内存。字符串的长度由strlen(str)决定,我们加1来容纳空终止符。
1.我们将输入字符串str中的字符以相反的顺序复制到动态分配的结果字符串中。
1.我们确保结果字符串以空终止。
1.在使用反转字符串之后,使用free释放动态分配的内存以避免内存泄漏是很重要的。

相关问题