2017-03-06 71 views
-6

我对输入和输出感到困惑,谁能告诉我为什么我会得到这样的输出。开关盒中的逗号

#include<iostream> 
#include<stdlib.h> 
using namespace std; 

int main() 
{ 
    int ival, oddcnt(0), evencnt(0); 
    while (cin >> ival) { 
     switch (ival) { 
     case 1, 3, 5, 7, 9: 
      oddcnt++; 
      break; 
     case 2, 4, 6, 8, 10: 
      evencnt++; 
      break; 
     } 
    } 
    cout << "Quantity of odd number:" << oddcnt << "\n" 
     << "Quantity of even number:" << evencnt << endl; 
    system("pause"); 
    return 0; 
} 

这是结果获得: 输入:1 1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4 5 5 5 6 6 6 7 7 7 7 8 8 9 9 10 10 10 EOF 输出:奇数的数量:2 数量偶数:3 enter image description here

+3

我无法访问您的图像用我的工作场所的输出,你能写下来吗? –

+1

是什么让你认为'case 1,3,5,7,9:'是有效的C++? –

+0

我猜测它只能检查9和10。 [在逗号运算符上的某些帖子](http://stackoverflow.com/questions/54142/how-does-the-comma-operator-work) – JGroven

回答

4

逗号在case标签这种用法是非法的标准C++。这在语法上是不正确的。一致性编译器必须发布诊断消息来响应此代码,即使它以某种方式接受它。

有可能(或可能不)涉及一些复杂的细节。

  • 在原来的C++ 98语言逗号运算符被禁止使用的形式被用于case标签。它被语言规范的两个不同部分“封锁”:

    首先,constant-expression的语法不允许在常量表达式中使用顶级逗号运算符。在语法上,逗号运算符只能出现在包含在()中的常量表达式中。其次,C++ 98规范明确禁止在嵌套()(见5.19/1)的任何级别的常量表达式中使用逗号运算符。

    (这是基本相同的C语言的要求。)

  • 然而,C++ 11做了一些改变:它allowed comma operator in constant expressions。然而,语法没有改变。这意味着逗号运算符现在允许使用常量表达式,但只能在()中使用。例如。从C++ 11开始,你可以使用

    case (1, 3, 5, 7, 9): 
    

    这是一个普通的逗号运算符。它使相当于

    case 9: 
    

同时整个事情,你

case 1, 3, 5, 7, 9: 

仍然用C++非法的这一天。如果你的编译器以某种方式支持它,它必须是你的编译器实现的语言扩展。请查阅您的编译器文档以确定它的含义。

通过您得到的输出来判断,编译器将case 1, 3, 5, 7, 9:视为等效于case (1, 3, 5, 7, 9):,因此等于case 9:。这解释了输出。该程序只是在输入中计数9 s和10 s。你有两个9 s和三个10 s。

参见:
Is the comma operator allowed in a constant-expression in C++11?
Why was the restriction on the comma operator being in a constant expression removed in C++11?

+0

那么,正如OP中提到的那样,编译器拿了那个,并产生了一些输出?你确定这个骗局在这里被错误地应用了吗? –

+0

我更喜欢你的情况(1,3,5,7,9):解决方案比我的答案。不能说你有215K没有任何东西:) –

+0

[http://stackoverflow.com/questions/42618651/comma-in-switch-case] _italic_ ** bold **'code'你的解释在这里有道理。起初,考虑到逗号的低优先级,我想不出为什么它不计算1和2的数目。我想,尝试一个可以运行的错误程序很有趣。谢谢你的解释。 – Higher

0
switch (var) { 
    case value1: /* ... */ break; 
    case value2: /* ... */ break; 
    /* ... */ 
} 
2

可以尝试这代替开关内部:

switch (ival) { 
    case 1: 
    case 3: 
    case 5: 
    case 7: 
    case 9: 
    oddcnt++; 
    break; 

    case 2: 
    case 4: 
    case 6: 
    case 8: 
    case 10: 
    evencnt++; 
    break; 
} 
+1

或者他们可以丢弃'switch'并使用模数运算符。 'ival%2'是一个很好的偶数/奇数检测器。 – user4581301

+0

是的,其实你的答案会更好,更短。但我只是写了如何制作一个以他想要的方式工作的开关。 –

0
switch (ival) { 
     case 1, 3, 5, 7, 9: 
      oddcnt++; 
      break; 
     case 2, 4, 6, 8, 10: 
      evencnt++; 
      break; 
     } 

壳体1,3,5,7,9: 这种类型的switch语句会导致语法错误,但在您的情况下却没有。

语法错误(在编译器gcc版本5.4.0(GCC)):

error: expected ‘:’ before ‘,’ token 
     case 1, 3, 5, 7, 9: 
      ^
error: expected ‘:’ before ‘,’ token 
    case 2, 4, 6, 8, 10: 
     ^
error: expected primary-expression before ‘,’ token 

不过你可以试试下面的开关情况:

switch (ival) { 
     case 1: 
     case 3: 
     case 5: 
     case 7: 
     case 9: 
      oddcnt++; 
      break; 
     case 2: 
     case 4: 
     case 6: 
     case 8: 
     case 10: 
      evencnt++; 
      break; 
     } 
+0

它显然不会导致OP示例中的语法错误。 –

+0

我想知道它是如何通过编译? :D –

+0

没问题,因为@AnT的回答可能是由于OP的编译器提供的扩展... –