Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Check if a string is a number without regex or try catch

I want to implement a simple is_number function that checks if it’s an integer, float or an unsigned long int using this method:

bool isNumber(const std::string& str)
{
    size_t idx = 0;

    //Check if it's an integer
    std::stoi(str,&idx);
    if (idx == str.size())
        return true;

    //Check if it's a float  
    std::stof(str,&idx);
    if (idx == str.size() || str[str.size()-1] == 'f' && idx == str.size()) //Cause I do have some float numbers ending with 'f' in the database
        return true;

    //Check if it's an unsigned long int
    std::stoul(str,&idx);
    if (idx == str.size())
        return true;
        
    return false;
}

But if I test it with a pure string like "test" or "nan", it will throw an error because I’m trying to change a pure string to an integer.

terminate called after throwing an instance of 'std::invalid_argument'
  what():  stoi

However if I test it with "0nan" for example, stoi or the others will retrieve the first number and assign the index position of the first found number to the idx variable.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Is it possible to find a workaround for pure strings like "nan" or any other?
Or is there a better method to implement this without regex or try-catch?

>Solution :

std::stoi throws when it fails. Instead of using C i/o you can use C++ streams, try to read from the stream and check if there is something left in the stream:

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

enum Number {Float,Signed,Unsigned,NotANumber};


template <typename T>
bool is_only_a(const std::string& str){
    std::stringstream ss(str);
    T x;
    return (ss >> x && ss.rdbuf()->in_avail() ==0);
}

Number isNumber(const std::string& str)
{
    size_t idx = 0;

    if (is_only_a<unsigned long>(str)) return Unsigned;
    else if (is_only_a<int>(str)) return Signed;
    else if (is_only_a<float>(str)) return Float;
    return NotANumber;
}

int main() {
    std::cout << isNumber("1.2") << "\n";
    std::cout << isNumber("12") << "\n";
    std::cout << isNumber("-12") << "\n";
    std::cout << isNumber("asd") << "\n";
    std::cout << isNumber("nan") << "\n";
}

Order is important, because 12 could be a float as well.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading