want to "harden" a file reading utility:

Pages: 12
I have seen code that never return out the input stream reference leading to awkward usage problem cuz we like to nest them in statements when using.

e.g
cin >> a >> b >> c;

cout << a << b << c;

Although it is *not* wrong not to return the iostream out, it is highly recommended as most programmers expect to use those iostream operator in as intuitive as possible manner.
Yes, the standard does specifically permit you to return anything, but this is for doing fancy stuff with manipulators and the like. And does specifically permit you to return void, but as sohguanh succinctly demonstrated, that is (almost always) a mistake.

For normal purposes, just return the stream you are given.
Whoops, sorry... I was thinking of operator<<.
Duoas wrote:
Extraction operators don't take const references
Except when you are using a temporary wrapper that holds a mutable reference to an object, in order to modify the default behaviour of the istream with your object, xP.

I prefer something like
cat file | get_rid_of_comments -cpp | filter -not number | my_program

Now your program will only see numeric input.
Except when you are using a temporary wrapper that holds a mutable reference to an object, ...

For example, exactly as I explained in two large posts on the first page of this topic.
So, Duoas -

I'm trying to figure out how to modify this to work on an object instead of an int. (For added confusion, I'm trying to alter the array into a vector, which presented its own snags, recorded in another thread here.) The object contains three long ints, and when you assign a value to the object, it is stored in one of these longs.

Is it simply a matter of altering the >> operator, or is there more at play here?

Thanks.
The example I have already given you here is sufficient:
http://www.cplusplus.com/forum/general/51003/#msg277446

The myint object has a mutable reference to something (in my example, an int, but you can choose anything you desire).

Good luck!
Hi, Duoas –

I made the following changes:

- long to SocReg (the name of my object class)
- array to vector

Here's the 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
struct my_int
{
mutable	SocReg& n;
	my_int( SocReg& n ): n( n ) { }
};

// This is our special method to read ints -- skipping bad integers and C++ commentary
istream& operator >> ( istream& ins, const my_int& n )
{
	// only continue if all OK
	while (ins && !ins.eof())
	{

		// get an integer -- if OK then we're done
		if (ins >> n.n)
			break;

		// otherwise, get it as a string
		string s;
		ins.clear();
		ins >> s;

		// special handling for comments
		if (is_comment( s ))
			ins.ignore( numeric_limits <streamsize> ::max(), '\n' );
	}
	// return the stream
	return ins;
}
// end of routine taken from http://www.cplusplus.com/forum/general/51003/

long	readCoeffs(string file,
				   long nbrCells,
				   vector<SocReg>& a,
				   long startIndex)
{
	int		rc;
	ifstream    s(file.c_str());

	if (s)
	{
		for (int i=startIndex; i < nbrCells + startIndex; i++)
			s >> my_int (a.at(i));
		rc = 0;
	}
	else
	{
		cout << "Cannot open " << file << "." << endl;
		rc = 1;
	}
	s.close();
	return rc;
}


The program blows up on the line:

if (ins >> n.n)

I never did understand the "n.n" syntax, but now I guess I need to. Can you tell me from this information what I overlooked?

Thanks.
Er, now you aren't making sense. What is a SocReg? And why aren't you just overloading it as:

1
2
3
4
istream& operator >> ( istream& ins, SocReg& sr )
{
	...
}

?
SocReg is a class I've defined:

1
2
3
4
5
6
7
class SocReg
{
        long   resetValue;
        long	qCurrent;
        long	qNext;
public:
// etc. 


I was trying to model your example, but I guess I didn't understand it. So, is the correct syntax to identify the element in SocReg that should receive the input, as the second parameter in the overload?

EDIT:

I think I have little better understanding of this now. I've made the following change:

1
2
//			s >> my_int (a.at(i));
			s >> a.at(i);


And modified the parameters for the overload as follows:

1
2
//istream& operator >> ( istream& ins, const my_int& n )
istream& operator >> ( istream& ins, SocReg& n )


Now, the problem I'm having is how to actually assign the input value into the object. This produces a runtime error (invalid memory):

if (ins >> n)

And this doesn't compile, because the object member is of course private:

if (ins >> n.qNext)

I do have a set() function, but I don't know how to form the code to make this work with the >> operator.

Am I at least in the ballpark here?

EDIT #2:

I cheated and did this:

1
2
3
4
5
6
7
8
9
10
11
12
	long	tempLong;

// only continue if all OK

	while (ins && !ins.eof())
	{
		// get an integer -- if OK then we're done
		if (ins >> tempLong)
		{
			n = tempLong;
			break;
		}


It seems to work, but I'd be interested in knowing the "correct" way of doing this for future reference. Thanks for bearing with me.
Last edited on
The way the function works depends on how your input is defined. If a SocReg is, textually, a list like this:

7 2 4

Then your input function should read three integers (longs):

1
2
	SocReg sr;
	cin >> sr.resetValue >> sr.qCurrent >> sr.qNext;

In order to make it prettier, easier to use, and compatible with the STL, you'll want to overload the extraction operator:

1
2
3
4
5
istream& operator >> ( istream& ins, SocReg& sr )
{
	ins >> sr.resetValue >> sr.qCurrent >> sr.qNext;
	return ins;
}

Now you can use it as if it were an built-in type:

1
2
	SocReg sr;
	cin >> sr;

This makes life easy in loops and the like as well:

1
2
3
4
5
6
	SocReg cells[ 12 ];
	ifstream f( ... );
	for (int n = 0; n < 12; n++)
	{
		f >> cells[ n ];
	}

Keep in mind you can organize your input so that it looks however you want:

(7 2 4)
7, 2, 4
(socreg: 7, 2, 4)
etc.

Now, as per your first post, do you still want to be able to skip over non-SocReg information?
I apologize for leaving out a detail: the only member in SocReg that gets changed during an assignment, initialization or other "normal" input (like reading from a file) is the qNext. (This is modeling a data flip-flop, if that helps.)

With regard to your overload example in the prior post, the members of SocReg are private, so I get a compile error if I try to do:

ins >> sr.qNext

And yes, I do want to skip over any non-integer stuff in the file. I've saved all your code for doing that, though, and it should be OK as is (I think).

Thanks for bearing with me.
Topic archived. No new replies allowed.
Pages: 12