Getting my student grades program working.

My book walked me through creating this StudentGrades program and there is a lot of detail into what the functions are doing and how they work which is great but I think the overlooked something... the program doesn't work lol! Well I mean, it should work but here take a look at the full program thus far (partially commented, I haven't finished yet):

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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#include <algorithm>
#include <iomanip>
#include <iostream>
#include <ios>
#include <string>
#include <vector>
#include <stdexcept>

using namespace std;

/*
 * Student_info is a type which has four data members: name, midterm, final and homework.
 * because Student_info is a type we can define objects of that this type each of which
 * will contain an instance of these four data members, ie: vector<Student_info> students;
 * can be created s/t one can call its data members, ie: students.grade, students.midterm,
 * students.name, etc...
 */
struct Student_info
{
	string name;
	double midterm, final;
	vector<double> homework;
};

/*
 * The compare function delegates the work of comparing Student_info/s to the string class,
 * which provides a < operator for comparing strings. That operator compares strings by
 * applying normal dictionary ordering. That is, it considers the left-hand operand to be
 * less than the right-hand operand if it is alphabetically ahead of the right-hand operand.
 */
bool compare(const Student_info& x, const Student_info& y)
{
	return x.name < y.name;
}

/*
 * The median function begins by diving size by 2 in order to locate the middle of the vector.
 * If the number of elements is even, this division is exact. If the number is odd, then the
 * result is the next lower integer. If it is even, the median is the average of the two
 * elements closest to the middle. Otherwise, there is an element in the middle, the value
 * of which is the median.
 */
double median(vector<double> vec)
{
	typedef vector<double>::size_type vec_sz;

	vec_sz size = vec.size();
	if(size == 0)
	{
		throw domain_error("median of an empty vector");
	}

	sort(vec.begin(), vec.end());

	vec_sz mid = size/2;

	return size % 2 == 0 ? (vec[mid] + vec[mid-1]) / 2 : vec[mid];
}

// Compute a students overall grade given a midterm, final exam and homework grade.
double grade(double midterm, double final, double homework)
{
	return 0.2 * midterm + 0.4 * final + 0.4 * homework;
}

/*
 * Compute a student's overall grade from midterm and final exam grades and a vector
 * of homework grades. This function does not copy its argument because median()
 * already does that for us.
 */
double grade(double midterm, double final, const vector<double>& hw)
{
	if(hw.size() == 0)
	{
		throw domain_error("student has done no homework");
	}

	return grade(midterm, final, median(hw));
}

// Determine a students overall grade given a midterm, final exam and homework grade.
double grade(const Student_info& s)
{
	return grade(s.midterm, s.final, s.homework);
}


istream& read_hw(istream& in, vector<double>& hw)
{
	if(in)
	{
		hw.clear();

		double x;
		while(in >> x)
		{
			hw.push_back(x);
		}

		in.clear();
	}

	return in;
}

istream& read(istream& is, Student_info& s)
{

	is >> s.name >> s.midterm >> s.final;

	read_hw(is, s.homework);
	return is;
}

int main()
{
	vector<Student_info> students;
	Student_info record;
	string::size_type maxlen = 0;

	while(read(cin, record))
	{
		maxlen = max(maxlen, record.name.size());
		students.push_back(record);
	}

	sort(students.begin(), students.end(), compare);

	for(vector<Student_info>::size_type i = 0; i != students.size(); ++i)
	{

		cout << students[i].name << string(maxlen + 1 - students[i].name.size(), ' ');

		try
		{

			double final_grade = grade(students[i]);
			streamsize prec = cout.precision();
			cout << setprecision(3) << final_grade << setprecision(prec);
		} catch (domain_error &e)
		{
			cout << e.what();
		}

		cout << endl;
	}

	return 0;
}


So at this point the while loop in reading by using cin but I feel like perhaps that is not the correct way to do things if you in fact want to read from a file? Perhaps I am wrong, perhaps you can read from an input file using cin?
Last edited on
perhaps you can read from an input file using cin?

The cin represents standard input, but where does the standard input come from?
User of the program could redirect file(s) into standard input:
https://ss64.com/nt/syntax-redirection.html
https://www.gnu.org/software/bash/manual/html_node/Redirections.html
If you're on Linux, there's Linux redirection.

Either way, you can use #include <fstream> to use ifstream and ofstream. ifstream is to take input from a file (like a .txt file) and ofstream is to write to a file.

Here's how to use ifstream:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include <string>
#include <fstream>

int main()
{
	std::ifstream inFile; //Declare ifstream as a Variable
	inFile.open("input.txt"); //Put File Name If In Same Folder OR The File Directory "C:\\users\\zapshe\\...."

	std::string info;

	inFile >> info; //Read A Word From The File Into The String.

	std::getline(inFile, info); //Read A Whole Line From The File Into The String
}


You should also have some error handling in case the file doesn't exist, couldn't be found, or couldn't be opened:

1
2
3
4
5
if (!inFile.is_open())
{
	std::cout << "COULDNT OPEN FILE!";
	return 0; //Exit Program
}
Last edited on
Redirection works with windows too. It's much better to read from cin. That way the input can come from a file (any file), or the user, or the output of another program.
Okay I think I understand how to use the redirection. I am assuming that would limit the program to being run from a terminal? Also would I need my program to be an executable like .exe or something? So assuming I figured out how to make my program executable then, as is, I could feed the program some text file by opening a command prompt and typing:

(windows)
myProgram.exe < text.txt

not sure on Linux. There is no standard executable file extension for Linux right? I am actually a bit confused on this matter. I am on Linux but I created my program through Eclipse so I just hit run to run it. I believe I have it setup to compile with g++ and from what I read online it would seem that when compiling with g++ a .out file should be created. However, when I navigate to the project directory I can't find any such file. So I guess what I am wondering is, when I press run in Eclipse, what exactly is happening behind the scenes?

Or, more specifically, how can I make my program an exicutable such that I could run a command like:

./myProgram < text.txt

on a Linux system? As of now I can't actually test my code :(
Last edited on
Okay I figured it out. The executable is created for me and lives in the Debug folder in my main project.
Topic archived. No new replies allowed.