PStringUtils::IsInt: accept an optional leading sign

IsInt now recognises (possibly signed) integers such as "-5" or "+42",
making it slightly more permissive than TString::IsDigit(). A lone sign,
a double sign, or a sign following a digit are still rejected. strToNum
test expectations updated accordingly.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-06 14:14:11 +02:00
parent aa5cdf8d6a
commit 07f9c744b3
3 changed files with 29 additions and 12 deletions
+19 -8
View File
@@ -65,23 +65,34 @@ std::vector<std::string> PStringUtils::Split(const std::string &str, const std::
// IsInt (static)
//--------------------------------------------------------------------------
/**
* <p>Returns true if the string is a non-empty sequence of decimal digits
* only. Mirrors the semantics of TString::IsDigit().
* <p>Returns true if the string is an integer literal, i.e. a non-empty
* sequence of decimal digits with an optional single leading sign (+/-).
* This is slightly more permissive than TString::IsDigit(), which rejects a
* sign, so that negative/positive integers such as "-5" or "+42" are also
* recognised.
*
* \param str string to be checked
* \return true if str consists of digits only
* \return true if str is a (possibly signed) integer
*/
bool PStringUtils::IsInt(const std::string &str)
{
// mirror TString::IsDigit(): all characters must be digits or whitespace,
// and there must be at least one digit (surrounding/embedded whitespace is
// tolerated, e.g. for tokens split on ',' or ';' only).
// all characters must be digits or whitespace, with an optional single
// leading sign (+/-) preceding the digits, and there must be at least one
// digit (surrounding/embedded whitespace is tolerated, e.g. for tokens
// split on ',' or ';' only).
bool hasDigit = false;
bool hasSign = false;
for (char c : str) {
if (std::isdigit(static_cast<unsigned char>(c)))
if (std::isdigit(static_cast<unsigned char>(c))) {
hasDigit = true;
else if (!std::isspace(static_cast<unsigned char>(c)))
} else if (c == '+' || c == '-') {
// a sign is only valid before any digit and may appear at most once
if (hasDigit || hasSign)
return false;
hasSign = true;
} else if (!std::isspace(static_cast<unsigned char>(c))) {
return false;
}
}
return hasDigit;
}
+5 -3
View File
@@ -67,11 +67,13 @@ class PStringUtils
static std::vector<std::string> Split(const std::string &str, const std::string &delimiters);
/**
* <p>Returns true if the string is a non-empty sequence of decimal
* digits only. Mirrors TString::IsDigit().
* <p>Returns true if the string is a (possibly signed) integer literal,
* i.e. a non-empty sequence of decimal digits with an optional single
* leading sign (+/-). Slightly more permissive than TString::IsDigit(),
* which rejects a sign, so that e.g. "-5" is also recognised.
*
* @param str string to be checked
* @return true if str consists of digits only
* @return true if str is a (possibly signed) integer
*/
static bool IsInt(const std::string &str);
+5 -1
View File
@@ -114,9 +114,13 @@ static void testIsInt()
check("'12345' is int", PStringUtils::IsInt("12345"));
check("' 42 ' (surrounding ws) is int", PStringUtils::IsInt(" 42 "));
check("'-5' is int (negative)", PStringUtils::IsInt("-5"));
check("'+42' is int (positive sign)", PStringUtils::IsInt("+42"));
check("'' is not int", !PStringUtils::IsInt(""));
check("' ' (ws only) is not int", !PStringUtils::IsInt(" "));
check("'-5' is not int (sign not allowed)", !PStringUtils::IsInt("-5"));
check("'-' (sign only) is not int", !PStringUtils::IsInt("-"));
check("'+-5' (double sign) is not int", !PStringUtils::IsInt("+-5"));
check("'5-3' (sign after digit) is not int", !PStringUtils::IsInt("5-3"));
check("'3.14' is not int", !PStringUtils::IsInt("3.14"));
check("'12a' is not int", !PStringUtils::IsInt("12a"));
}