Need assistance with this code please!!

Instructions: The history teacher at your school needs help in grading a True/False test. The students’ IDs and test answers are stored in a file. The first entry in the file contains answers to the test in the form:
TFFTFFTTTTFFTFTFTFTT
Every other entry in the file is the student ID, followed by a blank, followed by the student’s responses. For example, the entry:
ABC54301 TFTFTFTT TFTFTFFTTFT
indicates that the student ID is ABC54301 and the answer to question 1 is True, the answer to question 2 is False, and so on. This student did not answer question 9. The exam has 20 questions, and the class has more than 150 students. Each correct answer is awarded two points, each wrong answer gets one point deducted, and no answer gets zero points.

Write a program that processes the test data. The output should be the student’s ID, followed by the answers, followed by the test score, followed by the test grade. Assume the following grade scale:
90%–100%, A; 80%–89.99%, B; 70%–79.99%, C; 60%–69.99%, D; and 0%–59.99%, F

My issue is that I can get the first two right, but then the next two grades are a few digits off. Any Help?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include <iostream>
#include <fstream>
#include <cstring>
using namespace std;

int main(){
  char studentAnswer[20];
  char studentResponses;
  int totalScore;
  string id;

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

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

  while(inFile >> id){
    cout << id << " ";
    inFile.get(studentResponses);
    totalScore = 0;

    for(int i = 0; i < 20; i++){
        inFile.get(studentResponses);
        cout << "" << studentResponses;

        if(studentResponses == ' '){
          totalScore+=0;
        }
        else if(studentResponses == studentAnswer[i]){
          totalScore+=2;
        }
        else{
          totalScore-=1;
        }
    }

    cout << " " << totalScore << " ";
    double a = totalScore * 2.5;

    if(a >= 90){
        cout << 'A' << endl;
    }
    else if(a >= 80){
        cout << 'B' << endl;
    }
    else if(a >= 70){
        cout << 'C' << endl;
    }
    else if(a >= 60){
        cout << 'D' << endl;
    }
    else{
      cout << 'F' << endl;
    }

  }
  return 0;
}

Ch8_Ex6Data.txt:
1
2
3
4
5
TTFTFTTTFTFTFFTTFTTF
ABC54102 T FTFTFTTTFTTFTTF TF
DEF56278 TTFTFTTTFTFTFFTTFTTF
ABC42366 TTFTFTTTFTFTFFTTF
ABC42586 TTTTFTTT TFTFFFTF
Last edited on
You are not reading in the answer key as the answer key. You are reading it as if it were a student's answers.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <cstdlib>

int main()
{
   std::ifstream inFile("Ch8_Ex6Data.txt");

   if (!inFile)
   {
      std::cout << "Unable to open file, exiting....\n";
      return EXIT_FAILURE;
   }

   // read the answer key
   std::string answerKey;
   std::getline(inFile, answerKey);

   // get the number of answers based on the size of the answer key
   // never hard code a size using a "magic number" like 20
   size_t num_questions { answerKey.size() };

   std::string student;

   // read an entire file data line
   while (std::getline(inFile, student))
   {
      // parse out the student ID
      std::string id;
      std::stringstream studentData(student);
      studentData >> id;

      std::cout << id << ' ';

      // parse out each student's answers 
      std::string studentAnswers;
      std::getline(studentData >> std::ws, studentAnswers);

      // sanity check, make sure the number of answers matches the size of the answer key
      if (studentAnswers.size() < num_questions)
      {
         // if not enough answers resize and fill with blanks
         studentAnswers.resize(num_questions);
      }

      int totalScore { };

      for (size_t i { }; i < num_questions; ++i)
      {
         if (answerKey[i] == studentAnswers[i])
         {
            // correct answer +2
            totalScore += 2;
         }
         else if (studentAnswers[i] == ' ')
         {
            // didn't answer no score
            ;
         }
         else
         {
            // wrong answer, - 1
            totalScore--;
         }
      }

      std::cout << totalScore << ' ';

      double a { totalScore * 2.5 };

      std::cout << a << ' ';

      if (a >= 90)      { std::cout << "A\n"; }
      else if (a >= 80) { std::cout << "B\n"; }
      else if (a >= 70) { std::cout << "C\n"; }
      else if (a >= 60) { std::cout << "D\n"; }
      else              { std::cout << "F\n"; }
   }
}
ABC54102 27 67.5 D
DEF56278 40 100 A
ABC42366 31 77.5 C
ABC42586 23 57.5 F
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
#include <algorithm>

int main() {
	std::ifstream inFile("Ch8_Ex6Data.txt");

	if (!inFile)
		return (std::cout << "Unable to open file, exiting....\n"), 1;

	std::string answerKey;
	size_t max_id {}, max_ans {};

	std::getline(inFile, answerKey);

	for (std::string student, answers; std::getline(inFile >> student >> std::ws, answers); ) {
		int totalScore { };

		if (student.size() > max_id)
			max_id = student.size();

		if (answers.size() > max_ans)
			max_ans = answers.size();

		for (size_t i {}, quest { std::min(answerKey.size(), answers.size()) }; i < quest; ++i)
			if (answers[i] == answerKey[i])
				totalScore += 2;
			else if (answers[i] != ' ')
				--totalScore;

		const auto a { totalScore * 2.5 };

		std::cout << std::left << std::setw(max_id + 3) << student << std::setw(max_ans + 3) << answers <<
			std::right << std::setw(5) << totalScore << std::setw(8) << std::setprecision(2) << std::fixed << a << "%  ";

		if (a >= 90)
			std::cout << "A\n";
		else if (a >= 80)
			std::cout << "B\n";
		else if (a >= 70)
			std::cout << "C\n";
		else if (a >= 60)
			std::cout << "D\n";
		else
			std::cout << "F\n";
	}
}



ABC54102   T FTFTFTTTFTTFTTF TF      27   67.50%  D
DEF56278   TTFTFTTTFTFTFFTTFTTF      40  100.00%  A
ABC42366   TTFTFTTTFTFTFFTTF         34   85.00%  B
ABC42586   TTTTFTTT TFTFFFTF         26   65.00%  D

Last edited on
For my class we're not allowed to use strings like you use, we have to use chars. that is where I'm struggling, how do you find the size of a char array from inFile?
you don't.
here, you seem to know the approximate length.
just use
char mystring[1000]; //it can work on anything in the file up to 999 characters + the zero
and strlen(mystring); //its actual length after reading it from the file.
there are also ways to figure out how long the line is and allocate dynamic memory to fit and so on, but its way overkill.
Last edited on
The big problem with the data and C strings is the line length is not always the same. Having "blank" answers at the end of the line is not read as blanks. The data is 'incomplete.' You are going to have to pad the C string to be the same length as the data lines that have 'T' or 'F' terminating the data line, or parse out the actual number of answers store that. Any loop over that number of answers is "not answered."

M'ok, you are using std::string for id. Why is that allowed, yet not for reading the student's answers? Inconsistent.

Hint, if you are going to use std::string (and you are since you have using namespace std; cluttering things up) you need to #include <string> .

If you had mentioned first thing you can't use std::string we would have not run into the weeds.
we're not allowed to use strings like you use, we have to use chars


You are taking a C++ class? To paraphrase, "When in C++, do as C++"..

Ok. It's quite easy to convert my code from above to not use std::string.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <iostream>
#include <fstream>
#include <iomanip>
#include <algorithm>
#include <cstring>

constexpr size_t MAXCHAR { 100 };

int main() {
	std::ifstream inFile("Ch8_Ex6Data.txt");

	if (!inFile)
		return (std::cout << "Unable to open file, exiting....\n"), 1;

	char answerKey[MAXCHAR] {};

	inFile.getline(answerKey, MAXCHAR);

	const auto keySize { std::strlen(answerKey) };
	size_t max_id {}, max_ans {};

	for (char student[MAXCHAR] {}, answers[MAXCHAR] {};
		    (inFile >> std::setw(MAXCHAR) >> student >> std::ws) && inFile.getline(answers, MAXCHAR); ) {
		const auto studSize { std::strlen(student) };
		const auto ansSize { std::strlen(answers) };
		int totalScore { };

		if (studSize > max_id)
			max_id = studSize;

		if (ansSize > max_ans)
			max_ans = ansSize;

		for (size_t i {}, quest { std::min(keySize, ansSize) }; i < quest; ++i)
			if (answers[i] == answerKey[i])
				totalScore += 2;
			else if (answers[i] != ' ')
				--totalScore;

		const auto a { totalScore * 2.5 };

		std::cout << std::left << std::setw(max_id + 3) << student << std::setw(max_ans + 3) << answers <<
			std::right << std::setw(5) << totalScore << std::setw(8) << std::setprecision(2) << std::fixed << a << "%  ";

		if (a >= 90)
			std::cout << "A\n";
		else if (a >= 80)
			std::cout << "B\n";
		else if (a >= 70)
			std::cout << "C\n";
		else if (a >= 60)
			std::cout << "D\n";
		else
			std::cout << "F\n";
	}
}

Registered users can post here. Sign in or register to post.