【问题标题】:Segmentation fault using fgets()使用 fgets() 的分段错误
【发布时间】:2015-09-03 00:53:28
【问题描述】:

我正在制作一个基本程序,并决定在第一个输入中使用函数和指针,我可以选择键入“厨房”或“楼上”,但是当我使用 fgets() 时,我得到了分段错误,不知道为什么。我试图打印出字符串,看看我是否得到了正确的输出,当然由于分段错误,它没有发生。

代码如下:

#include <stdio.h>
#include <string.h>
char one(char *oOne[]);
void two();
void three();

int main() {
    char *oOne[10], oTwo[10], oThree[10]; // Options one, two, and three.
    puts("WELCOME TO ASAD'S ADVENTURE");
    puts("");
    one(oOne);
    return 0;
}

char one(char *oOne[]) {
    puts("You are in a creepy house! Would you like to go \"upstairs\", or into the \"kitchen\"?");

    printf("\n> ");

    if (fgets(*oOne, sizeof *oOne, stdin) == NULL) { // Receiving the input from the user, and removing the \n caused by fgets().
        puts("EOF Occurred");
        return 1;
    }

    *oOne[strcspn(*oOne, "\n")] = 0;
    printf("%s\n", *oOne);
    // puts(*oOne);
}

这是我收到的输出:

WELCOME TO ASAD'S ADVENTURE

You are in a creepy house! Would you like to go "upstairs", or into the "kitchen"?

> kitchen
Segmentation fault

如何解决分段错误?

【问题讨论】:

  • 您是否尝试通过gdbvalgrind 运行此程序?
  • 你有一个char* (oOne) 的数组,这是一个尚未初始化的指针数组。您需要为它们分配内存。您还需要仔细检查 sizeof *oOne 为您提供的内容。
  • 另外,"sizeof *oOne" 将返回指针的大小(4 或 8 字节),而不是您传入的缓冲区大小。您需要将缓冲区大小作为参数传入到函数。

标签: c arrays fgets


【解决方案1】:

C 中的字符串是指向字符的类型,例如:

char *oOne;

或者一个字符数组,如果你想静态分配你的内存:

char oOne[10];

但是不是一个指向字符数组的指针,这就是你所拥有的:

char *oOne[10];

你需要:

char oOne[10];

然后:

one(oOne);

然后用适当的类型修改你的 one 函数:

char one(char *oOne)
{
    if (fgets(oOne, sizeof oOne, stdin) == NULL)
    {
            puts("EOF Occurred");
            return 1;
    }

    *(oOne + strcspn(oOne, "\n")) = 0;

    printf("%s\n", oOne);


}

虽然我会传入一个明确的长度,而不是使用 sizeof,因为这不适用于动态分配的字符串:

car one(char *oOne, int len)
{
    if (fgets(oOne, len, stdin) == NULL)
    {
            puts("EOF Occurred");
            return 1;
    }

    // etc...
}

【讨论】:

  • char *oOne[10]; 是一个指针数组,而不是指向数组的指针。而且sizeof oOne 在这里不管oOne 是否被动态分配都不起作用。
  • 感谢您的解释,+1,我不知道指针和数组!
  • “C 中的字符串是指针到字符的类型”错误导致字符串既不是指针也不是类型。 C 字符串是以空字符结尾的字符数组。
【解决方案2】:

我认为您遇到了段错误,因为您正在取消引用 if (fgets(*oOne, sizeof *oOne, stdin) == NULL) 中的 oOne。使用char *oOne[] 上的右左规则,你会发现 oOne 是一个指向字符的指针数组,所以你拥有的是一个字符串数组而不是一个字符串。因此,要使用 fgets,您需要在您的情况下使用单个字符串,而不是字符串数组。所以改为将 oOne 定义为char oOne[BUFSIZ]。这为您提供了一个字符串,最大允许您接收 bufsiz 字符,这是缓冲区的大小,您不能超过这个。

所以要修复你的代码,它看起来像这样:

char *oOne[10], oTwo[10], oThree[10] 更改为char oOne[10], oTwo[10], oThree[10]

char one(char *oOne[]) 更改为char one(char * oOne)

fgets(*oOne, sizeof *oOne, stdin) 更改为fgets(oOne, sizeof oOne, stdin)

*oOne[strcspn(*oOne, "\n")] 更改为oOne[strcspn(oOne, "\n")]

通过这种方式,您可以将 oOne 作为字符串(字符数组)而不是字符指针数组进行交互。有关如何在 see 中定义变量的更多信息,请查看http://ieng9.ucsd.edu/~cs30x/rt_lt.rule.html 此处的左右规则。

【讨论】:

    猜你喜欢
    • 2013-01-19
    • 1970-01-01
    • 2016-01-15
    • 2013-01-03
    • 1970-01-01
    • 2018-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多