I'm working through Accelerated C++ chapter 4, trying to get the programs in the chapter working. In the following, the user enters their name and a grade, and then a list of grades. Strangely, with multpile entries, instead of the name, I get the name with a rightward-facing arrow as the first character, followed by their name, instead of the first letter of their name.
//so far this does the weird arrow thing, and it did it only after I added the read_hw function....
//Seems simple: when you do cntrl-z on same line as data, you get fubar
//when you hit enter, and then cntrl-z, then it is all good
#include <string>
#include <iostream>
#include <vector>
#include <ios> //std::istream
//standard library names
using std::cin; using std::cout;
using std::endl; using std::istream;
using std::string; using std::vector;
////////////
//Structures
struct Student_info
{
string name;
int midterm;
vector<double> homework;
}; //semicolon required!
///////////
//Functions
//Read in homework grades
istream& read_hw(istream& in, vector<double>& hw)
{
if(in) //if they didn't enter EOF
{
//Get rid of previous data
hw.clear();
//read homework grades
double x;
while (in>>x)
hw.push_back(x);
//clear stream so input will work for next student
in.clear();
}
return in;
}// read_hw function
//read and store student's name and test grade
istream& read(istream& is, Student_info& s)
{
cout << "\nPlease enter name and midterm grade, or EOF if done:"<< endl;
is >> s.name >> s.midterm;
if(is)
{
cout <<"Please enter set of homework grades, followed by EOF: "<<endl;
}
read_hw(is, s.homework);
return is; //
} //read
//////End function definitions
////////////////////////////////////
///// MAIN ////
////////////////////////////////////
int main()
{
vector<Student_info> students;
Student_info record;
//Read and store all records
while (read(cin, record))
{
students.push_back(record);
}
//Print out all names
cout << "\n\nStudent names: \n";
for (vector<Student_info>::size_type i=0; i != students.size(); ++i)
{
//write the name
cout << students[i].name << "\t";
} //for
//Wait for user input
cout << "\n\n";
cin.get();
return 0;
} //main
Thanks Duoas for the help! My response is a comment and question...
One thing I just noticed is that when I do ctrl-z before hitting return, I get the bad behavior, but when I hit return and then ctrl-z, the behavior is just fine. This is discussed here:
To quote one comment there, "[ctrl-z] is only translated by the console to an EOF signal to the program when it is typed at the start of aline. That's just the way that the windows console works. There is no "workaround" to this behaviour that I know of." So basically, instead of ctrl-z, then return, I have to instruct users to enter 'return, ctrl-z, return.' Seems ugly, but it works.
Duoas suggests that programs not tell the user to enter cntrl-z (or whatever EOF is on your platform). But shouldn't it work just fine, as long as you are careful? E.g., with the appropriate modifications to the above program? Not saying that is optimal, especially for real-life end users, but at least possible?
Duoas so you are saying it is possible to do it the way I did, but it violates the conventional use of EOF to say 'No more input in this program, period.' Is that it?
Though on second thought, isn't EOF really meant to simply signify the end of input from a particular stream (e.g., a file). But you can read multiple files into a single program, which will involve multiple EOF messages in the same program. This simply seems to be an instance of such a case, but with each EOF indicating that you have stopped pulling input from the present user's istream.
Yes, but you are mixing things by thinking of it that way.
EOF signals end of stream. If you are piping something in to stdin, EOF means no more input on stdin.
If you try to do it as you suggest, when does stdin actually close? How is your program to distinguish from one input file and five?
EOF means EOF, not FS (file separator).
(Typically, piping multiple files into stdin concatenates those files into a single stream, though other mechanisms exist to indicate where files change. The CPP, for example, embeds messages in the input stream to track things like filename and line number so that the compiler can produce useful error messages.)