Check if String Is Number in C++

Check if string is a number in C++

1. Introduction to the Problem Statement

In C++ programming, a common task is determining whether a given string represents a valid number. This challenge can arise in various contexts, such as input validation, data parsing, or before performing arithmetic operations.

Our Goal: To check if a string like "123" or "45.67" is a valid number.

Expected Output: A boolean value – true if the string is a number, false otherwise.

We will explore multiple methods to accomplish this task, assess their performance, and discuss their suitability in different scenarios.

2. Using std::istringstream

One standard approach is to use std::istringstream from the <sstream> header.

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

bool isNumberIstringstream(const std::string& str) {
    std::istringstream iss(str);
    double val;
    iss >> val;
    return iss.eof() && !iss.fail();
}

int main() {
    std::string testStr = "123.45";
    std::cout << "Using std::istringstream: " << isNumberIstringstream(testStr) << std::endl;
    return 0;
}

 

Explanation: The function isNumberIstringstream checks if the string "123.45" can be completely read as a double. Since it can, the function returns true (represented as 1 in C++ boolean context).

Performance: Generally efficient for most cases.

Use Cases: Suitable for a wide range of applications, particularly where standard library solutions are preferred.

3. Using std::stod and Exception Handling

Another method involves std::stod (string to double conversion) wrapped in a try-catch block.

#include <iostream>
#include <string>
#include <stdexcept>

bool isNumberStod(const std::string& str) {
    try {
        size_t pos;
        std::stod(str, &pos);
        return pos == str.length();
    } catch (const std::invalid_argument& ia) {
        return false;
    } catch (const std::out_of_range& oor) {
        return false;
    }
}

int main() {
    std::string testStr = "123.45";
    std::cout << "Using std::stod: " << isNumberStod(testStr) << std::endl;
    return 0;
}

 

Explanation: isNumberStod tries to convert the string "123.45" to a double using std::stod. This conversion is successful, and the entire string is processed (pos == str.length()), so the function returns true.

Performance: Comparable to std::istringstream, but may be slightly slower due to exception handling.

Use Cases: Good when you need more control over error handling, particularly in larger applications with robust error management.

4. Using Regular Expressions

For more complex scenarios, regular expressions can be used.

#include <iostream>
#include <regex>
#include <string>

bool isNumberRegex(const std::string& str) {
    std::regex numberRegex("^[-+]?([0-9]*\\.[0-9]+|[0-9]+)$");
    return std::regex_match(str, numberRegex);
}

int main() {
    std::string testStr = "123.45";
    std::cout << "Using Regular Expressions: " << isNumberRegex(testStr) << std::endl;
    return 0;
}

 

Explanation: isNumberRegex uses a regular expression to match the string against a numeric pattern. The string "123.45" matches the pattern, so the function returns true.

Performance: Slower than previous methods, especially for short strings or in tight loops.

Use Cases: Ideal for scenarios where the definition of a number is complex or non-standard (like including/excluding scientific notation).

5. Custom Parsing Method

For educational purposes, a manual parsing method can be implemented.

#include <iostream>
#include <string>
#include <cctype>

bool isNumberCustom(const std::string& str) {
    if(str.empty()) return false;
    size_t i = 0;
    if (str[0] == '+' || str[0] == '-') i = 1;

    bool hasDigits = false, hasDecimalPoint = false;
    for (; i < str.size(); ++i) {
        if (std::isdigit(str[i])) {
            hasDigits = true;
        } else if (str[i] == '.' && !hasDecimalPoint) {
            hasDecimalPoint = true;
        } else {
            return false;
        }
    }
    return hasDigits;
}

int main() {
    std::string testStr = "123.45";
    std::cout << "Using Custom Parsing Method: " << isNumberCustom(testStr) << std::endl;
    return 0;
}

 

Explanation:

  • isNumberCustom manually checks each character of "123.45" to determine if it is a valid number. It uses std::isdigit() to check if a character is a digit.
  • std::isdigit(char c): This function checks if the character c is a digit (0 to 9). It is a part of the <cctype> header and is useful for character-by-character analysis, especially in custom parsing logic as seen in this method.
  • The string "123.45" passes all the checks (digits and at most one decimal point), leading the function to return true.

Performance: Can be efficient, particularly for simple cases.

Use Cases: Useful when you want full control over what constitutes a number, or in environments where library usage is restricted.

6. Conclusion

In this article, we’ve explored various methods to check if a string is a number in C++. std::istringstream and std::stod provide standard library solutions that are efficient for most cases. Regular expressions offer flexibility for complex number formats but at a performance cost. The custom parsing method, while less efficient, provides deeper insights and full control over the parsing logic.

[social_share share_on="facebook,twitter,linkedin,whatsapp"][post_navigator in_same_term="true"]

Leave a Reply

Your email address will not be published. Required fields are marked *

Subscribe to our newletter

Get quality tutorials to your inbox. Subscribe now.