关于 C 语言中的字符串 [duplicate]

Regarding strings in C [duplicate]

提问人:abhinav 提问时间:9/20/2023 最后编辑:chqrlieabhinav 更新时间:9/20/2023 访问量:49

问:

我是 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());
}
数组 C 字符串 函数

评论

1赞 Rohan Bari 9/20/2023
该函数返回局部变量的地址。也许逻辑无法将新值设置为?reverseresultresult

答:

1赞 chqrlie 9/20/2023 #1

该函数返回一个指向函数主体中具有局部作用域定义的数组的指针:当函数返回并且指针变得无效时,此数组超出作用域(悬空指针)。从无效指针读取具有未定义的行为。令人惊讶的是,这个输出,但未定义的行为意味着任何事情都可能发生,不要感到惊讶,不要期望下次出现相同的行为,试图解释实际观察到的行为是徒劳的。reverse()printf(null)

您应该创建数组或从堆中分配它,或者更好的是,将目标数组作为参数。static

另请注意,这是不正确的:scanf("%[^\n]s", str)

  • 尾随是没有意义的,应该删除;s
  • 应指定要存储到的最大字符数,以避免潜在的缓冲区溢出:strscanf("%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;
    }
}

评论

0赞 Jeevan ebi 9/20/2023
谢谢你的建议!这可能会有所帮助!
0赞 chqrlie 9/21/2023
@abhinav:您可以通过单击其分数下方的灰色复选标记来接受其中一个答案。
0赞 Jeevan ebi 9/20/2023 #2

代码段打印 (null) 的原因是,您从 reverse 函数返回局部数组结果,该函数是堆栈分配的数组。一旦 reverse 函数返回,结果数组的内存就会被释放,并且只剩下一个悬空的指针。访问此指针会导致未定义的行为,在您的情况下,它恰好打印 (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 以容纳 null 终止符。

  2. 我们以相反的顺序从输入字符串 str 中复制字符 添加到动态分配的结果字符串中。

  3. 我们确保以 null 结尾的结果字符串。

  4. 使用反转字符串后,释放 使用 free 动态分配内存以避免内存泄漏。

评论

1赞 chqrlie 9/20/2023
您是否知道,如果用户在空行上按回车键,更正后的程序仍将具有未定义的行为?
0赞 chux - Reinstate Monica 9/21/2023
@Jeevan ebi,旁白:更简单char* result = (char*)malloc((length + 1) * sizeof(char));char* result = malloc(length + 1);