无法在C ++程序中正确读取文本文件

问题描述 投票:0回答:1

这里是一个程序,应该加载一些测验,允许进行测验,然后显示结果。我已经重新编写了代码,并狂热地检查了语法错误,但是似乎无法弄清楚为什么它不能正确加载文本文件。我还在Dev C ++和VS代码之间切换,以查看是否可以解决问题,唯一的区别是VS代码给了我一个错误代码-有所不同。在本文发布时,我正在使用Dev C ++。

尽管我确实取得了突破,但是我能够加载文本文件,但问题未正确加载。

具有正确格式的文本文件的内容:

1
TF 
5
6 is equal to 3+3
true

从问题的数量开始,然后是问题的类型TF =是/否,然后是问题的点值,然后是问题,然后是答案。

此已加载,但没有问题(请参见下面的屏幕截图)。

“错误”

我尝试添加更多问题并遵循上述格式,但又回到了原来的问题。

代码

/*This program consists of a menu that allows users to load questions to a vector, then display them to the screen. */
#include <iostream>
#include <iomanip>
#include <string>
#include <fstream>
#include <cstdlib>
#include <vector>
#include <stdexcept>

using namespace std;

class Question // super class
{
private:
    string question, questiontype;
    string answer;
    string options;
    int points;
public:
    virtual string getQuestion() //gets the question
    {
        return question;
    }
    virtual int getValue() //gets the point value of the question
    {
        return points;
    }
    virtual void setQuestion(string answer, int points)
    {
    }
    virtual void getOptions()
    {
    }
    virtual string getAnswer()
    {
        return answer;
    }
};

class TFQuestion : public Question// class for true and false questions
{
private:
    string question, questiontype;
    string answer;
    int points;
public:
    string getQuestion() //gets the question
    {
        return question;
    }
    int getValue() //gets the point value of the question
    {
        return points;
    }
    //function to read lines in a file to create new object
    void setQuestion(string theQuestion, int pointValue)
    {
        string theAnswer;
        question = theQuestion;
        points = pointValue;
        getline(cin, theAnswer);
        answer = theAnswer;
    }
    void getOptions() //prints the options for that question
    {
        cout << "True or False" << endl;
    }
    string getAnswer() //outputs the answer for that question
    {
        return answer;
    }
};

class MCQuestion : public Question //class for multiple choice
{
private:
    int numberOfOptions;
    string question;
    string options[6];
    string answer;
    int points;
public:
    string getQuestion()
    {
        return question;
    }
    int getValue() //gets the point value of the question
    {
        return points;
    }
    //function to read lines in a file to create new object
    void setQuestion(string theQuestion, int pointValue)
    {
        string line;
        getline(cin, line);
        numberOfOptions = stoi(line);
        question = theQuestion;
        points = pointValue;
        //get the individual choice lines and load to options array
        for (int count = 0; count < numberOfOptions; count++) {
            getline(cin, line);
            options[count] = line;
        }
        //get the answer from the file
        getline(cin, line);
        answer = line;
    }
    void getOptions() // gets the options
    {
        char first = 'A';
        for (int count = 0; count < numberOfOptions; count++)
        {
            cout << first++ << ". " << options[count] << "\n";
        }
    }
    string getAnswer()// prints the answer
    {
        return answer;
    }
};

class Exam //class for exams
{
private:
    vector <Question*> myQuestions; //creates new vector to hold Question objects
    int numquestions;
public:
    int loadExam(ifstream& fin) //function to read file contents and store objects in the vector
    {
        myQuestions.clear();
        string line, theQuestion, questiontype, theAnswer;
        int questionvalue;
        streambuf* cinbuf = cin.rdbuf(); //save old buf
        cin.rdbuf(fin.rdbuf()); //redirect std::cin to file
        //get the number of questions from the first line in the file
        getline(cin, line);
        numquestions = stoi(line);
        for (int count = 0; count < numquestions; count++)
        {
            getline(cin, line);
            questiontype = line;
            getline(cin, line);
            questionvalue = stoi(line);

            if (questiontype == "TF")
            {
                myQuestions.push_back(new TFQuestion); //add new TFQuestion to the vector
                getline(cin, theQuestion);
                myQuestions[count]->setQuestion(theQuestion, questionvalue);
            }

            if (questiontype == "MC")
            {
                myQuestions.push_back(new MCQuestion); //add new MC question to the vector
                getline(cin, theQuestion);
                myQuestions[count]->setQuestion(theQuestion, questionvalue);
            }
        }
        cin.rdbuf(cinbuf); //restore cin to standard input

        return myQuestions.size(); //returns vector size to validate data properly added.
    }

    //function to display each question for the user
    void displayExamQuestion(int i)
    {
        cout << "Question # " << (i + 1) << endl;
        cout << myQuestions[i]->getQuestion() << endl;
        myQuestions[i]->getOptions();
    }
    int getNumberOfQuestions()
    {
        return myQuestions.size();
    }
    string getCorrectAnswer(int i)
    {
        return myQuestions[i]->getAnswer();
    }
    int getPointsValue(int i)
    {
        return myQuestions[i]->getValue();
    }
};

class Student
{
private:
    int pointsPossible;
    int pointsEarned;
public:
    Student()
    {
        pointsPossible = 0;
        pointsEarned = 0;
    }
    int getPointsPossible()
    {
        return pointsPossible;
    }
    int getPointsEarned()
    {
        return pointsEarned;
    }
    void setPointsPossible(int points)
    {
        pointsPossible = points;
    }
    void setPointsEarned(int points)
    {
        pointsEarned = points;
    }
};

//Function prototypes
string ConvertToupper(string);
int displayMenu();

int main()
{
    Exam myExam;
    Student s;
    /*initialize numquestions variable to zero helps with data validation. Number should change
    if loadExam function is successful.*/
    int numquestions = 0;
    int choice;
    try
    {   //loop to be executed until user chooses option 4 to quit the program
        while ((choice = displayMenu()) != 4)
            switch (choice)
            {
            case 1: //execute when load exam is chosen
            {
                string file;
                cout << "Enter the name of the file you would like to load questions from: ";
                cin >> file;
                ifstream fin;
                fin.open(file.c_str());
                while (!fin)
                {
                    cout << "Error.  File not found. Try again." << endl;
                    cout << "Enter the name of the file including the extension (i.e. 'test.txt'): " << endl;
                    cin >> file;
                    fin.open(file.c_str());
                }
                numquestions = myExam.loadExam(fin);
                cout << "Success! Number of questions loaded:  " << numquestions << endl; //inform user of number of questions loaded
                fin.close();
                system("PAUSE");
            }
            break;
            case 2: //execute when display exam is chosen.
                if (numquestions == 0) //this would indicate no questions are loaded
                {
                    cout << "No questions to display. Questions might not have been loaded." << endl;
                    system("PAUSE");
                }
                else //executes as long as there are questions loaded in the vector
                {
                    for (int i = 0; i < myExam.getNumberOfQuestions(); i++)
                    {
                        system("CLS"); //clear the screen for each new question
                        int pts = myExam.getPointsValue(i); //variable to be used for points possible and earned
                        s.setPointsPossible(s.getPointsPossible() + pts); //add to the total possible points
                        myExam.displayExamQuestion(i);
                        cout << endl << "Please enter your answer :  ";
                        string answer;
                        cin >> answer;
                        //convert user input and correct answer to ensure proper capitalization
                        answer = ConvertToupper(answer);
                        string corrAnswer = ConvertToupper(myExam.getCorrectAnswer(i));
                        cout << "Correct answer is: " << corrAnswer << endl;
                        if (answer == corrAnswer) //output if user answers correctly
                        {
                            cout << "Correct! Good job!" << endl;
                            s.setPointsEarned(s.getPointsEarned() + pts); //add points value to points earned
                        }
                        else //output if user answers incorrectly
                        {
                            cout << "That is incorrect." << endl;
                        }
                        system("PAUSE");
                    }
                    cout << endl << "You have completed the exam!" << endl; //informs user they have reached end of exam
                    system("PAUSE");
                }
                break;
            case 3: //displays user exam results
            {
                try
                {   //obtain and convert points earned and points possible to double and calculate percentage
                    double totalScore = ((double)s.getPointsEarned() / (double)s.getPointsPossible()) * 100.0;
                    if ((s.getPointsPossible() == 0) && (s.getPointsEarned() == 0))
                    {
                        cout << "No results to display. You need to take an exam first." << endl;
                        system("PAUSE");
                    }
                    else
                    {
                        cout << "Total points possible: " << s.getPointsPossible() << endl;
                        cout << "Total points earned:  " << s.getPointsEarned() << endl;
                        cout << "Final Score: " << fixed << setprecision(0) << totalScore << "% " << endl;
                        system("PAUSE");
                    }
                }
                catch (runtime_error& e) //in the event of a divide by zero exception occurs
                {
                    cout << "An exception occurred: " << e.what() << endl;
                }  
                break;
            }
            default: cout << "Invalid choice.  Try again.\n";
            }
    }
    catch (...) //if any exception occurs while running the program
    {
        cout << "Your choice caused an issue. Check your code. " << endl;
    }
    cout << "Thank you!" << endl;
    getchar();
    return 0;
}

string ConvertToupper(string s) //converts only the first character of a string to uppercase
{
    string str = s;
    str[0] = toupper(str[0]);
    return str;
}

int displayMenu() //menu function
{
    int choice;
    system("CLS"); //clears the screen to make it easier to read for users
    cout << "Enter your choice for this Exam." << endl;
    cout << "1.   Load Exam " << endl;
    cout << "2.   Take Exam " << endl;
    cout << "3.   Display Exam Results " << endl;
    cout << "4.   Quit" << endl;
    cin >> choice;
    return choice;
}
c++ file vector fstream
1个回答
0
投票

问题出在文本文件中。光标必须落在每行的最后一个字符上。如果光标不落在加载文件时每行的最后一个字符上。程序将不会加载文件或出现运行时错误。

我不确定为什么从技术角度来看会导致错误。

© www.soinside.com 2019 - 2024. All rights reserved.