| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 2529 人关注过本帖
标题:一道改程序题目,程序较为复杂,还请不吝赐教
只看楼主 加入收藏
supremeloyal
Rank: 1
等 级:新手上路
帖 子:3
专家分:0
注 册:2016-3-6
结帖率:0
收藏
已结贴  问题点数:20 回复次数:3 
一道改程序题目,程序较为复杂,还请不吝赐教
这道题来自《C语言的科学与艺术》,思考了三个晚上没有解决思路,代码较长,还请大神不吝赐教。

这个程序读取外部数据文件后,为学生提供题目,学生输入答案后,根据答案的不同提供下一道题目。
例如外部文件:
C programming review
1
Would you like help with int or bool type?
-----
int:     2
bool:   10

2
True or false: Integers can have fractional parts.
-----
true:    3
false:   5

3
No.  Floating-point numbers have fractional parts;
integers do not.
True or false: Integers can be negative.
-----
true:    5
false:   4

……
……
……


开始程序提供第1题,输入int后提供第2题,输入true提供第3题。
但是这个程序的缺陷在于,给出第3题以后,如果输入答案为maybe,则程序输出I don't understand that.然后再将第3题全部内容输出。
如下所示
No.  Floating-point numbers have fractional parts;
integers do not.
True or false: Integers can be negative.
maybe//输入maybe
I don't understand that.
No.  Floating-point numbers have fractional parts;
integers do not.
True or false: Integers can be negative.

但其中包含的提示性信息明显不符合实际,因此题目要求修改程序(不修改外部文件)改善这一情况,即在第二次输出第3题时不输出提示性内容,而是直接输出题目信息。

所有问题以字符串数组形式储存,完整数据结构图示以及源代码文件上传到了附件中。需要的库文件在二楼。
C.zip (91.95 KB)

我一直在考虑寻找外部文件中提示信息的共性,以此在第二次输出时不输出拥有该共性的字符串。但外部文件中并没有找到此种共性。
由于不能修改外部文件,无法在提示信息后添加标记值。
程序如下
程序代码:
/*

 * File: teach.c

 * -------------

 * This program executes a simple programmed instruction course.

 * The course is specified by a data file containing all the

 * course information.  The data structures and the format of

 * the data file are described in Chapter 16.

 */

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

#include "genlib.h"
#include "strlib.h"
#include "simpio.h"

/*

 * Constants

 * ---------

 * MaxQuestions          -- Maximum question number

 * MaxLinesPerQuestion   -- Maximum number of lines per question

 * MaxAnswersPerQuestion -- Maximum answers per question

 * EndMarker             -- String marking end of question text

 */

#define MaxQuestions          100
#define MaxLinesPerQuestion    20
#define MaxAnswersPerQuestion  10
#define EndMarker "-----"

/* Data structures */

/*

 * Type: answerT

 * -------------

 * This structure provides space for each possible answer

 * to a question.

 */

typedef struct {
    string ans;
    int nextq;
} answerT;

/*

 * Type: questionT

 * ---------------

 * This structure provides space for all the information

 * needed to store one of the individual question records.

 * Because this structure is large and it makes sense

 * to refer to it as a single entity, questionT is defined

 * as a pointer type.

 */

typedef struct {
    string qtext[MaxLinesPerQuestion+1];
    answerT answers[MaxAnswersPerQuestion];
    int nAnswers;
} *questionT;

/*

 * Type: courseDB

 * --------------

 * This type is used to define the entire database, which is

 * a pointer to a record containing the title and an array of

 * questions.

 */

typedef struct {
    string title;
    questionT questions[MaxQuestions+1];
} *courseDB;

/* Private function declarations */

static courseDB ReadDataBase(void);
static bool ReadOneQuestion(FILE *infile, courseDB course);
static void ReadQuestionText(FILE *infile, questionT q);
static void ReadAnswers(FILE *infile, questionT q);
static FILE *OpenUserFile(string prompt, string mode);
static void ProcessCourse(courseDB course);
static void AskQuestion(questionT q);
static int FindAnswer(string ans, questionT q);

/* Main program */

int main()
{
    courseDB course;

    course = ReadDataBase();
    ProcessCourse(course);
}

/* Section 1 -- Functions to read the data file */

/*

 * Function: ReadDataBase

 * Usage: ReadDataBase();

 * ----------------------

 * This function asks the user for a file name and reads

 * in the database for the course.  The file is formatted

 * as discussed in the section "Designing the external

 * structure" in Chapter 16.

 */

static courseDB ReadDataBase(void)
{
    FILE *infile;
    courseDB course;

    infile = OpenUserFile("Enter name of course: ", "r");
    course = New(courseDB);
    course->title = ReadLine(infile);
    while (ReadOneQuestion(infile, course));
    fclose(infile);
    return (course);
}

/*

 * Function: ReadOneQuestion

 * Usage: while (ReadOneQuestion(infile, course));

 * -----------------------------------------------

 * This function reads in a single question from infile into the

 * course data structure.  As long as the complete question is

 * read successfully, this function returns TRUE.  When the end

 * of the file is encountered, the function returns FALSE.

 * Thus, the "Usage" line above reads the entire data file.

 */

static bool ReadOneQuestion(FILE *infile, courseDB course)
{
    questionT question;
    string line;
    int qnum;

    line = ReadLine(infile);
    if (line == NULL) return (FALSE);
    qnum = StringToInteger(line);
    if (qnum < 1 || qnum > MaxQuestions) {
        Error("Question number %d out of range", qnum);
    }
    question = New(questionT);
    ReadQuestionText(infile, question);
    ReadAnswers(infile, question);
    course->questions[qnum] = question;
    return (TRUE);
}

/*

 * Function: ReadQuestionText

 * Usage: ReadQuestionText(infile, question);

 * ------------------------------------------

 * This function reads the text of the question into the

 * question data structure, which must have been allocated

 * by the caller.  The end of the question text is signaled

 * by a line matching the string EndMarker.

 */

static void ReadQuestionText(FILE *infile, questionT q)
{
    string line;
    int nlines;

    nlines = 0;
    while (TRUE) {
        line = ReadLine(infile);
        if (StringEqual(line, EndMarker)) break;
        if (nlines == MaxLinesPerQuestion) {
            Error("Too many lines");
        }
        q->qtext[nlines] = line;
        nlines++;
    }
    q->qtext[nlines] = NULL;
}

/*

 * Function: ReadAnswers

 * Usage: ReadAnswers(infile, question);

 * -------------------------------------

 * This function reads the answer pairs for the question

 * from the input file.  Each answer consists of a string

 * followed by a colon, followed by the number of the next

 * question to be read.  The end of the answer list is

 * signaled by a blank line or the end of the file.

 */

static void ReadAnswers(FILE *infile, questionT q)
{
    string line, ans;
    int len, cpos, nextq, nAnswers;

    nAnswers = 0;
    while ((line = ReadLine(infile)) != NULL
           && (len = StringLength(line)) != 0) {
        cpos = FindChar(':', line, 0);
        if (cpos == -1) Error("Illegal answer format");
        ans = SubString(line, 0, cpos - 1);
        nextq = StringToInteger(SubString(line, cpos+1, len-1));
        q->answers[nAnswers].ans = ConvertToUpperCase(ans);
        q->answers[nAnswers].nextq = nextq;
        nAnswers++;
    }
    q->nAnswers = nAnswers;
}

/*

 * Function: OpenUserFile

 * Usage: fileptr = OpenUserFile(prompt, mode);

 * --------------------------------------------

 * This function prompts the user for a file name using the

 * prompt string supplied by the user and then attempts to

 * open that file with the specified mode.  If the file is

 * opened successfully, OpenUserFile returns the appropriate

 * file pointer.  If the open operation fails, the user is

 * informed of the failure and given an opportunity to enter

 * another file name.

 */

static FILE *OpenUserFile(string prompt, string mode)
{
    string filename;
    FILE *result;

    while (TRUE) {
        printf("%s", prompt);
        filename = GetLine();
        result = fopen(filename, mode);
        if (result != NULL) break;
        printf("Can't open the file \"%s\"\n", filename);
    }
    return (result);
}

/* Section 2 -- Functions to process the course */

/*

 * Function: ProcessCourse

 * Usage: ProcessCourse(course);

 * -----------------------------

 * This function processes the course supplied by the caller.

 * The basic operation consists of a loop that

 *

 *    (a) prints out the current question

 *    (b) reads in an answer

 *    (c) looks up the answer in the database

 *    (d) goes to a new question on the basis of that answer

 *

 * In this implementation, the variable qnum holds the

 * index of the question and the variable q holds the

 * actual question data structure.  The course always begins

 * with question #1, after which the order is determined by

 * the answers.

 */

static void ProcessCourse(courseDB course)
{
    questionT q;
    int qnum;
    string ans;
    int index;

    printf("%s\n", course->title);
    qnum = 1;
    while (qnum != 0) {
        q = course->questions[qnum];
        AskQuestion(q);
        ans = ConvertToUpperCase(GetLine());
        index = FindAnswer(ans, q);
        if (index == -1) {
            printf("I don't understand that.\n");
        } else {
            qnum = q->answers[index].nextq;
        }
    }
}

/*

 * Function: AskQuestion

 * Usage: AskQuestion(q);

 * ----------------------

 * This function asks the question indicated by the questionT

 * specified by q.  Asking the question consists of displaying

 * each of the lines that comprise the question text.

 */

static void AskQuestion(questionT q)
{
    int i;

    for (i = 0; q->qtext[i] != NULL; i++) {
        printf("%s\n", q->qtext[i]);
    }
}

/*

 * Function: FindAnswer

 * Usage: FindAnswer(ans, q)

 * -------------------------

 * This function looks up the string ans in the list of answers

 * for question q.  If the answer is found, its index in the

 * answer list is returned.  If not, the function returns -1.

 * The function uses a simple linear search algorithm to look

 * through the array.

 */

static int FindAnswer(string ans, questionT q)
{
    int i;

    for (i = 0; i < q->nAnswers; i++) {
        if (StringEqual(ans, q->answers[i].ans)) return (i);
    }
    return (-1);
}


[此贴子已经被作者于2016-3-8 23:42编辑过]

搜索更多相关主题的帖子: numbers 艺术 false C语言 
2016-03-08 23:31
supremeloyal
Rank: 1
等 级:新手上路
帖 子:3
专家分:0
注 册:2016-3-6
收藏
得分:0 
不知道大家有没有什么想法?能不能一起交流一下。

需要的库文件我再上传到附件中。
standard.zip (43.19 KB)


[此贴子已经被作者于2016-3-8 23:43编辑过]

2016-03-08 23:41
rjsp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:528
帖 子:9025
专家分:54030
注 册:2011-1-18
收藏
得分:20 
洋洋洒洒数千字,就是看不懂,尤其是“但其中包含的提示性信息明显不符合实际,……”那段,俺没能“明显”出来

题目这么简单,你贴的代码却那么长,肯定有问题嘛。
大体应该是
int main( void )
{
    struct foo
    {
        题目
        答1
        size_t 答1的下一题索引
        答2
        size_t 答2的下一题索引
        ……
    };

    读文件建立foo数组

    for( size_t i=1; i!=0; )
    {
        根据回答获取下一题的索引
    }
}
当然,没法帮你做,各种细节问清楚了,一整天就过了
2016-03-09 10:04
supremeloyal
Rank: 1
等 级:新手上路
帖 子:3
专家分:0
注 册:2016-3-6
收藏
得分:0 
回复 3楼 rjsp
谢谢版主,可能我没说清楚,请问如何使得下面的情况

 
No.  Floating-point numbers have fractional parts;
integers do not.
True or false: Integers can be negative.
maybe//输入maybe
I don't understand that.
No.  Floating-point numbers have fractional parts;
integers do not.
True or false: Integers can be negative.


变成

No.  Floating-point numbers have fractional parts;
integers do not.
True or false: Integers can be negative.
maybe//输入maybe
I don't understand that.
True or false: Integers can be negative.//第二次不再输出提示性内容



2016-03-09 13:43
快速回复:一道改程序题目,程序较为复杂,还请不吝赐教
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.021765 second(s), 11 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved