【问题标题】:fgets segmentation fault when reading input from user读取用户输入时 fgets 分段错误
【发布时间】:2015-08-19 19:44:36
【问题描述】:

这是使用 ubuntu 的违规代码

char *name;

int main(void)
{
  fgets(name, sizeof(name), stdin);
}
void HUD()
{
  printf("%s ", name); 
}

这是我的问题。我从 scanf("%s", &name) 开始,并在字符串末尾变得垃圾。在过去的 2 个小时里一直在阅读有关 scanf 和 fgets 的文档,因为当您不知道所需数组的大小时,显然不应该使用 scanf,(并且由于用户输入的大小可能会有所不同)我决定尝试使用 fgets。我也尝试通过 char name[100]; 设置一个固定值。并通过 fgets(name, 100, stdin)

现在我遇到了分段错误,通过阅读我在谷歌前 2 页上找到的每一个结果,我的语法似乎是正确的,我在 cboard 或这里找不到任何东西可以解决我的问题。

有什么想法吗?

【问题讨论】:

  • 我已经这样做了。没有成功。仍然出现分段错误。
  • 当您不知道输入的长度时,您可以使用scanf() 就可以了,只要您指定一个防止数组溢出的字段宽度即可。 fgets() 具有完全相同的限制;它只是更明确地让你告诉它应该读取多少个字符的限制。
  • 请注意,scanf()fgets() 在如何确定何时停止阅读方面有所不同。

标签: c fgets


【解决方案1】:

sizeof(name) 将是您系统上指针的大小,在我的系统上是 8 个字节。不是缓冲区的大小,正如您所期望的那样

char* name 也未初始化。您将尝试写入未初始化的缓冲区,它会以未定义的行为结束。

要解决要么将其设置为固定大小的缓冲区,要么在堆上分配一些空间。

分配

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

#define NAME_SIZE 100
char *name;

void HUD()
{
  printf("%s ", name); 
}

int main(void)
{
    name=calloc(NAME_SIZE, sizeof(char));
    fgets(name, NAME_SIZE, stdin);

    HUD();

    free(name);
}

静态数组

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

#define NAME_SIZE 100
char name[NAME_SIZE];

void HUD()
{
  printf("%s ", name); 
}

int main(void)
{
    fgets(name, NAME_SIZE, stdin);

    HUD();
}

您必须将缓冲区的大小传递给fgets,以便它知道需要写入多少空间。

【讨论】:

  • 有没有办法读取字符串,直到他们点击 \n 并将数组的大小设置为输入的字符 + \0 ?
  • 事情变得复杂,因为缓冲区不会在 fgets 中自动调整大小,您必须推出自己的解决方案。 fgets 将读取直到 array_size - 1 个字符被读取或到达一个换行符。
  • @nathanil in c 你不会得到太多免费的。您必须实现自己的解决方案,随着输入的增长重新分配更大的缓冲区。如果您查看 c++ 中的 std::string ,它会按照这些思路进行操作。
  • 谢谢大家。这是我在这个项目上的第三天,在从 C# 开始 C 之后的一周。我正在艰难地学习 C 中没有免费的东西,就像我第一次不得不手动排序一样哈哈 :)
  • @nanthil,不是fgets(),没有。但是,虽然它不在 C 标准中,但 POSIX scanf() 实际上确实提供了此功能。它可以像这样使用:scanf("%m[^\n]", name)。您必须注意换行处理的一些差异。
【解决方案2】:

char *fgets(char *restrict s, int n, FILE *restrict stream);

fgets() 函数应该从流中读取字节到数组中 由 s 指向,直到 n-1 个字节被读取,或者 a 被读取并且 转移到 s,或遇到文件结束条件。这 然后字符串以空字节终止。 [0]

您需要将其分配到特定大小并使用该大小调用 fgets。这段代码可以帮助你完成同样的事情,但它有一个固定大小的缓冲区。

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

char name;
char* buffer;
int buffer_size = 16;
int i = 0;


void HUD()
{
        printf("%s ", buffer);
}

int main(void)
{
        buffer = malloc(buffer_size);
        if(!buffer) return;

        for(;;) {
                name = getchar();
                if(name < 0) {
                        buffer[i] = '\0';
                        goto finish;
                } else if(i < (buffer_size -1)) {
                        buffer[i++] = name;
                } else if(name == '\n') {
                        break;
                }
        }
        buffer[i] = '\0';
        finish:
            HUD();
            free(buffer);
            return 0;
}

[0]http://pubs.opengroup.org/onlinepubs/009695399/functions/fgets.html

【讨论】:

  • 初始化变量有什么作用?我来自 C#,我的印象是,如果没有给出具体的大小,它会读取我给它的内容,并在它的末尾添加一个空字符,因为它是一个 char * ......这真的当他们解释阅读输入时没有向我解释得很好
  • goto finish;用火杀死它!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-18
  • 2019-02-16
相关资源
最近更新 更多