Question

I am trying to write an if statement but cannot find the proper expression form to use. I'm thinking of writing something like this:

if ( var != type(int) )

However, I am unsure exactly how to go about doing this, and this method does not work.

Am I at least thinking along the right lines?

Was it helpful?

Solution

It sounds like you're trying to overload a function:

void foo(int i)
{
    // stuff
}

void foo(float f)
{
    // stuff
}

int main(void)
{
    int i = 10;
    float f = 1.0f;

    foo(i); // calls foo(int)
    foo(f); // calls foo(float)
}

If you want int-special behavior and then something else in all other cases, you can use templates:

template <typename T>
void foo(T t)
{
    // T is something
}

template <>
void foo(int i)
{
    // for int's only
}

int main(void)
{
    int i = 10;
    float f = 1.0f;
    double d = 2.0;

    foo(i); // calls specialized foo
    foo(f); // calls generic foo
    foo(d); // calls generic foo
}

According to your comment ("Task at hand is a simple program: Take two user inputted integers and add them. Restrict input to integer only. I can do it in Python and I am thinking too along those lines. if num1 != type(int): print "You did not enter an integer, please enter a integer." else: continue"), you want something like this:

#include <iostream>

int main(void)
{
    int i;
    std::cin >> i;

    if (std::cin.fail())
    {
        std::cout << "Not valid!" << std::endl;
    }
    else
    {
        // ...
    }
}

This will notify invalid input such as "@#$", "r13", but does not catch cases such as "34fg", "12$#%", because it will read the int, and stop at "fg" and "$#%", respectively.

To check that, you will have to read in a line of input, and then try to convert that line into the type you want. (Thanks, litb). That means your question is more like this question:

#include <iostream>
#include <sstream>
#include <string>

int main(void)
{
    std::string input;
    std::getline(std::cin, input);

    std::stringstream ss(input);
    int i;
    ss >> i;

    if (ss.fail() || !(ss >> std::ws).eof())
    {
        std::cout << "Not valid!" << std::endl;
    }
    else
    {
        // ...
    }
}

This does the following: get input, and put it into a stringstream. Then after parsing the int, stream out any remaining white space. After that, if eof is false, this means there are left-over characters; the input was invalid.

This is much easier to use wrapped in a function. In the other question, the cast was re-factored away; in this question we're using the cast, but wrapping the input along with it.

#include <iostream>
#include <sstream>
#include <string>

bool parse_int(int& i)
{
    std::string input;
    std::getline(std::cin, input);

    std::stringstream ss(input);
    ss >> i;

    return !(ss.fail() || !(ss >> std::ws).eof());
}

int main(void)
{
    int i;

    if (!parse_int(i))
    {
        std::cout << "Not valid!" << std::endl;
    }
    else
    {
        // ...
    }
}

Or more generically:

#include <iostream>
#include <sstream>
#include <string>

template <typename T>
bool parse_type(T& t)
{
    std::string input;
    std::getline(std::cin, input);

    std::stringstream ss(input);
    ss >> t;

    return !(ss.fail() || !(ss >> std::ws).eof());
}

int main(void)
{
    int i;

    if (!parse_type(i))
    {
        std::cout << "Not valid!" << std::endl;
    }
    else
    {
        // ...
    }
}

This let's you parse other types with error checking.


If you're okay with exceptions, using lexical_cast (either from boost, or "faked", see the other question linked in-code [same as above link]), your code would look something like this:

#include <iostream>
#include <sstream>
#include <string>

/* Faked lexical-cast from question:
https://stackoverflow.com/questions/1243428/convert-string-to-int-with-bool-fail-in-c/
*/
template <typename T>
T lexical_cast(const std::string& s)
{
    std::stringstream ss(s);

    T result;
    if ((ss >> result).fail() || !(ss >> std::ws).eof())
    {
        throw std::bad_cast("Bad cast.");
    }

    return result;
}


template <typename T>
T parse_type(void)
{
    std::string input;
    std::getline(std::cin, input);

    return lexical_cast<T>(input);
}

int main(void)
{
    try
    {
        int i = parse_type<int>();
        float f = parse_type<float>();
    }
    catch (const std::exception& e)
    {
        std::cout << e.what() << std::endl;
    }
}

I don't think boost has a no-throw version of lexical cast, so we can make a true/false rather than exception version of this code by catching bad_cast's, as follows. Once again, this works with either boost or a custom lexical cast. (Anything that does a lexical cast and throws bad_cast):

#include <iostream>
#include <sstream>
#include <string>

/* Faked lexical-cast from question:
https://stackoverflow.com/questions/1243428/convert-string-to-int-with-bool-fail-in-c/
*/
template <typename T>
T lexical_cast(const std::string& s)
{
    std::stringstream ss(s);

    T result;
    if ((ss >> result).fail() || !(ss >> std::ws).eof())
    {
        throw std::bad_cast("Bad cast.");
    }

    return result;
}


template <typename T>
bool parse_type(T& t)
{
    std::string input;
    std::getline(std::cin, input);

    try
    {
        t = lexical_cast<T>(input);

        return true;
    }
    catch (const std::bad_cast& e)
    {
        return false;
    }
}

int main(void)
{
    int i;
    if (!parse_type(i))
    {
        std::cout << "Bad cast." << std::endl;
    }
}

Now it's back to a bool result, except we avoid code duplication by using existing lexical_cast functions.

You can of course choose which method you would like to use.

OTHER TIPS

C++ is a statically-typed language, meaning that the type of a variable is known by the compiler at all times. In order to declare var therefore, you have to specify a type for it, which makes the if statement you posted a moot point. If you can describe a bit more the task you are trying to accomplish, perhaps there is another path to solve your problem.

That is right, more information is needed, if you are looking for an equivalent of "instanceOf" operator of Java, there isn't one, unless you use RTTI and typeid.

Do you mean that you have a floating-point value and want to know if it's an integer or not?

In that case, try this:

#include <math.h>

//...

double x = 5.0;
if(round(x) == x) {
   // x has an integer value
}

Or, if the value is the result of some computation, there might be small rounding errors. Then try something like this:

double x = 4.99999999999;
if(abs(round(x) - x) < 1e-8)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top