【问题标题】:How to declare a variable in the brackets of if statement?如何在if语句的括号中声明一个变量?
【发布时间】:2013-07-09 04:17:15
【问题描述】:

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

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

我想要的是,看看这个角色是不是我想要的。 通俗地说,我想在 if 的行和 if 的主体中都使用变量(char c),但不在 if。

但是 g++(GCC 4.8.1) 说 在 'char' 之前是预期的主表达式。 我想知道是否有办法做到这一点,因为我不想要类似的东西

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

【问题讨论】:

  • 你可以滥用for循环。
  • 如果是关于污染,你总是可以使用新的作用域,或者for循环。
  • 最简洁(愚蠢)的解决方案大概是if ( int c = getc( stdin ) - 1 ) ; else ungetc( c + 1 );
  • 为什么不解除变量定义和初始化的限制?
  • @GManNickG 风水?

标签: c++ c++11


【解决方案1】:

在看到一些发布的解决方案之前,我不知道如何创建变量并使用 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));

由于您只与一个值进行比较,因此您的特定问题根本不需要变量,因此您可以简单地这样做:

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

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

Jerry Coffin 的解决方案看起来很吸引人,但实际上归结为:

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】:

如果您担心的是命名空间污染,您可以随时在块中定义if 语句:

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

这样c 只会持续到到达块的末尾。

【讨论】:

  • 虽然没有回答问题,但这种写代码的方式简单、清晰、有效。谢谢。
  • @qlb1234 有时一个问题,就像你的情况一样,实际上是在问“我如何最好地编写糟糕的代码”。这些问题不应该用“这就是你编写糟糕代码的方式”来回答,而应该用“不要编写糟糕的代码,而是这样做”来回答。 :-)
  • @NikosC.:这个答案的吸引力在于它的简单性,但我很少发现这样的结构在代码审查中是可以接受的。当我看到这样一个独立的语句块时,我总是认为代码应该在一个单独的函数中。
【解决方案3】:

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

if (int ch = getchar())
    ;

问题是类型(例如,int)必须在左括号之后立即。您拥有的额外括号是导致编译失败的原因。所以,如果你真的想这样做,你需要变得聪明一点并使用这样的东西:

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

这使您可以完成ch 的创建和初始化,然后在表达式的该部分完成后,将ch=getchar() 放在括号中以覆盖赋值与. 比较。

请注意,&amp;&amp;|| 进行短路评估,因此您需要小心初始化。您可以使用:

if (char ch = 0 || ...

...或:

if (char ch = 1 && ...

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

现在需要注意的是:虽然我有理由确定这段代码符合标准的要求,并且大多数(所有?)当前的编译器都会接受它,但它可能会导致大多数程序员在阅读代码时遇到一些严重的问题已经完成了,为什么。对于在实际代码中使用这种“技术”,我会非常犹豫(充其量)。

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

【讨论】:

  • 你不能也用逗号吗?
  • @sje397:如果您尝试使用逗号,我拥有的每个编译器都会拒绝代码(我相信标准要求他们这样做)。
  • @JerryCoffin -1,无论你放多少括号,布尔值总是会以ch结尾。 IE。 char ch = 0 || ((ch = getchar()) == 42) 永远不会在 if 语句 的主体中包含 ch == 42
  • @JerryCoffin 当然,但是你也应该提到你正在做的事情相当于if (getchar () == 0x1) { /* just use 'true' instead of ch in here */ }
  • "这可以让你完成 ch 的创建和初始化,然后 [...]" 实际上 || 的右侧仍然是初始化表达式的一部分。 if 条件的语法要么是表达式,要么是单个声明;没有“声明后跟表达式”,因此您的代码结构使得表达式隐藏在声明的初始化程序中。
猜你喜欢
  • 2021-03-04
  • 1970-01-01
  • 2014-04-12
  • 1970-01-01
  • 2013-01-15
  • 1970-01-01
  • 2018-11-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多