使用strchr过载>>

时间:2016-03-18 21:38:38

标签: c++ operator-overloading inputstream strchr

我试图重载>>运算符读取单个(使用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;,与包含iostreamcstring相同。

2 个答案:

答案 0 :(得分:1)

这里有一些问题。首先,让我们来修复你的支撑。只需要总是使用大括号。很难看出它们的内容是什么:

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

答案 1 :(得分:0)

如果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'.