【问题标题】:Segmentation fault when using scanf or fgets in C language在 C 语言中使用 scanf 或 fgets 时出现分段错误
【发布时间】:2015-11-26 23:24:18
【问题描述】:

我有一个项目在我的一个编程课程中创建一个包含 20 个问题的游戏,该游戏递归地构建一棵二叉树,在您回答问题时计算机会遵循这些选择。我制作的节点文件已经过测试并且工作正常。但是,如果需要,我可以发布它,但我相信我的问题出在我的主文件中。

程序运行失败:

Is it a dog?

Enter "y" for yes and "n" for no: n

YOU WIN!!!

What were you thinking of? fish

Please give me a yes or no questions to distinguish dog from fish: does it have scales?

Segmentation fault (core dumped)

程序运行得非常好,并按预期执行,直到用户输入有区别的问题。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "Node.h"
#define BUFF 1

//prototype methods
void startGame();
void askQuestion(Node* currentNode);

//Declare variables
Node* startNode;
Node* moveNode;
Node* makeNode;
char ans;
char newQuestion[1000];
char playerObj[1000];

void startGame() {
    //Allocate memory for altering decision tree when new questions are added
    startNode = (Node*) malloc(BUFF * sizeof(Node));
    moveNode = (Node*) malloc(BUFF * sizeof(Node));
    makeNode = (Node*) malloc(BUFF * sizeof(Node));

    //Make root node of tree
    setQuestion("Is it a dog?", startNode);
    setObjName("dog", startNode);

}

void askQuestion(Node* currentNode) {

    printf("%s\n", getQuestion(currentNode));//Ask user a question
    printf("Enter \"y\" for yes and \"n\" for no: ");//Prompt user for response
    scanf("%c", &ans);//Get user character from keyboard
    fflush(stdin);//Flush standard input to clear newline character

    //If the computer is right computer wins
    if((isObjNode(currentNode)) & (ans == 'y')){
        printf("COMPUTER WINS!!!");
        //this section will later start another game using the current decision tree

    //Move to next yes node in tree
    }else if(!(isObjNode(currentNode)) & (ans == 'y')){
        askQuestion(currentNode->yesPointer);

    //If at leaf node and computer is wrong notify user and expand tree
    }else if((isObjNode(currentNode)) & (ans == 'n')){
        printf("YOU WIN!!!\n");

        printf("What were you thinking of? ");
        scanf("%s", &playerObj);//Get what user was thinking of
        fflush(stdin);//Flush newline character

        printf("Please give me a yes or no questions to distinguish %s from             %s: ",currentNode->objName, playerObj);
        fflush(stdout);

        scanf("%s", &newQuestion);
        //I also tried:
        //fgets(newQuestion, sizeof(newQuestion), stdin);
        fflush(stdin);

        //PROGRAM SEGMENTATION FAULTS

        setQuestion(strcat(strcat("Is it a ", playerObj), "?"), makeNode);
        setObjName(playerObj, makeNode);

        moveNode = currentNode;

        printf("If the answer would be %s, what would the answer be y for    yes, n for no?",playerObj);
        scanf("%c", &ans);
        fflush(stdin);
        setQuestion(newQuestion, currentNode);

        if(ans == 'y'){
            setYesNodeRef(currentNode, makeNode);
            setNoNodeRef(currentNode, moveNode);
        }else if(ans == 'n'){
            setYesNodeRef(currentNode, moveNode);
            setNoNodeRef(currentNode, makeNode);
        }

    }else if(!(isObjNode(currentNode)) & (ans == 'n')){
        askQuestion(currentNode->noPointer);
    }

}

int main() {

    startGame();
    askQuestion(startNode);

}

所以,简而言之,我的问题是导致分段错误的原因是什么?

我查看了几篇重新分级 scanf 的帖子,并根据一些帖子和教程尝试了 fgets。当代码完全相同时,fgets 甚至不会让我输入用户输入,只需将 scanf 更改为 fgets 以获取 newQuestion 输入(如果有任何兴趣)。

提前感谢大家对类似问题的任何意见或推荐。

【问题讨论】:

  • fflush(stdin); 的行为是未定义的,无论如何它不会按照你的想法做。还:提供一个可编译的示例。并且不要投射malloc()
  • 首先: 1. fflush(stdin); 是未定义的行为。不要使用它。 2. scanf("%s", &amp;playerObj); 是错误的,因为类型不匹配和缓冲区溢出的风险。使用scanf("%999s", playerObj);scanf("%s", &amp;newQuestion); 也应该是 scanf("%999s", newQuestion);
  • strcat(strcat("Is it a ", playerObj), "?") 非常糟糕。您不能修改字符串文字,即使允许修改,此代码也会导致缓冲区溢出。分配足够的缓冲区并使用sprintf()
  • 在这种情况下,也许您应该使用&amp;&amp;(逻辑与)而不是&amp;(按位与)。

标签: c scanf fgets


【解决方案1】:

再次感谢大家。

显示如下的行:
strcat(strcat("Is it a ", playerObj), "?")

导致我遇到的问题。当我完全注释掉该行时,程序能够继续程序中的其他点。正如用户 MikeCAT 所说,我正在寻找更好的方法来做到这一点。

【讨论】:

  • @MikeCAT 感谢您对此的提示。我将探索 sprintf
猜你喜欢
  • 2022-01-14
  • 2016-01-15
  • 2020-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-31
  • 2020-10-26
  • 1970-01-01
相关资源
最近更新 更多