c++ scores
Good day. My infile contains the following:
TFFTFFTFFTFFTFTFTFTFFF
A33
TFFTFFTFFFFFTFTFTFFFFT
Z27
TFFTFFTFFTFFTFTFTFTFFT
X12
TFTT FTFFTFFFT FTFTFFF
H44
TFFTFFTFFTFFFFTFTFFTFF
Q19
FFFFFFFFFFFFTFTFTFFFFF
D72
TFFTFFTFFTFF FFFFFTFFF
W32
FFFTFFTFFTFFTFTFTFFTTT
Y09
TFFTFFTFFTFFTFFTTFFTTT
S44
TFFTFFTFFTFFTFTFTFTFFF
G11
FFTFFTFFTFFTFTFTTFTFFF
J21
TFFTFFFFFTFFTFTFTFTFTT
K61
TFFTFFTFFTFFTFTFTFTFT
M03
TFFTFFTFFFFFTFTFTFTFFT
P24
TFFTFFTFFTFFTFTFTFFFFT
N54
FTFFTFFTFT TFF FTFTFFF
F33
TFFTFFTFFTFFTFTFTFTFFF
Z21
TFFTFFFTTFTTFFTFTFTFTF
V39
TFFFTTFTTFTTFTFTFTTFFF
O66
TTFTFFTFFTFFTFTFTFTFFF
B29
TFFTFFTFFTFF FFTTFFTFF
J17
TFFTFFFTTTFFTFFTFTFTTT
K09
TFFTFFTFTTFTTFTFTFFTFF
L99
FFTFFTFFTFFFFTFTFTFFF
My assignment:
The history teacher at the school needs help in grading a True/False test. The
student lD’s and test answers are stored (vertically) in a file named "tftest.txt". The
first entry in the file contains answers to the test in the form
TFFTFFTTTTFFTFTFTFTFTT
All of the other entries in the file are data for a student on 2 lines:
A43
TFFTFFTT TFTFTFFTTFTTT
Note that this student did not answer question 9. The test has 22 questions and
there are not more than 50 students in the class. Each correct answer is awarded 5
points, each incorrect answer is awarded -2 points (negative) and each "no answer"
gets a value of -4 points (negative).
lt can be seen that all test scores will be a whole number.
The student in the example achieved a grade as follows:
14 correct * 5 = 70
7 incorrect * -2 = -14
1 no answer *-4 = -4
70 - 14 -4 = 52 F
His output line would look like:
A43 TFFTFFTT TFTFTFFTTFTTT 52 F
The output should be the student’s ID, the student’s answers followed by the test
score and the test grade. The grade scale is:
Above 90 = A
80 - 89 = B
70 - 79 = C
60 - 69 = D
Below 60 = F
The program should finally display the class average (2 decimals)
...Now where do i even begin? Since the 1st line contains the correct answer...how do i store them so that the other lines are compared to it for the correct answer. I really need a jumpstart with this one. If i use a getline function for example...how will it diffrentiate between the answers i wanna check and the student's id #?
Thanks for all the pointers & input.
zandiago
Nearly a Posting Maven
2,480 posts since Jun 2007
Reputation Points: 129
Solved Threads: 26
>...Now where do i even begin?
You could use everything you've learned in your previous threads that do something similar.
>how do i store them so that the other lines are compared to it for the correct answer.
Just store it in an array:
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iostream>
namespace {
const int NQUESTIONS = 22;
}
int main()
{
std::ifstream in ( "sourcefile" );
if ( !in ) {
std::cerr<<"File open failure\n";
return EXIT_FAILURE;
}
else {
char answers[23];
// Get the correct answers
if ( !in.getline ( answers, sizeof answers )
|| std::strlen ( answers ) != NQUESTIONS )
{
std::cerr<<"Invalid file format\n";
return EXIT_FAILURE;
}
// Process each subsequent record
}
return EXIT_SUCCESS;
}
>If i use a getline function for example...how will it diffrentiate
>between the answers i wanna check and the student's id #?
Obviously because the ID numbers and scores are on two different lines. You read the ID first, then on the next line start processing scores...
Ptolemy
Junior Poster in Training
64 posts since Oct 2007
Reputation Points: 44
Solved Threads: 8
Each line in the file could be read in as a string. The first string would be stored as the correct answer string. The remaining lines alternate between student ID strings and the student answer strings. Once you have a student answer string you compare each element of that string with each element of the correct answer string and keep track of all the appropriate pieces of information with variables that act as counters.
Lerner
Nearly a Posting Maven
2,382 posts since Jul 2005
Reputation Points: 739
Solved Threads: 396
>Once you have a student answer string you compare each element
>of that string with each element of the correct answer string
But from the sample file it looks like if the last N answers were blank, the string is trimmed by that many characters. You also have to keep track of where you hit the end of the student answer string and subtract the correct number of "no answer" values from the score.
Ptolemy
Junior Poster in Training
64 posts since Oct 2007
Reputation Points: 44
Solved Threads: 8
>>But from the sample file it looks like if the last N answers were blank, the string is trimmed by that many characters. You also have to keep track of where you hit the end of the student answer string and subtract the correct number of "no answer" values from the score.
True enough. But I like it better than using sequential calls to something like get(), which would read the file one char at a time without ignoring whitespace, which is the alternative I can think of off the top of my head.
Lerner
Nearly a Posting Maven
2,382 posts since Jul 2005
Reputation Points: 739
Solved Threads: 396
Oh, don't read it as me bashing your solution, it's the same one I'd use. I was just mentioning that little pitfall because I'd noticed it while brainstorming. :)
Ptolemy
Junior Poster in Training
64 posts since Oct 2007
Reputation Points: 44
Solved Threads: 8
Personally, I'd read the test answers into a char* rather than a C++ string . A char* must be defined to accommodate the total number of answers necessary, but a string will read only the answers on the line. If a student doesn't answer the last 5 questions, the string could be short and cause problems. A char* will still have data, however it will have to be cleared after each use.
WaltP
Posting Sage w/ dash of thyme
10,506 posts since May 2006
Reputation Points: 3,348
Solved Threads: 944
If there's supposed to be 20 answers but the last question is unanswered then I suppose it will depend on whether there is a space before the newline char at the end of the line in the file or whether the newline char is right after the T/F for answer 19. If the newline char is right after the answer for question 19 and the line is then read in as a char *, or say char line[21], I wonder whether there would be a null char at line[19] or a space at line[19]? Guess I'll have to try it out for myself when I get the chance.
Lerner
Nearly a Posting Maven
2,382 posts since Jul 2005
Reputation Points: 739
Solved Threads: 396
Tested basic code below:
ofstream fout("practiceText");
char first[6] = "TTTT "; //"TTTT";
fout << first << endl;
fout.close();
ifstream fin("practiceText");
char first2[6];
fin.getline(first2, 6);
//string first2;
//getline(fin, first2);
cout << first2 << endl;
if(first2[4] == ' ')
cout << "space" << endl;
else
cout << "no space" << endl;
fin.close();
Using "TTTT " the version with first2 declared as char[] and string both output space whereas with "TTTT" the version with first2 declared as char[] and string both output no space.
Therefore, if file is set up with trailing spaces as needed for unanswered questions at end of answer line then reading in as either string or char[] should pick up that information whereas if file is set up with newline right after last T/F in the line, then allowances must be made irrespective of type read into. In addition, there's no apparent benefit to reading in answer line char by char with get() instead of with the appropriate version of getline().
Lerner
Nearly a Posting Maven
2,382 posts since Jul 2005
Reputation Points: 739
Solved Threads: 396
Good day:
#include <iomanip>
#include <cmath>
#include <fstream>
#include<string>
#include<iostream>
using namespace std;
void initialize(char test, int sstudent[30]);
void getdata(char test, int sstudent[30]);
int main()
{
ifstream inFile;
ofstream outFile;
inFile.open ("tftest.txt");
outFile.open ("testout");
int i, j, k;
int total=0;
char test;
int student[30];
initialize(test,student);
getdata(test,student);
for(i = 2; i < 30; i = i + 2)
{
for(j = 0; j < 22; j++)
{
cout << student[0].answer.substr(j,1);
if(student[0].answer.substr(j,1) == student[i].answer.substr(j,1))
{
total = total + 5;
}//end if
else if(student[i].answer.substr(j,1) == " ")
{
total = total - 4;
}//end else
else
{
total = total - 2;
}//end else
}//end for
}//end for
return 0;
}// end of main function
//********************************** Function Definitions
void initialize(test sstudent[30])
{
int i;
for(i = 1; i < 30; i++)
{
sstudent[i].id = "";
sstudent[i].answer = "";
}//end for
}//end initialize
//***********************************
void getdata(test sstudent[30])
{
int i;
getline(infile, sstudent[0].answer);
for(i = 1; i < 30; i++)
{
getline(infile, sstudent[i].id);
getline(infile, sstudent[i].answer);
}//end for
infile.close();
}//end getdata
//************************************
Considering the fact that my profesor requires functions, i thought i'd have it like this. Thx for your input.
zandiago
Nearly a Posting Maven
2,480 posts since Jun 2007
Reputation Points: 129
Solved Threads: 26
To be correct syntactally you should change line 57 to look like line 9 without the semicolon and line 68 to look like line 10 without the semicolon.
To be more correct logically you should read the first line of the file into a string to act as the answer key. Then you should use a loop to read the rest of the file. Within the loop you would read the student ID and student answers for each student and print them on a line. Then you compare this students answers with the answer key, calculate this students score, display the score, calculate this students grade, and display the grade before going to the next student information in the file.
Lerner
Nearly a Posting Maven
2,382 posts since Jul 2005
Reputation Points: 739
Solved Threads: 396
Thx for catching the sytax. I've corrected that, i'm just a bit of problems with your second part of your above-mentioned suggestion. Thx for your input.
zandiago
Nearly a Posting Maven
2,480 posts since Jun 2007
Reputation Points: 129
Solved Threads: 26
zandiago
Nearly a Posting Maven
2,480 posts since Jun 2007
Reputation Points: 129
Solved Threads: 26
The key as I see it is this:
His output line would look like:
A43 TFFTFFTT TFTFTFFTTFTTT 52 F
You can read the file student by student processing the information as you go within a loop (see post #12 this thread) or you can read all information in the file into (one or more) containers and process it from there. I think it's easier to the former. Here's a skeleton program outlining the flow with comments copied from post #12. If you go this route you'll have to fill in the details as this is almost going too far as it is.
int main()
{
ifstream inFile("tftest.txt");
ofstream outFile;
double score;
char grade;
string answerKey;
string studentID;
string studentAnswers;
//read the first line of the file into a string to act as the answer key.
getline(inFile, answerKey);
/*Then you should use a loop to read the rest of the file. Within the loop you would read the student ID and student answers for each student and print them on a line. */
while(getline(inFile, studentID))
{
cout << studentID << ' ';
getline(inFile, studentAnswers)
cout << studentAnswers << ' ';
/*Then you compare this students answers with the answer key, calculate this students score, display the score, calculate this students grade, and display the grade*/
score = calculateStudentScore(answerKey, studentAnswers);
cout << score << ' ';
grade = determineStudentGrade(score);
cout << grade << endl;
//before going to the next students information in the file
}
}
You can embellish it a bit by saving each score in array as you to calculate a class average, etc, if desired/required.
Lerner
Nearly a Posting Maven
2,382 posts since Jul 2005
Reputation Points: 739
Solved Threads: 396
#include <iomanip>
#include <cmath>
#include <fstream>
#include<string>
#include<iostream>
using namespace std;
const int ANSWER_SIZE = 23;
int check_correct_answers( char [], char [] );
int check_incorrect_answers( char [], char [] );
int check_no_answer( char [], char [] );
char display_student_grade( int );
int main()
{
ifstream inFile;
ofstream outFile;
inFile.open ("tftest.txt");
outFile.open ("testout");
char student_id[4];
char test_answers[23];
char student_answers[ANSWER_SIZE];
double score;
while (getline(inFile, test_answers))
{
cout << "Test answers: " << test_answers << endl;
cout << "Student answers: " << student_answers << endl;
}
while(getline(inFile, student_id))
{
cout << " " << student_id;
cout << " " << student_answers;
cout << " " << check_correct_answers( test_answers, student_answers ) << " "
<< display_student_grade( check_correct_answers( test_answers, student_answers ) ) << endl;
}
return 0;
}
// CHECK ANSWERS TO TEST
int check_correct_answers( char test_answers[], char student_answers[])
{
int i, correct = 0, incorrect = 0, blank = 0, score = 0;
for (i = 0; i < ANSWER_SIZE - 1; i++)
{
if (test_answers[i] == student_answers[i])
correct++;
if (test_answers[i] != student_answers[i])
incorrect++;
if (student_answers[i] == ' ')
{
blank++;
incorrect--;
}
score = (correct * 5) + (incorrect * -2) + (blank * -4);
}
return score;
}
// PRINT OUT STUDENT GRADES
char display_student_grade( int student_score )
{
int i;
for (i = 0; i < 10; i++)
{
if (student_score >= 90)
return 'A';
else if (student_score < 90 && student_score > 79)
return 'B';
else if (student_score <= 79 && student_score > 69)
return 'C';
else if (student_score <= 69 && student_score > 60)
return 'D';
else if (student_score <= 59)
return 'F';
}
return '0';
}
Ok. if you can see any other problems let me know. I get the following error messages...it has to do with my use of 'getline'.
1>Compiling...
1>truefalse.cpp
1>c:\users\documents\visual studio 2008\projects\truefalse\truefalse\truefalse.cpp(33) : error C2784: 'std::basic_istream<_Elem,_Traits> &std::getline(std::basic_istream<_Elem,_Traits> &,std::basic_string<_Elem,_Traits,_Alloc> &)' : could not deduce template argument for 'std::basic_istream<_Elem,_Traits> &' from 'std::ifstream'
1> c:\program files\microsoft visual studio 9.0\vc\include\string(527) : see declaration of 'std::getline'
1>c:\users\documents\visual studio 2008\projects\truefalse\truefalse\truefalse.cpp(33) : error C2784: 'std::basic_istream<_Elem,_Traits> &std::getline(std::basic_istream<_Elem,_Traits> &,std::basic_string<_Elem,_Traits,_Alloc> &)' : could not deduce template argument for 'std::basic_string<_Elem,_Traits,_Alloc> &' from 'char [23]'
1> c:\program files\microsoft visual studio 9.0\vc\include\string(527) : see declaration of 'std::getline'
1>c:\users\documents\visual studio 2008\projects\truefalse\truefalse\truefalse.cpp(33) : error C2780: 'std::basic_istream<_Elem,_Traits> &std::getline(std::basic_istream<_Elem,_Traits> &,std::basic_string<_Elem,_Traits,_Alloc> &,const _Elem)' : expects 3 arguments - 2 provided
1> c:\program files\microsoft visual studio 9.0\vc\include\string(475) : see declaration of 'std::getline'
1>c:\users\documents\visual studio 2008\projects\truefalse\truefalse\truefalse.cpp(33) : fatal error C1903: unable to recover from previous error(s); stopping compilation
1>Build log was saved at "file://c:\Users\Documents\Visual Studio 2008\Projects\truefalse\truefalse\Debug\BuildLog.htm"
1>truefalse - 4 error(s), 0 warning(s)
zandiago
Nearly a Posting Maven
2,480 posts since Jun 2007
Reputation Points: 129
Solved Threads: 26
score = calculateStudentScore(answerKey, studentAnswers);
grade = determineStudentGrade(score);
Ok guys thanks for the feedback...i've taken both suggestions and will be making own program. But Lerner, what do the two above lines do?
zandiago
Nearly a Posting Maven
2,480 posts since Jun 2007
Reputation Points: 129
Solved Threads: 26
This is what it has come down to:
#include <iomanip>
#include <cmath>
#include <fstream>
#include<string>
#include<iostream>
using namespace std;
int check_correct_answers ( char answerKey[], char studentAnswers[], char grade, double score);
char display_student_grade( int score);
int main()
{
ifstream inFile;
ofstream outFile;
inFile.open ("tftest.txt");
outFile.open ("testout");
double score;
char grade;
string answerKey;
string studentID;
string studentAnswers;
getline(inFile, answerKey);
cout<<"The correct answers "<<answerKey << endl<<endl;
while(getline(inFile, studentID))
{
cout << studentID <<" ";
getline(inFile, studentAnswers);
cout << studentAnswers << endl;
}
return 0;
}
int check_correct_answers( char answerKey[], char studentAnswers[], int score, char grade)
{
int i, correct = 0, incorrect = 0, blank = 0;
for (i = 0; i < 23 - 1; i++)
{
if (answerKey[i] == studentAnswers[i])
correct++;
if (answerKey[i] != studentAnswers[i])
incorrect++;
if (studentAnswers[i] == ' ')
{
blank++;
incorrect--;
}
score = (correct * 5) + (incorrect * -2) + (blank * -4);
}
cout << score << endl;
return score;
}
// PRINT OUT STUDENT GRADES
char display_student_grade( int score )
{
int i;
for (i = 0; i < 30; i++)
{
if (score >= 90)
cout<<"A"<<endl;
else if (score < 90 && score > 79)
cout<< "B"<<endl;
else if (score <= 79 && score > 69)
cout<< "C"<<endl;
else if (score <= 69 && score > 60)
cout<< "D"<<endl;
else if (score <= 59)
cout<< "F"<<endl;
}
return 0;
}
My two problems:
It doesn't show the numeric grade beside the persons info, nor the student's letter grade equivalent. It does readin the values(students records) just fine. Thx for your input.
zandiago
Nearly a Posting Maven
2,480 posts since Jun 2007
Reputation Points: 129
Solved Threads: 26
Try commenting your code:
getline(inFile, answerKey); // Get the answer key
cout<<"The correct answers "<<answerKey << endl<<endl;
while(getline(inFile, studentID)) // Read student ID
{
cout << studentID <<" "; // display the current student
getline(inFile, studentAnswers); // read the student's answers
cout << studentAnswers << endl; // Output the answers
}
return 0;
}
What seems to be missing?
And you still need to work on your formatting.
WaltP
Posting Sage w/ dash of thyme
10,506 posts since May 2006
Reputation Points: 3,348
Solved Threads: 944
Thanks for responding....i dunno what's missing. Aren't my two functions that i have there suppose to provide me with the letter and number grade:
int check_correct_answers( char answerKey[], char studentAnswers[], int score, char grade)
&
char display_student_grade( int score )
zandiago
Nearly a Posting Maven
2,480 posts since Jun 2007
Reputation Points: 129
Solved Threads: 26
Am i not allowed to do this in the main function:
int main()
{
ifstream inFile;
ofstream outFile;
inFile.open ("tftest.txt");
outFile.open ("testout");
double score = 0;
char grade;
string answerKey;
string studentID;
string studentAnswers;
check_correct_answers (answerKey[] , studentAnswers[] , grade, score);
display_student_grade(score);
getline(inFile, answerKey);
cout<<"The correct answers "<<answerKey << endl<<endl;
while(getline(inFile, studentID))
{
cout << studentID <<" ";
getline(inFile, studentAnswers);
cout << studentAnswers << endl;
}
return 0;
}
zandiago
Nearly a Posting Maven
2,480 posts since Jun 2007
Reputation Points: 129
Solved Threads: 26