使用 strchr 重载 >>
Using strchr to overload >>
我正在尝试重载 >> 运算符以读取单个(使用 enum Symbol {e,a,b,c,d};
创建)符号:
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;
}
但这读取了一些垃圾(数字)而不是我正在寻找的东西,导致在尝试使用我的 << 重载打印它时出现分段错误,我做错了什么?
编辑:哦,当然我确实在开头添加了 using namespace std;
,包括 iostream
和 cstring
。
如果ch
是'a'
,ch - 'e'
(97 - 101)将是一个负数(-4),这将导致访问数组Arr
出界。这会导致未定义的行为。
您拥有符号的方式需要使用 switch
语句:
switch (ch)
{
case 'a':
sym = a;
break;
case 'b':
sym = b;
break;
case 'c':
sym = c;
break;
case 'd':
sym = d;
break;
case 'e':
sym = e;
break;
default:
// Nothing to do
break;
}
如果您想使用Arr
,您需要将Arr
定义为:
Symbol Arr[]={a,b,c,d,e};
然后,您可以如下访问数组并避免 switch
语句:
sym=Arr[ch-'a']; // ch - 'a' is 0 when ch is 'a'
// ch - 'a' is 4 when ch is 'e'.
这里有些地方不对。首先,让我们修复您的支撑。只是总是使用大括号。很难看到什么与什么对齐:
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;
}
很好。现在,如果用户输入类似 'a'
的内容会发生什么。 strchr
成功,然后你做 sym = Arr[ch - 'e']
。但是 ch - 'e'
在这种情况下是 -4
。那是某处完全随机的内存位,所以你得到了垃圾。要实际使用 strchr
,您需要执行以下操作:
const char* options = "eabcd";
if (const char* p = strchr(options, ch)) {
sym = Arr[p - options];
}
但这有点糟糕。我建议只使用一个开关:
switch (ch) {
case 'e': sym = e; break;
case 'a': sym = a; break;
...
default:
is.unget();
is.setstate(ios::failbit);
}
另外、is >> ch
可能会失败,而您没有检查它。你应该:
istream& operator>>(istream& is, Symbol& sym) {
char ch;
if (is >> ch) {
switch(ch) { ... }
}
return is;
}
我正在尝试重载 >> 运算符以读取单个(使用 enum Symbol {e,a,b,c,d};
创建)符号:
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;
}
但这读取了一些垃圾(数字)而不是我正在寻找的东西,导致在尝试使用我的 << 重载打印它时出现分段错误,我做错了什么?
编辑:哦,当然我确实在开头添加了 using namespace std;
,包括 iostream
和 cstring
。
如果ch
是'a'
,ch - 'e'
(97 - 101)将是一个负数(-4),这将导致访问数组Arr
出界。这会导致未定义的行为。
您拥有符号的方式需要使用 switch
语句:
switch (ch)
{
case 'a':
sym = a;
break;
case 'b':
sym = b;
break;
case 'c':
sym = c;
break;
case 'd':
sym = d;
break;
case 'e':
sym = e;
break;
default:
// Nothing to do
break;
}
如果您想使用Arr
,您需要将Arr
定义为:
Symbol Arr[]={a,b,c,d,e};
然后,您可以如下访问数组并避免 switch
语句:
sym=Arr[ch-'a']; // ch - 'a' is 0 when ch is 'a'
// ch - 'a' is 4 when ch is 'e'.
这里有些地方不对。首先,让我们修复您的支撑。只是总是使用大括号。很难看到什么与什么对齐:
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;
}
很好。现在,如果用户输入类似 'a'
的内容会发生什么。 strchr
成功,然后你做 sym = Arr[ch - 'e']
。但是 ch - 'e'
在这种情况下是 -4
。那是某处完全随机的内存位,所以你得到了垃圾。要实际使用 strchr
,您需要执行以下操作:
const char* options = "eabcd";
if (const char* p = strchr(options, ch)) {
sym = Arr[p - options];
}
但这有点糟糕。我建议只使用一个开关:
switch (ch) {
case 'e': sym = e; break;
case 'a': sym = a; break;
...
default:
is.unget();
is.setstate(ios::failbit);
}
另外、is >> ch
可能会失败,而您没有检查它。你应该:
istream& operator>>(istream& is, Symbol& sym) {
char ch;
if (is >> ch) {
switch(ch) { ... }
}
return is;
}