2

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"

Bence Kaulics
  • 7,066
  • 7
  • 33
  • 63
Sujay Kundu
  • 71
  • 1
  • 1
  • 10
  • 2
    For example, what is `1e1` - integer, float or string? – anatolyg Aug 29 '17 at 14:08
  • 1
    You can just try to convert it. Essentially that means reading in a line as string (use `getline`), and then e.g. put it in an `istringstream` and try to read whatever you want from that. If it fails the input wasn't that. – Cheers and hth. - Alf Aug 29 '17 at 14:08
  • By default, cin will take a _String_ input from the user. Whether it contains only numerical characters, or an _f_ for _float_ at the end, can be checked by iterating over the _chars_ of the _String_ and checking each _char_ – Josh Evans Aug 29 '17 at 14:12
  • 3
    Can you show me an example of input which is not a string? – n. m. could be an AI Aug 29 '17 at 14:13
  • bool is_double(const std::string& s) { std::istringstream iss(s); double d; return iss >> d >> std::ws && iss.eof(); } – Hariom Singh Aug 29 '17 at 14:13
  • Refer [typeid](https://stackoverflow.com/a/11310937/5811973) – Ishpreet Aug 29 '17 at 14:17
  • In Java there's an instanceof which tells you what you pass it. Someone asked a question similar to yours a while back. Can be found here: https://stackoverflow.com/questions/500493/c-equivalent-of-instanceof –  Aug 29 '17 at 14:24
  • Assuming you want the string entered to be classified as int/float/string. Loop over it to check if all are digits, if there is exactly one '.' and +/- in the beginning it is a float. If all are digits then an integer. There can be errors in this if string entered is a roman numeral etc. – akp Aug 29 '17 at 14:49
  • One problem is that "134" can be floating point also. Let's add a thorn to the recognition, scientific notation: -3.14159E-6. – Thomas Matthews Aug 29 '17 at 15:47

6 Answers6

10

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.

Artemy Vysotsky
  • 2,694
  • 11
  • 20
5

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.

George Hanna
  • 382
  • 2
  • 15
5
#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
Richard Hodges
  • 68,278
  • 7
  • 90
  • 142
0

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
Chris Uzdavinis
  • 6,022
  • 9
  • 16
0

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;
  }
}
markgalassi
  • 390
  • 6
  • 11
-1

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;
    }
}
Mohamed Salah
  • 868
  • 1
  • 15
  • 34