Hi,

I'm having problems checking whether a string is an unsigned integer. The code I am using only checks the first character of the string, so "a1" would return false, but "1a" would return true. Any ideas where I'm going wrong?

bool checkUnsignedInt(string *str)
{
	unsigned long value;
	stringstream ss(*str);

	if (ss >> value)
	{
		return true;
	}
	else
	{
		return false;
	}
}

Thanks

Dani AI

Generated

Short version: operator>> will happily parse the leading number and stop at the first non-digit, so your original stringstream approach returns success for "1a". That is the behaviour ran into. Checking only the first character (as suggested) is not enough; you must ensure the whole string is digits or that the numeric parser consumed the entire string (as suggested conceptually). Also avoid atoi (as suggested) because it gives no trailing-data or overflow diagnostics.

A simple, fast validator (no numeric conversion) is to require at least one character and verify every character is a digit (allow an optional leading '+'). Use std::all_of with a safe std::isdigit wrapper to avoid UB:

bool isUnsignedDigits(const std::string& s)
{
    if (s.empty()) return false;
    std::size_t start = (s[0] == '+') ? 1 : 0;
    if (start == 1 && s.size() == 1) return false;
    return std::all_of(s.begin() + start, s.end(),
                       [](char c){ return std::isdigit(static_cast<unsigned char>(c)); });
}

If you need the numeric value and robust error/overflow handling, prefer std::stoul (C++11+) or strtoul (C) and check that the parser consumed the whole string and that there was no overflow. Example pattern with std::stoul (reject a leading '-'):

bool parseUnsigned(const std::string& s, unsigned long &out)
{
    if (s.empty() || s[0] == '-') return false;
    std::size_t pos = 0;
    try {
        out = std::stoul(s, &pos, 10);
    } catch (const std::invalid_argument&) { return false; }
    catch (const std::out_of_range&) { return false; }
    return pos == s.size();
}

Troubleshooting notes: watch for leading/trailing whitespace (trim or reject), explicitly reject - if you want only unsigned input, and test edge cases like "", +, 42, 1a, and very large numbers. std::all_of/isdigit is the simplest full-match check; std::stoul/strtoul give you value+overflow detection. This ties the earlier replies together: the stream-trailing check works, ArkM’s digit-only idea is valid, and the real fixes are either “all chars are digits” or “conversion consumed the whole string.”

Recommended Answers

All 7 Replies

What exactly is the problem? this works fine for me....nvm

EDIT:
of you need to loop through each character rather than just using the first one

Chris

Member Avatar for Member #248612

Maybe something like this comes helpful:

bool checkUnsignedInt(string *str)
{
	unsigned long value;
	stringstream ss(*str);

	if (ss >> value)
	{
                string str;
                ss >> str;
                return str.empty(); // nothing following the digits
	}
	return false;
}

*Mumbles something about multiple exit points*

You can do that:

bool checkUnsignedInt(const string &str)
{
	return atoi(str.c_str()) >= 0;
}

I think you can simply check if the first character is a numeral.

I think you can simply check if the first character is a numeral.

Thats what his code does, but that doesn't mean that "1dfjkghdflgh" is an integer, because it isn't. But by your logic it would be.

Chris

inline bool isUint(const std::string& s)
{
    return s.find_first_not_of("0123456789") == std::string::npos;
}
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.