I'm trying to overload the >> operator to read a single (created with enum Symbol {e,a,b,c,d};
) Symbol:
istream & operator >> (istream & is, Symbol & sym) {
Symbol Arr[]={e,a,b,c,d};
char ch;
is>>ch;
if (strchr("eabcd",ch))
sym=Arr[ch-'e'];
else {
is.unget();
is.setstate(ios::failbit);
}
return is;
}
But this reads some trash (numbers) instead of what I was looking for, leading to a segmentation fault when trying to print it with my << overload, what am I doing wrong?
Edit: Oh, and of course I did add using namespace std;
at the start, same with including iostream
and cstring
.
There's a few things wrong here. First, let's fix your bracing. Just always use braces. It's very difficult to see what's lined up with what:
istream & operator >> (istream & is, Symbol & sym) {
Symbol Arr[]={e,a,b,c,d};
char ch;
is>>ch;
if (strchr("eabcd",ch)) {
sym=Arr[ch-'e'];
}
else {
is.unget();
is.setstate(ios::failbit);
}
return is;
}
Ok great. Now, what happens if the user inputs something like 'a'
. The strchr
succeeds, and then you do sym = Arr[ch - 'e']
. But ch - 'e'
in this case is -4
. That's some totally random bit of memory somewhere, so you're getting garbage. To actually use strchr
, you'd need to do something like:
const char* options = "eabcd";
if (const char* p = strchr(options, ch)) {
sym = Arr[p - options];
}
But that's kind of awful. I'd suggest just using a switch:
switch (ch) {
case 'e': sym = e; break;
case 'a': sym = a; break;
...
default:
is.unget();
is.setstate(ios::failbit);
}
Also, is >> ch
could fail and you're not checking that. You should:
istream& operator>>(istream& is, Symbol& sym) {
char ch;
if (is >> ch) {
switch(ch) { ... }
}
return is;
}