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.

>...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...

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.

>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.

>>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.

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. :)

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.

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.

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().

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.

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.

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.

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.

#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)
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?

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.

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.

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 )

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;
}

Yes, they are there to provide you with the answer. Just because you buy a bread machine does not mean you always have bread ready. You have to actually use the thing first. Where did you use the functions...

Nice illustration....this is most recent post:

#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 = 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;
}
   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;
}

It however, gives me:

1>Compiling...
1>grading.cpp
1>c:\users\documents\visual studio 2008\projects\grading\grading\grading.cpp(34) : error C2059: syntax error : ']'

This was in reference to(which is in the main function) :

check_correct_answers (answerKey[] , studentAnswers[] , grade, score);

It however, gives me:

1>Compiling...
1>grading.cpp
1>c:\users\documents\visual studio 2008\projects\grading\grading\grading.cpp(34) : error C2059: syntax error : ']'

This was in reference to(which is in the main function) :

check_correct_answers (answerKey[] , studentAnswers[] , grade, score);

Change it to check_correct_answers (answerKey , studentAnswers, grade, score); When passing an array, just the name is necessary.

You must call the functions when you have data. You can't call the functions willy-nilly just to get them in the code.

Ask yourself, does it make sense to check the students answers against the answer key or determine their grade before I know what the answer key is or what the students answers were? Because that's what you are trying to do with the current placement of the function calls.

There is no sense sending score to check_correct_answers if you are going to return it. Either return score and just pass the two answer strings or send array to the function by reference so it's value is useable back in main().

Remember that an object of the string class isn't the same thing as null terminated string object, so make your string types match. Fixing this misnatch will correct the error message you quote in #22.

grade is never used in check_correct_answers() so don't send it.

If you don't want to start a new line aftter displaying the students answers or the students scores then don't call endl, which tells cout to go to a new line.

I did try to change it as you pointed out WaltP...but then i got:

1>c:\users\documents\visual studio 2008\projects\grading\grading\grading.cpp(34) : error C2664: 'check_correct_answers' : cannot convert parameter 1 from 'std::string' to 'char []'

Paragraph 3 post #24 tells you what to do to fix this error: make your string types consistent througout your program. Use either STL strings or null terminated char arrays, but not both, at least until you know how to convert from one to the other.

Missed that one Lerner....thx...let me repost....at this point i'm still getting the data and the students records, i'm just working on the function to compare the answerKey to the students actual grade.

#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 = 0;
    char grade;   
  
   string answerKey;
   string studentID;
   string studentAnswers;

   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;
}

i guess because of how i've got my functions, it prints out a bunch of F's for the grades?

Since you've eliminated any definition of the display_student_grades () function I'm surprised it compiles, let alone prints out a grade value of any type.

You still haven't moved the function call for display_student_grade() to the appropriate spot, even when you have a copy of a program outline that explicitly shows you where to put it. (Though I admit that determineStudentGrade() and display_student_grade() aren't the same function names so that may be what has you confused.) As is, grade is initialized to 0 before it is sent to the display_student_grade() outside the while loop, so it should print out F (you never give it a different score value to work with), if you had your prior function definition in force.

The code i had before wasn't the entire code..it was just the main function. This is my whole code:

#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 = 0;
    char grade;   
  
   string answerKey;
   string studentID;
   string studentAnswers;

   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;
}
   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;
}
This question has already been answered. Start a new discussion instead.