Help!!! writng a program that outputs to a .dat file

I have been asked to write a program to grade several multiple-choice exams. The exam has less than 80 questions, each answered with a letter in the range of ‘a’ through ‘f’. The data are stored on several files such as exam1.dat where the first line is the key, consisting of a string of n characters (0<n < 80). The remaining lines on the file are exam answers, and consist of a student ID number, a space, and a string of n characters.

The program should have a while loop in the main routine to ask users input a data file name through keyboard. In this way, the program has a capability of repeatedly asking for a new data file in each while loop until users input a key word “exit”. Once “exit” is encountered, the while loop terminates and your program ends. A typical input exam data file (exam1.dat) looks like:

abcdefabcdefabcdefab
1234567 abcdefabcdefabcdefab
9876543 abddefbbbdefcbcdefac
5554446 abcdefabcdefabcdef
4445556 abcdefabcdefabcdefabcd

Apply strlen( ) or the length( ) of string to the first line of the above data file for determining the number of questions in the problem. If a student gives more answers than necessary, the extra answers will be automatically truncated. On the other hand, if a student provides less number of answers, the remaining unanswered questions are considered as being answered wrongly.

After users input an exam data file, your program should ask users to input another grade-curving file name (e.g., gradeCurving.dat). This second file contains the information to convert a percentile score to a curved grade in levels of ‘A’ through ‘E’. For instance, a grade-curving file takes the following format: a curved alphabetic grade, a space, a percentile grade served as marker.

A 90
B 80
C 70
D 60
E 50

The above information means that ‘A’ = 90 through 100; ‘B’=80 through 89; ‘C’=70 through 79; ‘D’ = 60 through 69; “E”=50 through 59; For the remaining grades, you can assign an ‘F’.

Furthermore, in each while loop in the main routine, your program should ask users to input an output file name such as score1.dat. The output file will store the scores for each student in a format: student ID number, a space, a percentile score, and a curved grade in ‘A’ though ‘E’. The program should also compute and display the following statistics for the graded answers: Average score, Maximum score, and Minimum score.


A typical output on a data file looks like:

1234567 90% A
9876543 85% B
5554446 95% A
4445556 75% C
5551112 80% B
Statistics:
Average Score: 85%
Minimum Score: 95%
Maximum Score: 75%

This Is what I have so far. It compiles fine and everything but when I input the files it says "There was an error opening the corresponding files. Check input name perhaps?" an it exits out so can anyone help. It would be appreciated. I'm going to keep working on it but I've been doing this for weeks.

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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#include "stdafx.h"
#include <iostream>
#include <string>
#include <fstream>
#include <assert.h>
using namespace std;

int openfiles(ifstream& infile, ifstream& curvingfile, ofstream& outfile);

void Size(ofstream&,int,string);

int main()
{
	int num_student = 4, count, length, score2, w[6];

	ifstream infile, curvingfile; char x;

	ofstream outfile; float score;

	int open = openfiles(infile, curvingfile, outfile);

	if (open != 3)   
	{       
		cout << "There was an error opening the corresponding files. Check input name perhaps?" << endl;        
		return 0;   
	}

	string  key, answer, id;

	 do {        
		 openfiles(infile, curvingfile, outfile);  // function calling         
		 infile >> key; // answer key 

		 for (int i = 0; i < num_student; i++) // loop over each student
		 {
			 infile >> id;

			 infile >> answer;

			 count = 0;

			 length = key.size();

			 Size (outfile, length, answer);

			 for(int j = 0; j < length; j++) // loop over each question
			 {
				 if (key[j] == answer[j])

					 count++;
			 }

			 score = (float) count / length;
			 score2 = (int)(score * 100);

			 outfile<< id <<"   "<< score2 <<" % " ;

			 if (score2 >= 90)//<-----w[0]
				 outfile << "A" << endl;

			  else if (score2 >= 80)//<-----w[1] 
				  outfile << "B" << endl;

			 else if (score2 >= 70)//<-----w[2]
				 outfile <<"C"<<endl;

			 else if (score2 >= 60)//<-----w[3] 
				 outfile << "D" << endl;

			 else if (score2 >= 50)//<-----w[4] 
				 outfile << "E" << endl;

			 else if (score2 < 50)//<-----w[5]
				 outfile << "F" << endl;
		 }
		cout << " New Trial? (y/n):";
		cin >> x;
	 }	
	 while (x == 'y' || x == 'Y');
	 
	 return 0;
}

int openfiles(ifstream& infile, ifstream& curvingfile, ofstream& outfile)
{
	string name1, name2, name3, answerstring, curvedata; 

	cin >> name1; name2; name3;
	
	cout << "Input the name for the exam file: ";
	cin >> name1;

	infile.open(name1.c_str());
	infile >> answerstring;

	cout << "Input the name for the curving file: ";
	cin >> name2;

	infile.open(name2.c_str());
	infile >> curvedata;

	cout << "Input the name for the output: ";
	cin >> name3;

	outfile.open(name3.c_str());
	return true;
}

void Size(ofstream& outfile, int length, string answer)
{
	bool check;

	if (answer.size() > length)
	{
		outfile << "Unnecessary extra answers";
	}

	else if (answer.size() < length)
	{
		outfile << "The remaining answers are incorrect";
	}

	else 
	{check = false;};
}
Can someone possibly help?
openfiles() returns true which is !=3 so you are always going to exit with the opening files error message.
@vin So are you saying that I:
1. Need to change the condition

or

2. Change the return value
Yes.


E.g. if you choose 2.

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
int openfiles(ifstream& infile, ifstream& curvingfile, ofstream& outfile)
{
	string name1, name2, name3; //, answerstring, curvedata; 
        int num_files_open = 0;

	//cin >> name1; name2; name3; /// no need
	
	cout << "Input the name for the exam file: ";
	cin >> name1;
	infile.open(name1.c_str());
	//infile >> answerstring; don't do this here if you do it in main()
        if(infile){++num_files_open;}        

	cout << "Input the name for the curving file: ";
	cin >> name2;
	curvingfile.open(name2.c_str());
	//infile >> curvedata; /// this value not returned to main ????
        if(curvingfile){++num_files_open;}
        
	cout << "Input the name for the output: ";
	cin >> name3;
	outfile.open(name3.c_str());
        if(outfile){++num_files_open;}

	return num_files_open;
}
Last edited on
@vin
Thank you now that the error is fixed how do I get the stuff to output the files.
I have a less complicated code. The code above was to much from what my class mate said so now I have this code:
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#include "stdafx.h"
#include <fstream>
#include <ostream>
#include <iostream>
#include "string" 
#include <assert.h>

using namespace std;  
   


int main()  
{  

	int openfiles(ifstream& infile, ofstream& outfile);  
	int num_student = 4, count, length, score2;  

	ifstream infile, curvingfile; 
	char x;  
	ofstream outfile;
	float score;  

	string name1,name2,name3,key,answer,id;  

		do
		{  

			cout << "Input the name for the exam file: ";  

			cin >> name1;  

			infile.open(name1.c_str());    

			cout << "Input the name for the curving file: ";    

			cin >> name2;  

			curvingfile.open(name2.c_str());    

			cout << "Input the name for the output: ";     

			cin >> name3;  
   
			outfile.open(name3.c_str());
		    infile >> key; // answer key  

			for (int i = 0; i < num_student; i++) // loop over each student  
   
				{  

					infile >> id;  

					infile >> answer; 

					count = 0;  

					length = key.size(); // length represents number of questions in exam from exam1.dat  
										// size is a function....  

					for (int y = 0; y < length; y++) // loop over each question  

					 {  

						if (key[y] == answer[y])  
						count++;  

					}  


             score = (float) count / length;   
             score2 = (int)(score * 100);  
    
             outfile << id << "     " << score2 << "%";  

             if (score2 >= 90)  

    
                outfile << "A" << endl;  

            else if (score2 >= 80)  
 

             outfile << "B" << endl;  

  
         else if (score2 >= 70)  

                 outfile << "C" << endl;  
   

          else if (score2 >= 60)  

  
               outfile << "D" << endl;  

      }  

     cout << "Would you like to attempt a new trial? (y/n): ";  
     cin >> x;  
     } while (x == 'y' || x == 'Y');  

     return 0;  

 }//end of main()   


But I keep getting this output to the file score1.dat:

     -2147483648%     -2147483648%     -2147483648%     -2147483648%

What is wrong? Any help would be appreciated.
Hi I am learning C++ while doing a diploma in game development and thought I might prototype stats for game balancing and such just as a console app and maybe upgrade it as my knowledge of C++ grows.

One thing I have learned (think I have learned) is a bit of fstream. First of all I had to save the value of my variables (like int health, fireResist for example)
so when my program closes and reopens, if the text file for my const FILENAME was already created, I could load the existing values.

Now down to the important bit. I had so much trouble with fstream, and what I suggest is you read up on serialization. It isn't hard and could possible help you for future needs quite alot. Quite basically you can save all the variables of a class.

for example: I have a class in my program, with the public variables called health, fireresist, icedamage, etc...

all I do is open fstream:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void Character::saveStats(Character *object)
{
	cout << "Opening file" << endl;
	ofstream ofs;
	ofs.open(FILENAME, ios::binary);

	if (ofs.is_open())
	{
		ofs.write( (char*)&*object, sizeof(*object));
		cout << "Wrote to file" << endl;
	}
	else
	{
		cout << "Failed to open document";
		exit(1);
	}
	ofs.close();
}


This may not be the best method, and would LOVE some feedback myself.
I just hope this may help you a bit OP.
I'm currently trying to get my computer science degree. This is my first c++ class with my school and its more difficult then what I thought.
Yes I know that using a class is the best option and good programming but for this project he(professor) only wanted us to use what we had learned up to that point and time. Our 2nd and last project features class and structs. What I have above is the base code for the program but you had to tweak it a little. But for me its not outputting to the file right.
Write the required text in binary, and open the dat in binary mode, unless you have to actually read it from the dat file itself, then I would be interested to see how that is supposed to happen. I spent 2 days trying to write two variables to a text document, and it isn't what you would think, so best way was with binary format which worked great. I am sure you can save binary to a file without having to save a Class;
The program works fine for me, but the problem is the extensions. When you type the file names at the beginning I bet you are entering exam1 and that is it. You must include the extension "exam1.dat" in all cases or take care of that problem with the program. Really the name should be checked for an extension before continuing. If the names are typed correctly I get the correct output you are looking for, but if they are incorrect a file is created with no extension containing the numbers you specified.
Okay that's weird because I thought the same thing that maybe I wasn't typing in the files name right. I will have to check that and see if that works.
Topic archived. No new replies allowed.