Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/apache-flex/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 循环条件出现问题-文件结束_C - Fatal编程技术网

C 循环条件出现问题-文件结束

C 循环条件出现问题-文件结束,c,C,当前代码迭代: #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #define MAX_LINE_SIZE 60 #define MAX_LIST_SIZE 15 #define MAX_QUIZ_SIZE 10 typedef struct question { char *question; char **choice

当前代码迭代:

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

#define MAX_LINE_SIZE 60
#define MAX_LIST_SIZE 15
#define MAX_QUIZ_SIZE 10

typedef struct question {
    char *question;
    char **choices;
    int n_choices;
    char *correct_answer;
} QUESTION;

char *dupString(const char *s) {
    // copies a string
    // CHECK TO SEE IF DUP WORKS

    char *dup = malloc(strlen(s) + 1);
    if (strcpy(dup, s)) {
        return dup;
    } else {
        printf("Error duplicating string");
        return 0;
    }
}

void free_question(QUESTION *q) {
    // free memory
    for(int i = 0; i < q->n_choices; i++) {
        free(q->choices[i]);
    }
    free(q->choices);
    free(q->question);
    free(q->correct_answer);

    // set pointers to null
    for(int i = 0; i < q->n_choices; i++) {
       q->choices[i] = NULL;
    }
    q->choices = NULL;
    q->question = NULL;
    q->correct_answer = NULL;
}

static int read_info(FILE *pData, char **ptr)
{
    char line[MAX_LINE_SIZE];
    if (fgets(line, sizeof(line), pData) == 0 ||
        (*ptr = dupString(line)) == 0)
        return EOF;
    return 0;
}

static int read_number(FILE *pData, int *num, QUESTION *q)
{
    char line[MAX_LINE_SIZE];
    if (fgets(line, sizeof(line), pData) == 0 ||
        (*num = atoi(line)) < 2 || q->n_choices > 9)
        return EOF;
    return 0;
}

static int read_choices(FILE *pData, QUESTION *q)
{
    char line[MAX_LINE_SIZE];
    for (int i = 0; i < q->n_choices; i++)
    {
        if (fgets(line, sizeof(line), pData) == 0 ||
            (q->choices[i] = dupString(line)) == 0)
            return EOF;
    }
    return 0;
}

int parseQuestion(FILE *pData, int qnum, QUESTION *q)
{
    *q = (QUESTION){ NULL, NULL, 0, NULL };

    if (read_info(pData, &q->question) == EOF ||
        read_number(pData, &q->n_choices, q) == EOF ||
        (q->choices = calloc(q->n_choices, sizeof(char *))) == 0 ||
        read_choices(pData, q) == EOF ||
        read_info(pData, &q->correct_answer) == EOF)
    {
        
        return EOF;
    }

    return 0;
}

struct question makeQuestion(FILE *pData, QUESTION *q) {

    int qIndex, numChoices; 
    char question[MAX_LINE_SIZE], temp[MAX_LINE_SIZE], choices[MAX_LINE_SIZE], correctAns[MAX_LINE_SIZE];

    // Eat first line = QUESTION
    fgets(question, MAX_LINE_SIZE, pData);
    q->question = dupString(question);
    

    // Eat second line = NUMBER OF CHOICES
    fgets(temp, MAX_LINE_SIZE, pData);
    numChoices = atoi(temp);
    q->n_choices = numChoices;

    // Allocate memory
    q->choices = calloc(q->n_choices, sizeof(char*));

    // Eat nth lines = CHOICES
    for (qIndex=0; qIndex<=numChoices-1; qIndex++) {
        fgets(choices, MAX_LINE_SIZE, pData);
        q->choices[qIndex] = dupString(choices);
    }
    
    // Eat nth + 1 line = CORRECT ANSWER
    fgets(correctAns, MAX_LINE_SIZE, pData);
    q->correct_answer = dupString(correctAns);

    return *q;  
}           

int ask(QUESTION *q) {
    // Return 1 for correct guess, 0 for incorrect guess.
    
    int choice;

    printf("\n%s\n", q->question);

    for (int i = 0; i <= q->n_choices-1; i++) {
        printf("%d : %s", i+1, q->choices[i]);
    }

    do {
        printf("Select an answer [1-%d]: ", q->n_choices);
        scanf("%d", &choice);
        
        if (choice == 0) {
            return 2;
        }

        /* Check guess */
        int ret;
        size_t size = sizeof(q->correct_answer);
        ret = memcmp(q->choices[choice-1], q->correct_answer, size);
    
        if (ret == 0) {
            return 1;
        }
    } while (choice < 1 || choice > q->n_choices);

    return 0;
}


int main() {

    int num = 0;        // question being asked
    int score = 0;  // incorrect guesses
    char temp[MAX_LINE_SIZE]; // temp for loop condition

    FILE* pData;

    char *filename = "tickle.txt";
    char c;

    if ((pData = fopen(filename, "r"))) {

        printf("Welcome to the 2014 Quiz-festival!\n\n");
        printf("Are you ready to begin? [Y/y]:  ");
        c = getchar();

        if (c == 'Y' || c == 'y') {

            QUESTION q;
            while (parseQuestion(pData, ++num, &q) == 0) {
                makeQuestion(pData, &q);
                
                if (ask(&q) == 1) {
                    ++score;
                    printf("Correct!\n");
                } else {
                    printf("Oops, bad luck!\n");
                }
                free_choices(&q);
            }       

        } else {
            printf("Come back again.\n");
            return 0;
        }

    } else {
        printf("File failed to open.");
        return 0;
    }

    fclose(pData);
    return 0;
}
#包括
#包括
#包括
#包括
#定义最大线尺寸60
#定义最大列表大小15
#定义最大尺寸10
类型定义结构问题{
char*问题;
字符**选择;
int n_选择;
正确答案;
}问题,;
char*dupString(常量char*s){
//复制字符串
//检查DUP是否工作
char*dup=malloc(strlen+1);
if(strcpy(dup,s)){
返回dup;
}否则{
printf(“复制字符串时出错”);
返回0;
}
}
无效自由问题(问题*q){
//空闲内存
对于(int i=0;in_选项;i++){
自由(q->选择[i]);
}
自由(q->选择);
免费(q->问题);
免费(q->正确答案);
//将指针设置为null
对于(int i=0;in_选项;i++){
q->choices[i]=NULL;
}
q->choices=NULL;
q->question=NULL;
q->correct_answer=NULL;
}
静态整数读取信息(文件*pData,字符**ptr)
{
字符行[最大行大小];
如果(fgets(line,sizeof(line),pData)=0||
(*ptr=dupString(行))==0)
返回EOF;
返回0;
}
静态整数读取编号(文件*pData,整数*num,问题*q)
{
字符行[最大行大小];
如果(fgets(line,sizeof(line),pData)=0||
(*num=atoi(line))<2|q->n|u选项>9)
返回EOF;
返回0;
}
静态整数读取选项(文件*pData,问题*q)
{
字符行[最大行大小];
对于(int i=0;in_选项;i++)
{
如果(fgets(line,sizeof(line),pData)=0||
(q->choices[i]=dupString(行))==0)
返回EOF;
}
返回0;
}
int-parseQuestion(文件*pData,int-qnum,问题*q)
{
*q=(问题){NULL,NULL,0,NULL};
如果(读取信息(pData,&q->问题)=EOF||
读取编号(pData,&q->n\U选项,q)=EOF||
(q->choices=calloc(q->n_choices,sizeof(char*))==0||
读取选项(pData,q)=EOF||
阅读信息(pData,&q->正确答案)=EOF)
{
返回EOF;
}
返回0;
}
结构问题生成问题(文件*pData,问题*q){
国际货币指数,国际货币选择;
字符问题[MAX_LINE_SIZE],临时[MAX_LINE_SIZE],选项[MAX_LINE_SIZE],更正[MAX_LINE_SIZE];
//吃第一行=问题
fgets(问题、最大线尺寸、pData);
q->question=dupString(问题);
//吃第二行=选择的数量
FGET(温度、最大线尺寸、pData);
数值选择=原子(温度);
q->n_选项=numChoices;
//分配内存
q->choices=calloc(q->n_choices,sizeof(char*);
//吃第n行=选择
for(qIndex=0;qIndexchoices[qIndex]=dupString(choices);
}
//第n+1行=正确答案
fgets(校正、最大线尺寸、pData);
q->correct\u answer=dupString(correctAns);
返回*q;
}           
int ask(问题*q){
//返回1表示正确猜测,返回0表示错误猜测。
智力选择;
printf(“\n%s\n”,q->问题);
for(int i=0;i n_选项-1;i++){
printf(“%d:%s”,i+1,q->选项[i]);
}
做{
printf(“选择一个答案[1-%d]:”,q->n_选项);
scanf(“%d”,选择(&C);
如果(选项==0){
返回2;
}
/*猜猜看*/
int ret;
size\u t size=sizeof(q->正确答案);
ret=memcmp(q->choices[choice-1],q->correct\u答案,大小);
如果(ret==0){
返回1;
}
}而(选择<1 |选择>q->n|u选择);
返回0;
}
int main(){
int num=0;//正在询问的问题
int score=0;//猜测不正确
char temp[MAX_LINE_SIZE];//循环条件的温度
文件*pData;
char*filename=“tickle.txt”;
字符c;
如果((pData=fopen(文件名,“r”)){
printf(“欢迎参加2014年智力竞赛节!\n\n”);
printf(“您准备好开始了吗?[Y/Y]:”;
c=getchar();
如果(c=='Y'| | c=='Y'){
问题q;
while(parseQuestion(pData,++num,&q)==0){
提出问题(pData和q);
如果(询问(&q)==1){
++得分;
printf(“正确!\n”);
}否则{
printf(“糟糕,运气不好!\n”);
}
自由选择(&q);
}       
}否则{
printf(“再次返回。\n”);
返回0;
}
}否则{
printf(“文件打开失败”);
返回0;
}
fclose(pData);
返回0;
}
它似乎起作用了,但是,它从第二次测验开始。现在我完全糊涂了

示例数据文件:

问题1

3(答覆数目)

答复1a

答复1b

答复1c

答案1a(这是正确答案)

问题2

二,

答复2a

答复2b

答案2b(这是正确答案)


程序从问题2开始。内存有什么问题吗?我似乎无法理解它。

由于
parseQuestion()
函数是检测EOF的函数,它应该返回一个值,指示是否有问题要处理(假设没有问题,则为EOF)

考虑到这种情况,我可能会重写它的界面:

QUESTION question;
while (parseQuestion(pData, ++num, &question) == 0)
{
    …process a known-to-be-valid question…
}
我会让它做提示,传递文件指针、问题编号和指向它将填充的问题结构的指针。成功时返回0,失败时返回其他值(可能是EOF)

这或多或少是C中处理此类问题的标准方法。退一步,这就是检查
fgets()
是否有效的方法:

char line[4096];
while (fgets(line, sizeof(line), fp) != 0)
{
    …process line…
}

您可以这样重写
parseQuestion()

int parseQuestion(FILE *pData, int qnum, QUESTION *q)
{
    char line[MAX_LINE_SIZE];

    *q = (QUESTION){ NULL, NULL, 0, NULL };

    printf("******** Question: %d ********\n", num);

    if (fgets(line, sizeof(line), pData) == 0 ||
        (q->question = dupString(line)) == 0)
        return EOF;

    if (fgets(line, sizeof(line), pData) == 0)
    {
        free_choices(q);
        return EOF;
    }
    q->n_choices = atoi(line);
    if (q->n_choices < 2 || q->n_choices > 9)
    {
        fprintf(stderr, "Invalid number of choices %d (should be 2..9)\n",
                q->n_choices);
        free_choices(q);
        return EOF;
    }

    q->choices = calloc(q->n_choices, sizeof(char *));
    if (q->choices == 0)
    {
        fprintf(stderr, "Memory allocation failed)\n");
        free_choices(q);
        return EOF;
    }

    for (int i = 0; i < q->n_choices; i++)
    {
        if (fgets(line, sizeof(line), pData) == 0 ||
            (q->choices[i] = dupString(line)) == 0)
        {
            free_choices(q);
            return EOF;
        }
    }

    if (fgets(line, sizeof(line), pData) == 0 ||
        (q->correct_answer = dupString(line)) == 0)
    {
        free_choices(q);
        return EOF;
    }

    return 0;
}
您可以让
read\u choices()
调用
read\u info()
迭代,而不是在内部实现
read\u info()
static int read_info(FILE *pData, char **ptr)
{
    char line[MAX_LINE_SIZE];
    if (fgets(line, sizeof(line), pData) == 0 ||
        (*ptr = dupString(line)) == 0)
        return EOF;
    return 0;
}

static int read_number(FILE *pData, int *num)
{
    char line[MAX_LINE_SIZE];
    if (fgets(line, sizeof(line), pData) == 0 ||
        (*num = atoi(line)) < 2 || q->n_choices > 9)
        return EOF;
    return 0;
}

static int read_choices(FILE *pdata, QUESTION *q)
{
    for (int i = 0; i < q->n_choices; i++)
    {
        if (fgets(line, sizeof(line), pData) == 0 ||
            (q->choices[i] = dupString(choices)) == 0)
            return EOF;
    }
    return 0;
}

int parseQuestion(FILE *pData, int qnum, QUESTION *q)
{
    printf("******** Question: %d ********\n", num);
    *q = (QUESTION){ NULL, NULL, 0, NULL };

    if (read_info(pData, &q->question) == EOF ||
        read_number(pData, &q->n_choices) == EOF ||
        (q->choices = calloc(q->n_choices, sizeof(char *))) == 0 ||
        read_choices(pData, q) == EOF ||
        read_info(pData, &q->correct_answer) == EOF)
    {
        free_choices(q);
        return EOF;
    }

    return 0;
}