Sujay Kundu
Sujay Kundu

Reputation: 71

How to check whether an input is integer, string or float in C++

What I want to know is, If I ask a user to input something, how will I output if the input is a Integer or String or a Float Value. I want some method to check the data type of the input in C++14.

For eg.

If the input is "Hello world"

Output should be : "The input is String"

If the input is "134"

Output should be : "The input is integer"

If the input is "133.23"

Output should be : "The input is float"

Upvotes: 2

Views: 13216

Answers (6)

markgalassi
markgalassi

Reputation: 370

I don't have an answer [edited: I actually do; see the end of a proposal that is old-style but does not do exceptions], but I could not fit this into comments -- I'm worried about the suggestions that involve "try using stoi()": if you don't have an integer then stoi() will throw an exception. Suddenly you're in exception handling territory with that problematic approach to logic (you don't want to use exception handling as logic) and possibly significant slowing down. See code below to see how you trigger exceptions.

It seems to me that the solutions based on parsing text are more appropriate.

#include <string>  
#include <iostream>  

// compile and run with:
// g++ -Wall test_stoi.cpp
// ./a.out
// output should look like:
// terminate called after throwing an instance of 'std::invalid_argument'
// what():  stoi


using namespace std;

int main()
{
  string s = "dude";
  size_t pos;
  int x = stoi(s, &pos);
  cout << "x,pos: " << x << "   " << pos << "\n";
}

A footnote: the C++ "official" FAQ firmly states:

Do not use exceptions as simply another way to return a value from a function. Most users assume – as the language definition encourages them to – that ** exception-handling code is error-handling code **, and implementations are optimized to reflect that assumption.

https://isocpp.org/wiki/faq/exceptions

#include <string>
#include <vector>
#include <tuple>
#include <iostream>

// compile and run with:                                                                                                                                              
// g++ -ggdb3 -O0 -Wall -Wextra -pedantic -Wno-unused-result str_has_number.cpp                                                                                       
// ./a.out                                                                                                                                                            
//                                                                                                                                                                    
// <2.5> -- 1                                                                                                                                                         
// <17> -- 1                                                                                                                                                          
// <dude> -- 0                                                                                                                                                        
// <2.5 junk> -- 0                                                                                                                                                    
// <stuff 12> -- 0                                                                                                                                                    
// <hey14.2> -- 0                                                                                                                                                     
// <55 3.14159> -- 0                                                                                                                                                  


using namespace std;

static bool dio_str_has_number(string s);

int main()
{
  vector<string> test_strings = {"2.5", "17", "dude", "2.5 junk",
                                 "stuff 12", "hey14.2", "55 3.14159"};
  for (string &s : test_strings) {
    bool has_num = str_has_number(s);
    cout << "<" + s + "> -- " << has_num << "\n";
  }
}

/**                                                                                                                                                                   
 * @brief Find if the given string contains a number.                                                                                                                 
 */
static bool str_has_number(string s)
{
  char* p_end;
  // there are three different ways                                                                                                                                   
  (void) strtod(s.c_str(), &p_end);
  // std::ignore = strtod(s.c_str(), &p_end);                                                                                                                         
  // [[maybe_unused]] double x = strtod(s.c_str(), &p_end);                                                                                                           
  if (p_end != s.c_str() && p_end == s.c_str() + s.size()) {
    // if the end pointer is not at the start, and at it is at the end                                                                                                
    // end of the string, then we found a number                                                                                                                      
    return true;
  } else {
    return false;
  }
}

Upvotes: 0

Mohamed Salah
Mohamed Salah

Reputation: 1205

You can easily wrap string.strof for float or string.stroi for int in try-catch block:

#include <string>
bool isFloat(string str) {
    try {
        float floatCheck = stof(str);
        return true;
    }
    catch (...) {
        return false;
    }
}

bool isInt(string str) {
    try {
        int intCheck = stoi(str);
        return true;
    }
    catch (...) {
        return false;
    }
}

Upvotes: -1

Chris Uzdavinis
Chris Uzdavinis

Reputation: 6131

The input is in a string. Without additional agreements, how could you possibly know if the user intended "1" to be the string containing the character '1' or a string representation of the integer 1?

If you decide that "if it can be interpreted as an int, then it's an int. If it can be a double, then it's a double. Else it's a string", then you can just do a series of conversions until one works, or do some format checking, perhaps with a regexp.

Since all ints can be converted into doubles, and string representations of doubles can be converted into ints (perhaps with some junk left over) if you care about the difference, you probably need to check for indicators of it being a double (digits with perhaps a . in it, possibly a 'e' with +/- possibly after it. Etc. You can find regexps on the internet, depending on what you want to allow, leading +, e-notation, etc.

If it's an int, you can use regex ^\d+$, else if it's a double, [+-]?(?:0|[1-9]\d*)(?:.\d*)?(?:[eE][+-]?\d+)? else it's a string.

Here's some code that seems to work. :)

#include <iostream>
#include <string>
#include <regex>
using namespace std;


void handleDouble(double d) {
    std::cout << "Double = " << d << "\n";
}

void handleInt(int i) {
    std::cout << "Int = " << i << "\n";
}

void handleString(std::string const & s) {
    std::cout << "String = " << s << "\n";
}

void parse(std::string const& input) {
    static const std::regex doubleRegex{ R"([+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)" };
    static const std::regex intRegex{ R"(\d+)"};

    if (std::regex_match(input, intRegex)){
        istringstream inputStream(input);
        int i;
        inputStream >> i;
        handleInt(i);
    }
    else if (std::regex_match(input, doubleRegex)) {
        istringstream inputStream(input);
        double d;
        inputStream >> d;
        handleDouble(d);
    }
    else {
        handleString(input);
    }
}

int main()
{
    parse("+4.234e10");
    parse("1");
    parse("1.0");
    parse("123abc");
}

output:

Double = 4.234e+10
Int = 1
Double = 1
String = 123abc

Upvotes: 0

Richard Hodges
Richard Hodges

Reputation: 69864

#include <iostream>
#include <string>
#include <boost/variant.hpp>
#include <sstream>


using myvariant = boost::variant<int, float, std::string>;

struct emit : boost::static_visitor<void>
{
    void operator()(int i) const {
        std::cout << "It's an int: " << i << '\n';
    }

    void operator()(float f) const {
        std::cout << "It's a float: " << f << '\n';
    }

    void operator()(std::string const& s) const {
        std::cout << "It's a string: " << s << '\n';
    }
};

auto parse(const std::string& s) -> myvariant
{
    char* p = nullptr;

    auto i = std::strtol(s.data(), &p, 10);
    if (p == s.data() + s.size())
        return int(i);

    auto f = std::strtof(s.data(), &p);
    if (p == s.data() + s.size())
        return f;


    return s;
}

void test(const std::string& s)
{
    auto val = parse(s);
    boost::apply_visitor(emit(), val);
}

int main()
{
    test("Hello world");
    test("134");
    test("133.23");
}

expected output:

It's a string: Hello world
It's an int: 134
It's a float: 133.23

Upvotes: 5

Artemy Vysotsky
Artemy Vysotsky

Reputation: 2734

Read string.

In <string>, the standard library provides a set of functions for extracting numeric values from their character representation in a string or wstring.

Use x=stoi(s,p). Check p - if whole string was read - it is integer.

Do the same with x=stof(s,p) or x=stod(s,p), x=stold(s,p) to check for float/double/long double.

If everything fails - it is string.

Upvotes: 10

George Hanna
George Hanna

Reputation: 392

The user will always input a string, what you can do is try to convert it to a float, if it succeeds then it probably is a float or an int. If the float conversion doesnt succeed then its probably not a number.

Upvotes: 5

Related Questions