GIDForums

Go Back   GIDForums > Computer Programming Forums > CPP / C++ Forum
User Name
Password
Register FAQ Members List Calendar Search Today's Posts Mark Forums Read


 
 
Thread Tools Search this Thread Rate Thread
  #1  
Old 25-Sep-2007, 12:02
earachefl earachefl is offline
Member
 
Join Date: Feb 2006
Posts: 178
earachefl is on a distinguished road

Input stream question


I'm trying to understand a series of programs in Accellerated C++ which build a grading program in steps. The authors began, in Chapter 3, with a program that includes all the user input and output in main, using a vector<double> to hold homework grades. In chapter 4, the author separates functions out into separate source files, and arranges student records in structs. In chapter 5, he introduces iterators and lists.

The problems I'm having are in the revised function to read homework. First, the author removed any kind of prompt in the revision, so that when the program compiles, there's no indication of what to do.... just a cursor. That I fixed. The remaining problem is what to do when one wants to indicate that one is through entering homework.

main calls function read:

CPP / C++ / C Code:
 while (read(cin, s)) {
                maxlen = max(maxlen, s.name.size());
                vs.push_back(s);
        }

And function read is included in the Student_info source file:

CPP / C++ / C Code:
istream& read(istream& is, Student_info& s)
{
	// read and store the student's name and midterm and final exam grades
     //prompt added
    cout << "Please enter name, midterm and final grades:";
	is >> s.name >> s.midterm >> s.final;

	read_hw(is, s.homework);  // read and store all the student's homework grades
	return is;
}

// read homework grades from an input stream into a `vector<double>'
istream& read_hw(istream& in, vector<double>& hw)
{
	if (in) {
		// get rid of previous contents
		hw.clear();

		// read homework grades
           // prompt added: in the original version, prompted to enter
           // end-of-file to signal no more homework to add
        cout << "Enter all your homework grades:";
		double x;
		while (in >> x)
			hw.push_back(x);

		// clear the stream so that input will work for the next student
		in.clear();
	}
	return in;
}


The problem, in a nutshell, is that there's no way to gracefully exit the read_hw function in the current version. On my mac, using XCode 2.4.1, entering end-of-file (CTL-D) does nothing. I've also tried entering CTL-Q followed by CTL-D. The only way out of the loop is to enter a non-numeric value which gives an error message:
Quote:
Enter all your homework grades, followed by end-of-file:12
qwe
Please enter name, midterm and final grades:
qwe
ZeroLink: unknown symbol '__Z13extract_failsRSt6vectorI12Student_infoSaIS0_ EE'

I've tried altering the read_hw function to use a flag '-1' to signal end of homework, but that doesn't get me out of the main loop:
Quote:
Enter all your homework grades, followed by -1:-1
Please enter name, midterm and final grades:

I'm at a loss as to first, signal the end of entering homework, and second, signal the last student entered. Any help would be greatly appreciated. I've not yet been able to get the code to compile on Dev-C++ on my PC. Here are the complete source files if anyone is interested:

main.cc

CPP / C++ / C Code:
#include <algorithm>
#include <vector>
#include <iostream>
#include <string>

#include "Student_info.h"
#include "grade.h"

//driver program for grade partitioning examples

using std::cin;
using std::cout;
using std::endl;
using std::sort;
using std::string;
using std::vector;

#ifdef _MSC_VER
#include "../minmax.h"
#else
using std::max;
#endif

vector<Student_info> extract_fails(vector<Student_info>& v);

int main()
{
        vector<Student_info> vs;
        Student_info s;
        string::size_type maxlen = 0;
        while (read(cin, s)) {
                maxlen = max(maxlen, s.name.size());
                vs.push_back(s);
        }

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

	vector<Student_info> fails = extract_fails(vs);

	for (int i = 0; i < fails.size(); ++i)
		cout << fails[i].name << " " << grade(fails[i]) << endl;

	return 0;
}

Student_info.h:

CPP / C++ / C Code:
#ifndef GUARD_Student_info
#define GUARD_Student_info

// `Student_info.h' header file
#include <iostream>
#include <string>
#include <vector>

struct Student_info {
	std::string name;
	double midterm, final;
	std::vector<double> homework;
};

bool compare(const Student_info&, const Student_info&);
std::istream& read(std::istream&, Student_info&);
std::istream& read_hw(std::istream&, std::vector<double>&);
#endif


Student_info.cc:
CPP / C++ / C Code:
// source file for `Student_info'-related functions
#include "Student_info.h"
#include <iostream>
using std::cout;

using std::istream;  using std::vector;

bool compare(const Student_info& x, const Student_info& y)
{
	return x.name < y.name;
}

istream& read(istream& is, Student_info& s)
{
	// read and store the student's name and midterm and final exam grades
    cout << "Please enter name, midterm and final grades:";
	is >> s.name >> s.midterm >> s.final;

	read_hw(is, s.homework);  // read and store all the student's homework grades
	return is;
}

// read homework grades from an input stream into a `vector<double>'
istream& read_hw(istream& in, vector<double>& hw)
{
	if (in) {
		// get rid of previous contents
		hw.clear();

		// read homework grades
        cout << "Enter all your homework grades:";
		double x;
		while (in >> x)
			hw.push_back(x);

		// clear the stream so that input will work for the next student
		in.clear();
	}
	return in;
}
grade.h:
CPP / C++ / C Code:
#ifndef GUARD_grade_h
#define GUARD_grade_h

#include <vector>
#include "Student_info.h"

double grade(double, double, double);
double grade(double, double, const std::vector<double>&);
double grade(const Student_info&);

bool fgrade(const Student_info&);

#endif
grade.cc:
CPP / C++ / C Code:
#include <stdexcept>
#include <vector>
#include "grade.h"
#include "median.h"
#include "Student_info.h"

using std::domain_error;  using std::vector;


// compute a student's overall grade from midterm and final exam grades 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 vector of homework grades.
// this function does not copy its argument, because `median' does so 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));
}

double grade(const Student_info& s)
{
	return grade(s.midterm, s.final, s.homework);
}

// predicate to determine whether a student failed
bool fgrade(const Student_info& s)
{
	return grade(s) < 60;
}

median.h:
CPP / C++ / C Code:
#ifndef GUARD_median_h
#define GUARD_median_h

// `median.h'--final version
#include <vector>
double median(std::vector<double>);

#endif

and median.cc:
CPP / C++ / C Code:
// source file for the `median' function
#include <algorithm>    // to get the declaration of `sort'
#include <stdexcept>    // to get the declaration of `domain_error'
#include <vector>       // to get the declaration of `vector'

using std::domain_error;   using std::sort;   using std::vector;

#include "median.h"

// compute the median of a `vector<double>'
// note that calling this function copies the entire argument `vector'
double median(vector<double> vec)
{
#ifdef _MSC_VER
	typedef std::vector<double>::size_type vec_sz;
#else
	typedef vector<double>::size_type vec_sz;
#endif

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

Last edited by LuciWiz : 25-Sep-2007 at 12:12. Reason: Please insert your C/C++ code between [cpp] & [/cpp] tags
  #2  
Old 25-Sep-2007, 14:39
davekw7x davekw7x is offline
Outstanding Member
 
Join Date: Feb 2004
Location: Left Coast, USA
Posts: 4,520
davekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to behold

Re: Input stream question


Quote:
Originally Posted by earachefl
I'm trying to understand a series of programs in

Code:
ZeroLink: unknown symbol '__Z13extract_failsRSt6vectorI12Student_infoSaIS0_ EE'
Your code won't compile because you don't have the implementation of the function extract_fails() anywhere in the files that you posted. Or am I missing something? (It wouldn't be the first time.)

Anyhow...

Quote:
Originally Posted by earachefl
I've tried altering the read_hw function to use a flag '-1' to signal end of homework, but that doesn't get me out of the main loop:
Then change your functions so that the calling function can tell by some return value that the user indicated end of input somehow or other.

For example:

CPP / C++ / C Code:
istream& read_hw(istream& in, vector<double>& hw)
{
    if (in) {

        hw.clear();

        cout << "Enter all your homework grades:";
        double x;
        while (in >> x)
            hw.push_back(x);

        in.clear(); // <--- this clears error flags, including end-of-file
    }
    return in;
}

Note my comment: the in.clear() resets any error flags, so that the results of an invalid input (or end-of-file or other stream error) is not fed back to the calling program. Therefore, no matter what happens with the in stream in this function, it always returns whatever state the stream had when the function was called.

Regards,

Dave
  #3  
Old 26-Sep-2007, 08:05
earachefl earachefl is offline
Member
 
Join Date: Feb 2006
Posts: 178
earachefl is on a distinguished road

Re: Input stream question


Thanks, Dave.

I assume that the best solution would be to set an end-of-file flag on the input stream if there is no more homework to be read. Unfortunately, I'm still totally at a loss as how to make this happen on my Mac, using Xcode 2.4.1, with this code. I've tried entering CTRL-D, CTRL-Q followed by CTRL-D, and even CTRL-Z for the hell of it.... nothing makes it stop reading.

If I say to hell with it and decide to ask the user to enter some nonsense value, like -1, to signal the end of entering homework, would this be a reasonable way to do it?
CPP / C++ / C Code:
istream& read_hw(istream& in, vector<double>& hw)
{
    if (in) {

        hw.clear();

        cout << "Enter all your homework grades, followed by -1 when finished:";
        double x;
        while (in >> x && x != -1) //add condition to check for end flag
            hw.push_back(x);

        if(x == -1) 
                in.eof(); //set end-of-file flag on the input stream 
        else
                in.clear(); // <--- this clears error flags, including end-of-file
    }
    return in;
}
Note that I know this is not in any way robust error handling.... just trying to get a handle on how to get this going.
Last edited by admin : 26-Sep-2007 at 09:26. Reason: Please insert your C code between [cpp] & [/cpp] tags
  #4  
Old 26-Sep-2007, 09:05
davekw7x davekw7x is offline
Outstanding Member
 
Join Date: Feb 2004
Location: Left Coast, USA
Posts: 4,520
davekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to behold

Re: Input stream question


Quote:
Originally Posted by earachefl
...enter some nonsense value, like -1, to signal the end of...
CPP / C++ / C Code:
 
        while (in >> x && x != -1) //add condition to check for end flag
            hw.push_back(x);
OK so far. This gets you out of the loop so that no more homework scores will be accepted for the current student.

However...
Quote:
Originally Posted by earachefl
CPP / C++ / C Code:

        if(x == -1) 
                in.eof(); //set end-of-file flag on the input stream  <---(No, it doesn't.)
        else
                in.clear(); // <--- this clears error flags, including end-of-file
    }
    return in;
}

The statement in.eof(); does not set the eof flag on the input stream. And what if it did? How would that help anything back up the chain of calling functions?

In other words, the issue now is in the loop in your main() program that calls the read() function. How will you let that piece of program know that there are no more students to be processed?

Regards,

Dave
  #5  
Old 26-Sep-2007, 09:16
earachefl earachefl is offline
Member
 
Join Date: Feb 2006
Posts: 178
earachefl is on a distinguished road

Re: Input stream question


Oh, I see, in.eof() just returns a bool indicating whether the stream has hit end-of-file... so is there no istream member function that lets you actually force the eof flag to be set? I looked at http://www.cppreference.com/io_flags.html#manipulators and didn't see any there.

And yes, I understand that the calling function is going to have to deal with the return from the read function.... but I'm trying to deal with the most pressing problem for me right now, which is, again, how the hell do I cause the eof flag to be set?
  #6  
Old 26-Sep-2007, 09:35
davekw7x davekw7x is offline
Outstanding Member
 
Join Date: Feb 2004
Location: Left Coast, USA
Posts: 4,520
davekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to behold

Re: Input stream question


Quote:
Originally Posted by earachefl
Ohow the hell do I cause the eof flag to be set.
There is no "eof flag" that can be manipulated by your program. We sometimes talk about the "eof flag" being set by certain actions on an input stream object, but there is no "eof flag" that can be directly set or reset by program instructions. Period.


I hate to repeat myself, but what if you could set it when leaving your lowest-level read function? It would be set for each and every student for which you had called the function (since each time you call the read_hw() function, it reads homework values until you tell it to quit). How would setting the eof flag every time let any upstream calling function know which one was the last student that you intended to process?

Regards,

Dave
  #7  
Old 26-Sep-2007, 09:46
Kimmo Kimmo is offline
Member
 
Join Date: Mar 2007
Location: Finland
Posts: 229
Kimmo has a spectacular aura aboutKimmo has a spectacular aura about

Re: Input stream question


Quote:
Originally Posted by davekw7x
There is no "eof flag" that can be manipulated by your program. We sometimes talk about the "eof flag" being set by certain actions on an input stream object, but there is no "eof flag" that can be directly set or reset by program instructions. Period.
Maybe it's the language barrier, but what are clear() or setstate() used for if not this?
__________________
Music, programming, endless learning..
  #8  
Old 26-Sep-2007, 09:47
earachefl earachefl is offline
Member
 
Join Date: Feb 2006
Posts: 178
earachefl is on a distinguished road

Re: Input stream question


OK, got it - so eof should only be true if the istream actually reads end-of-file, either from a file or from input (which I still don't know how to make happen.... sigh). That would definitively signal that there is no more homework to be read.

So I should modify the read_hw() and read() functions to also return a bool that indicates whether the current student is finished inputting grades, and also modify either the read() function or the calling function to ask whether there are more students to be read.
  #9  
Old 26-Sep-2007, 10:01
davekw7x davekw7x is offline
Outstanding Member
 
Join Date: Feb 2004
Location: Left Coast, USA
Posts: 4,520
davekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to behold

Re: Input stream question


Quote:
Originally Posted by Kimmo
Maybe it's the language barrier...
No, it is a little barrier in my brain. The one that separates fact from fantasy.

You are, of course, correct. A user can set the "eof flag" on an istream object by
CPP / C++ / C Code:
     in.setstate(ios::eofbit); //set end-of-file flag on the input stream 


Thanks for the tweak.

Regards,

Dave
  #10  
Old 26-Sep-2007, 10:17
earachefl earachefl is offline
Member
 
Join Date: Feb 2006
Posts: 178
earachefl is on a distinguished road

Re: Input stream question


OK, so if I can set the eofbit to true, all I should then need to do in my read() function is something like:
CPP / C++ / C Code:
istream& read(istream& is, Student_info& s)
{
	// read and store the student's name and midterm and final exam grades
    cout << "Please enter name, midterm and final grades:";
	is >> s.name >> s.midterm >> s.final;

	read_hw(is, s.homework);  // read and store all the student's homework grades

      if (is.eof()) //check if read_hw has returned istream is with eof true
      {
            cout << "Enter another student? Enter Y or N";
            char more;
            cin >> more;
            if (more == 'y' || more == 'Y')
                   is.clear(); //clear the eof flag so calling function will continue loop
      } // if eof is true, and the istream has not been cleared 
        // the calling function will see that eof has been reached and break out of loop
	return is;
}
This would work, yes?
Last edited by earachefl : 26-Sep-2007 at 10:30. Reason: wrapping code with [CPP]
 

Recent GIDBlogMaster?s Degree by crystalattice

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
basic input question prince87x C Programming Language 10 01-Oct-2006 16:21
scanf / clearing input stream zone4 C Programming Language 8 08-May-2004 14:42
IP tables rogermark100 C Programming Language 6 18-Apr-2004 07:22
a C input question.. tmike C Programming Language 2 19-Sep-2003 02:39
a C input question tmike C Programming Language 1 16-Sep-2003 02:31

Network Sites: GIDNetwork · GIDWebHosts · GIDSearch · Learning Journal by J de Silva, The

All times are GMT -6. The time now is 18:59.


vBulletin, Copyright © 2000 - 2008, Jelsoft Enterprises Ltd.