Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to declare a variable in the brackets of if statement?

Tags:

c++

c++11

I want to declare a local variable in the brackets of an if statement. For example.

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

What I want is, to see if the character is the one I want. To say it commonly, I want to use the variable(char c) both in the line of if and the body of if, but not outside the if.

But g++(GCC 4.8.1) says expected primary-expression before 'char'. I wonder if there's a way to do that, because I don't want something like

char c = getc(stdin);
if(c == 0x01)
{
    bla...
}
like image 704
Wesley Avatar asked Jul 11 '13 02:07

Wesley


2 Answers

If it's the namespace pollution you are worrying about you can always define the if statement within a block:

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

So that c will only last until the end of the block is reached.

like image 107
Shoe Avatar answered Oct 05 '22 23:10

Shoe


I didn't know how to create a variable and test its value with an if until after seeing some of the posted solutions. However, you could use switch. This would allow you to react to additional values (perhaps EOF):

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

You could always place the if statement in an inlined function instead, and the code will look a little cleaner. If you really want the source code right at that location, but without creating a new scope around an if with a new variable, then perhaps a lambda would be acceptable to you.

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

Since you are only comparing against one valuem your particular problem does not require a variable at all, so you can simply do:

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

If you are wanting to compare against a set of values, then the switch suggestion is the better option.

Jerry Coffin's solution looks appealing, but it really boils down to:

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

This is probably not what you really wanted, as it does not generalize well if you want to compare to a value different from 0x01.

Potatoswatter's solution seems closer to what you want, but perhaps it would be nicer to pull the type out into a standalone class:

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...
}
like image 37
jxh Avatar answered Oct 05 '22 22:10

jxh