2013-07-11 307 views
7

我想在if语句的括号中声明一个局部变量。例如, 。如何在if语句的括号中声明一个变量?

if((char c = getc(stdin)) == 0x01)//This is not OK with g++. 
{ 
    ungetc(c, stdin); 
} 

我想要的是看看角色是否是我想要的角色。 一般来说,我想在如果如果但是不在如果之外使用变量(char c)。

但g ++(GCC 4.8.1)说期望在'char'之前的主表达式。 我不知道是否有一种方法可以做到这一点,因为我不希望像

char c = getc(stdin); 
if(c == 0x01) 
{ 
    bla... 
} 
+3

你可能会滥用'for'循环。 – SLaks

+2

如果是污染问题,您可以随时使用新的作用域或for循环。 – chris

+0

最简洁(愚蠢)的解决方案可能是'if(int c = getc(stdin) - 1); else ungetc(c + 1);'。 – Potatoswatter

回答

17

如果这是你担心你总是可以定义命名空间污染区块内if声明:

{ 
    char c = getc(stdin); 
    if(c == 0x01) 
    { 
     // ... 
    } 
} 

这样c将只持续,直到到达块的结束。

+4

虽然没有回答问题,但这种写代码的方式简单明了有效。谢谢。 – Wesley

+3

@ qlb1234有时候一个问题,就像你的情况一样,有效地询问“我如何最好地编写错误的代码”。这些问题不应该用“这就是你如何编写错误的代码”来解决,而是“不要编写错误的代码,而是做这个”。 :-) –

+2

@NikosC .:这个答案的吸引力在于它的简单性,但我很少在代码评论中发现这样的结构是可以接受的。当我看到像这样的独立语句块时,我总是认为代码应该在一个单独的函数中。 – jxh

10

我不知道如何创建一个变量,并看到一些贴后测试其与if值,直到解决方案。但是,您可以使用switch。这将允许你向另外的值(也许EOF)反应:

switch (int c = getc(stdin)) { 
case 0x01: ungetc(c, stdin); break; 
case EOF: // ...handle EOF 
default: break; 
} 

你总是可以放置if声明内联函数来代替,而且代码看起来干净了一点。如果你确实需要在该位置的源代码,但是没有用一个新变量在if周围创建一个新的范围,那么你可能会接受一个lambda。

[](int c){ if (c == 0x01) ungetc(c, stdin); }(getc(stdin)); 

由于您只对一个值M比较您的具体问题并不需要一个变量可言,所以你可以简单地做:

if (getc(stdin) == 0x01) { 
    char c = 0x01; 
    ungetc(c, stdin); //or bla... 
} 

如果你想要进行比较的一组值,那么switch建议是更好的选择。

杰里棺材的解决方案看起来有吸引力,但它确实可以归结为:

if (int c = (getc(stdin) == 0x01)) //... 

这可能不是你真正想要的,因为它如果要比较从0x01不同的值,并不能一概而论好。

Potatoswatter的解决方案似乎更接近你想要什么,但也许这将是更好的拉式出到一个独立的类:

template <typename T> 
class SetAndTest { 
    const T test_; 
    T set_; 
public: 
    SetAndTest (T s = T(), T t = T()) : set_(s), test_(t) {} 
    operator bool() { return set_ == test_; } 
    operator bool() const { return set_ == test_; } 
    operator T &() { return set_; } 
    operator T() const { return set_; } 
}; 

//... 
if (auto c = SetAndTest<int>(getc(stdin), 0x01)) { 
    ungetc(c, stdin); //or bla... 
} 
+2

这就是......聪明:p – chris

+0

哇,从来没有想到这一点。 – Manas

+0

你为什么要重复操作符重载? – aah134

8

可以if语句里面定义变量就好了。例如,这应该编译:

if (int ch = getchar()) 
    ; 

问题是,类型(例如,,int)必须在右括号后跟着。你有的额外括号是导致编译失败的原因。所以,如果你真的想这样做,你需要得到一个小聪明,用这样的:一部分后

if (char ch = 0 || ((ch = getchar()) == 0x1)) 

这可以让你创建和初始化ch做,然后的表达是完整的,放在围绕ch=getchar()的括号中以覆盖赋值与比较的优先级。

请注意,&&||做短路评估,所以你需要小心你的初始化。您可以使用:

if (char ch = 0 || ... 

...或:

if (char ch = 1 && ... 

...但如果您尝试使用if (ch = 1 || ...if (ch = 0 && ...,短路评估将保持正确的操作数(部分你真的关心)被评估。

现在需要注意的是,虽然我相当肯定这段代码符合标准的要求,而且大多数(所有)当前编译器都会接受它,但很可能会导致大多数程序员阅读代码时会认真摸清头绪你已经完成了,为什么。我会非常犹豫(充其量)关于在实际代码中使用这种“技术”。

编辑:有人指出,由此产生的结果可能比最初期望的更具误导性,所以我会试着澄清一下情况。会发生什么是从输入中读取一个值。该值分配给ch并与0x1进行比较。到现在为止还挺好。之后,比较结果(转换为整数,因此01)将被分配到ch。我相信它有足够的顺序点,结果是定义的行为。但这可能不是你或者任何人想要的 - 因此你可能不想使用它的建议,以及提及它可能会让大多数程序员挠着脑袋,想知道你在做什么。在与0x1进行比较的特定情况下,if语句内的ch值将为1,但这或多或少都是巧合。如果您比较的是0x2,则if内的ch的值仍将为1,而不是2

+0

难道你不能使用逗号吗? – sje397

+0

@ sje397:奇怪的是,没有 - 在这种情况下不允许。 –

+0

'0 ||'部分是做什么的?看起来'ch = true'将不可避免地发生在'ch = getchar()'之后。 – Potatoswatter

相关问题