Search code examples
c++filefile-iofstreamifstream

Issue reading file and using Arrays to store and check content correctly


I'm working on an assignment that reads from a text file, which contains correct answers to a fictional true or false test, and then contains a Student ID, that student's answers, and then the next line is repeated with another student. I'm attempting to go through the file and store the content in arrays, but there appears to be something wrong as the third entry gets cut off halfway through.

I have tried to rewrite my loop structure, rename the arrays, and replace the New lines with single character versions instead of the string versions, and even give them their own cout statement.

string studentId;
char answers [20];
char response;
int testScore = 0;

ifstream inFile;
inFile.open ("Ch8_Ex6Data.txt");

for (int i=0; i<20; i++)
    {
    inFile >> answers [i];
    }

    while ( ( inFile >> studentId))
        {
        cout << '\n' << studentId << ' ';
        inFile.get(response);
        testScore = 0;
        for (int i = 0; i < 20; i++)
            {
            inFile.get (response);
            cout << response;
            if (response == ' ')
                {
                testScore = testScore - 2;
                }
                else if (response == answers [i])
                {
                testScore = testScore + 2;
                }
                else
                {
                testScore = testScore -1;
                }
            }
            cout << ' ' << testScore << ' ';
            double p = testScore * 2.5;
            if (p >= 89)
                {
                cout << 'A';
                }
            else if (p >=79)
                {
                cout << 'B';
                }
            else if (p >=69)
                {
                cout << 'C';
                }
            else if (p >=59)
                {
                cout << 'D';
                }
            else if (p <= 59)
                {
                cout << 'F';
                }
        }
    inFile.close();
    return 0;
    }

The output I recieve is
ABC54102 T FTFTFTTTFTTFTTF TF 23 F
DEF56278 TTFTFTTTFTFTFFTTFTTF 40 A
ABC42366 TTFTFTTTFTFTFFTTF
AB 31 C
C42586 TTTTFTTT TFTFFFTF

21 F

When I had hoped it would continue, as

ABC54102 T FTFTFTTTFTTFTTF TF 27 F
DEF56278 TTFTFTTTFTFTFFTTFTTF 40 A
ABC42366 TTFTFTTTFTFTFFTTF 34 B
ABC42586 TTTTFTTT TFTFFFTF 26 D

I'm not sure as to why it does this, and also incorrectly calculates the first entries score.

This is the text file.
TTFTFTTTFTFTFFTTFTTF
ABC54102 T FTFTFTTTFTTFTTF TF
DEF56278 TTFTFTTTFTFTFFTTFTTF
ABC42366 TTFTFTTTFTFTFFTTF
ABC42586 TTTTFTTT TFTFFFTF


Solution

  • You want to modularize your code. You want to break up your code into different functions where each function performs its own task or has its own responsibility.

    Here is what I was able to come up with using your code. Now my code is working properly however it differs from your expected results, this might be due to the value(s) you are using within your calculations. However; you should model your code to something of what I am proposing here:

    main.cpp

    #include <string>
    #include <vector>
    #include <iostream>
    #include <ifstream>
    
    #include "Student.h"
    
    char calculateGrade( int score );
    void calculateScores( Student& student, const std::string& answers );
    
    int main() {
        // Open our file for reading
        std::ifstream in;
        in.open("Ch8_Ex6Data.txt");
    
        // get the first line to retrieve the test answers
        std::string testAnswers;
        std::getline(in, testAnswers); 
    
        // read the rest of the file and get the students id's and answers
        // then populate our vector of students
        std::vector<Student> students;
        std::string line;
        while (std::getline(in, line)) {
            // parse each line correctly to populate each student's information
            Student s;
            s.id_ = line.substr(0, line.find_first_of(' '));
            s.testAnswers_ = line.substr(line.find_first_of(' ') + 1);
            students.push_back(s);
        }
    
        // Now that we have the information we can calculate the test scores
        for (auto& s : students)
            calculateTestScores(s, testAnswers);
    
        // We can finally print all of the students results
        for (auto& s : students)
            std::cout << s;
    
        return EXIT_SUCCESS;
    }
    
    char calculateGrade(int score) {
        float p = score * 2.5f;
        if (p >= 89)
            return 'A';
        if (p >= 79 && p < 89)
            return 'B';
        if (p >= 69 && p < 79)
            return 'C';
        if (p >= 59 && p < 69)
            return 'D';
        if (p < 59 )
            return 'F';
    
        return ' ';
    }
    
    void calculateTestScores(Student& student, const std::string& answers) {
        int score = 0;
        int i = 0;
        for (auto& c : student.testAnswers_) {
            if (c == ' ')
                score -= 2;
            else if (c == answers[i])
                score += 2;
            else
                score -= 1;
    
            i++;
        }
    
        student.score_ = score;
        student.grade_ = calculateGrade(student.score_);
    }
    

    Student.h

    #ifndef STUDENT_H
    #define STUDENT_H
    
    // or #pragma once
    
    #include <string>
    #include <iostream>
    
    struct Student {
        std::string id_;
        std::string testAnswers_;
        int score_;
        char grade_;
    };
    
    std::ostream& operator<<( std::ostream& os, const Student& s );
    
    #endif // STUDENT_H
    

    Student.cpp

    #include "Student.h"
    
    std::ostream& operator<<(std::ostream& os, const Student& s) {
        return os << s.id_ << ' ' << s.testAnswers_
            << ' ' << s.score_ << ' ' << s.grade_
            << '\n';
    }
    

    When I run this code in my IDE I end up with this output as my result:

    ABC54102 T FTFTFTTTFTTFTTF TF 23 F
    DEF56278 TTFTFTTTFTFTFFTTFTTF 40 A
    ABC42366 TTFTFTTTFTFTFFTTF 34 B
    ABC42586 TTTTFTTT TFTFFFTF  22 F
    

    There is one possible issue that I can see and it pertains to the structure of your text file. The above may fail to calculate the scores correctly when answers at the end of each line in the text file are white spaces. So you may have to modify the function that calculates the score to incorporate how many answers were given for how many there are supposed to be. I'll leave that as an exercise for you. The suggestion here is using the string's built in functions to query for its size or length.