files and arrays, help

I'm lost about how I'm suppose to do certain things in this task, which i have made bold:

A file contains the following as the first line.

15 11 68 85 43 21.1 61.8 5 9 10 7 45 23 2 2 6 1 56 45.3 20

which corresponds to the answers in an arithmetic test.

Each of the next lines (less than 150 of them, but we are not sure of the exact amount) give a student’s ID and student’s response, such as:

908-77-4532 14 11 67 85 43 21.1 61.8 5 9 10 7 45 23 2 2 6 1 56 45.3 20

We wish to write a program that will read in each of the student’s responses and print the student ID and grade to an output file. Since there are twenty question on the test, each one is worth 5 points out of 100.

Declare an array, answer, that holds twenty variables (what type?) for the answer key.
Declare an input file and output file and open them.
Create a function, readarr, that reads the first line of the input file into the array answer. This function takes the array answer, and the ifstream variable as parameters.
4. In the main function, have a while loop that loops while there are still students in the file.
Each time through the loop the student ID is read, and then a function getgrad is called. This function takes the ifstream variable, the array answer, and a float reference variable as parameters. The function reads the student’s answers from the file, compares them to the correct answers and places the final grade into the float reference variable.
5. The main function prints the ID and grade to an output file.


this is what I got so far
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
  #include<iostream>
#include<fstream>

using namespace std;

void readarr(ifstream &in, double answer[]);
void getgrad(ifstream &in, double answer[], float &reference);

int main()
{
	double answer [20];
	float reference;

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

	if (!inFile)
		cout << "error";
	return 1;

	while (!EOF)
	{
		//um...
		//read only the student ID
		//call getgrad
		//print id and final grad to output


		ofstream outFile;
		outFile.open("sorted.txt");

		if (!outFile)
			cout << "error";
		return 1;

		cout << endl; //<<student grade << float

		outFile.close();
	}

	inFile.close();
	return 0;
}

void readarr(ifstream &in, double answer[])
{

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


}

void getgrad(ifstream &in, double answer[], float &reference)
{
	double studentans[20];
	int i;
	for (i = 0; i<20; i++)
	{
		in >> studentans[i];
	}

	//reads the student answers
	//compares studentans to the correct answer
	//computes final grade and puts it into float ref
}
In your loop you need a string variable to temporarily hold the student id. Then you read in the id, the same way you read in everything else. After you call getgrad, your reference variable is updated, so you print the id and the score, and then you write the same line to your output file.

Your getgrad function should compare each element of studentans to the corresponding element in answer, and keeping a running total of points for the correct answers, Then you store that total in your reference variable,

You should probably open your output file outside your while loop.
Can't seem to get it to work, no error shows up.

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
#include<iostream>
#include<fstream>
#include<string>

using namespace std;

void readarr(ifstream &in, double answer[]);
void getgrad(ifstream &in, double answer[], float &reference);

int main()
{
	double answer [20];
	float reference;
	string temp;

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

	if (!inFile)
		cout << "error";
	return 1;

	ofstream outFile;
		outFile.open("sorted.txt");

		if (!outFile)
			cout << "error";
		return 1;
		
	while (!EOF)
	{
		//um...
		//read only the student ID
		//call getgrad
		//print id and final grad to output
		inFile >> temp;
		getgrad(inFile, answer, reference);

		cout << temp << " " << reference << endl;
		outFile << temp << " " << reference << endl;
	}

	inFile.close();
	outFile.close();
	return 0;
}

void readarr(ifstream &in, double answer[])
{

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


}

void getgrad(ifstream &in, double answer[], float &reference)
{
	double studentans[20];
	int i;
	float correct = 0;
	for (i = 0; i<20; i++)
	{
		in >> studentans[i];
	}

	for (i = 0; i < 20; i++)
	{
		if (answer[i] == studentans[i])
		{
			correct++;
		}
	}

	reference = correct * 5;
	//reads the student answers
	//compares studentans to the correct answer
	//computes final grade and puts it into float ref
}
1
2
3
	if (!inFile)
		cout << "error";
	return 1;


You're returning regardless of the check on inFile here because you don't have brackets for your if block.
still not working despite adding brackets

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
#include<iostream>
#include<fstream>
#include<string>

using namespace std;

void readarr(ifstream &in, double answer[]);
void getgrad(ifstream &in, double answer[], float &reference);

int main()
{
	double answer [20];
	float reference;
	string temp;

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

	if (!inFile)
	{
		cout << "error";
		return 1;
	}

	ofstream outFile;
		outFile.open("sorted.txt");

		if (!outFile)
		{
			cout << "error";
			return 1;
		}
		
	while (!EOF)
	{
		//um...
		//read only the student ID
		//call getgrad
		//print id and final grad to output
		inFile >> temp;
		getgrad(inFile, answer, reference);

		cout << temp << " " << reference << endl;
		outFile << temp << " " << reference << endl;
	}

	inFile.close();
	outFile.close();
	return 0;
}

void readarr(ifstream &in, double answer[])
{

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


}

void getgrad(ifstream &in, double answer[], float &reference)
{
	double studentans[20];
	int i;
	float correct = 0;
	for (i = 0; i<20; i++)
	{
		in >> studentans[i];
	}

	for (i = 0; i < 20; i++)
	{
		if (answer[i] == studentans[i])
		{
			correct++;
		}
	}

	reference = correct * 5;
	//reads the student answers
	//compares studentans to the correct answer
	//computes final grade and puts it into float ref
}
Last edited on
The use of while (!EOF) is far from correct here. for one thing, EOF is a constant defined in <cstdio>, and does not really apply to the ifstream where the flags such as inFile.good() or inFile.fail() would be more relevant.

Also, checking the file status before reading from it is not really useful, since the important thing the program needs to know is the file status afterwards, which will indicate whether the data was read in successfully or not.

For example, the correct answers from the first line of the file could be read like this. Notice that the return type of the function is a bool which indicates whether or not the operation succeeded.
1
2
3
4
5
6
7
8
9
bool readarr(ifstream &in, double answer[])
{
    for (int i = 0; i<20; i++)
    {
        in >> answer[i];
    }

    return in;
}

That function could be called like this:
1
2
3
4
5
6
    bool ok = readarr(inFile, answer);
    if (!ok)
    {
        cout << "error reading answers" << endl;
        return 1;
    }


The separate variable ok isn't strictly necessary, but it may help to show the logic more clearly.

Similarly, you could use a while loop which checks the result of reading the data for each student, before deciding to go ahead and calculate and output the grade.

My suggestion is to separate the reading of the file from the grade calculation, like this:
1
2
3
4
5
6
7
8
    string id;
    double studentAns[20];
    while (readStudent(inFile, studentAns, id))
    {
        double reference = getgrade(answer, studentAns);
        cout    << id << " " << reference << endl;
        outFile << id << " " << reference << endl;
    }


Here, the function readStudent() reads the student id, then the 20 answers. It returns a bool in the same manner as function readarr()

If the file access was ok, the body of the loop is executed, the grade calculated in function getgrade() and the result output.
Last edited on
I'm retyping the code and I seem to get an error of some sort when comparing the elements in answer and studentAns.

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
#include<iostream>
#include<fstream>
#include<string>

using namespace std;

bool readarr(ifstream &in, double answer[])
{
	for (int i = 0; i<20; i++)
	{
		in >> answer[i];
	}
}

bool readStudent(ifstream &in, string id, double studentAns)
{
	in >> id;
	for (int i = 0; i < 20; i++)
	{
		in >> studentAns;
	}
}

void getgrade(double answersheet, double studentAns, float &reference)
{
	float correct = 0;

	for (int i = 0; i < 20; i++)
	{
		if (answersheet[i] == studentAns[i])
		{
			correct++;
		}
	}

	reference = correct * 5;
}
Remember that you are dealing with arrays for the scores here.
This function header makes sense, it has an array to hold the 20 values:
bool readarr(ifstream &in, double answer[])

The function readStudent() should pass an array too. It will also need to pass the id by reference, like this:
bool readStudent(ifstream &in, string &id, double studentAns[])
I see you've so far omitted to return a value from those two functions. That will alter the controlling logic needed in main()

Similarly, function getgrade() will need to pass two arrays:
void getgrade(double answersheet[], double studentAns[], float &reference)
errors i get are:
return in; (both of them)
and
in >> studentAns

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
#include<iostream>
#include<fstream>
#include<string>

using namespace std;

bool readarr(ifstream &in, double answer[])
{
	for (int i = 0; i<20; i++)
	{
		in >> answer[i];
	}
	return in;
}

bool readStudent(ifstream &in, string &id, double studentAns[])
{
	in >> id;
	for (int i = 0; i < 20; i++)
	{
		in >> studentAns;
	}
	return in;
}

void getgrade(double answersheet [], double studentAns[], float &reference)
{
	float correct = 0;

	for (int i = 0; i < 20; i++)
	{
		if (answersheet[i] == studentAns[i])
		{
			correct++;
		}
	}

	reference = correct * 5;
}
Last edited on
I seem to get an error of some sort

Could you please be more specific. If there is an error message it would be useful if you could paste it here, verbatim.


in >> studentAns
studentAns is an array, you need to specify the subscript of the particular element you wish to access.
Last edited on
oh yeah forgot the [], silly me.

the error is

no suitable conversion function from "std::ifstream" to "bool" exists
Thanks for that response. I tried the above code in two different compilers, and there were no errors or warnings. Perhaps your compiler behaves differently.

The return in; statement is indeed converting a type ifstream to a type bool. There might be something I'm missing here. Someone more expert than myself might have an explanation.

You might try return bool(in);.
If that doesn't work, perhaps
1
2
3
4
if (in) 
    return true;
else
    return false;

which should work according to the bool operator documented here:
http://www.cplusplus.com/reference/ios/basic_ios/operator_bool/
I use Microsoft visual studios.

return bool (in); worked!

Oh and bada bing bada boom:
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
#include<iostream>
#include<fstream>
#include<string>

using namespace std;

bool readarr(ifstream &in, double answersheet[])
{
	for (int i = 0; i<20; i++)
	{
		in >> answersheet[i];
	}
	return bool(in);
}

bool readStudent(ifstream &in, string &id, double studentAns[])
{
	in >> id;
	for (int i = 0; i < 20; i++)
	{
		in >> studentAns[i];
	}
	return bool(in);
}

void getgrade(double answersheet [], double studentAns[], float &reference)
{
	float correct = 0;

	for (int i = 0; i < 20; i++)
	{
		if (answersheet[i] == studentAns[i])
		{
			correct++;
		}
	}

	reference = correct * 5;
}

int main()
{
	double answersheet[20];
	double studentAns[20];
	string studentID;
	float reference;

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

	bool ok = readarr(inFile, answersheet);
	if (!ok)
	{
		cout << "error reading answers" << endl;
		return 1;
	}

	ofstream outFile;
	outFile.open("studentidscores.txt");

	while (readStudent(inFile, studentID, studentAns))
	{
		getgrade(answersheet, studentAns, reference);
		cout << studentID << " " << reference << endl;
		outFile << studentID << " " << reference << endl;
	}

	cout << endl;
}


Thank you, you are the best. I'll keep this unsolved for a bit, I would like to know why return in; did not work for me.
Topic archived. No new replies allowed.