From 07f9c744b35aab71bc18084317e06a745593d06e Mon Sep 17 00:00:00 2001 From: Andreas Suter Date: Sat, 6 Jun 2026 14:14:11 +0200 Subject: [PATCH] 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 --- src/classes/PStringUtils.cpp | 27 +++++++++++++++++++-------- src/include/PStringUtils.h | 8 +++++--- src/tests/strToNum/strToNum.cpp | 6 +++++- 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/src/classes/PStringUtils.cpp b/src/classes/PStringUtils.cpp index 45eaf89a7..2a588c7ad 100644 --- a/src/classes/PStringUtils.cpp +++ b/src/classes/PStringUtils.cpp @@ -65,23 +65,34 @@ std::vector PStringUtils::Split(const std::string &str, const std:: // IsInt (static) //-------------------------------------------------------------------------- /** - *

Returns true if the string is a non-empty sequence of decimal digits - * only. Mirrors the semantics of TString::IsDigit(). + *

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(c))) + if (std::isdigit(static_cast(c))) { hasDigit = true; - else if (!std::isspace(static_cast(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(c))) { return false; + } } return hasDigit; } diff --git a/src/include/PStringUtils.h b/src/include/PStringUtils.h index c28aadc65..01eeb4f01 100644 --- a/src/include/PStringUtils.h +++ b/src/include/PStringUtils.h @@ -67,11 +67,13 @@ class PStringUtils static std::vector Split(const std::string &str, const std::string &delimiters); /** - *

Returns true if the string is a non-empty sequence of decimal - * digits only. Mirrors TString::IsDigit(). + *

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); diff --git a/src/tests/strToNum/strToNum.cpp b/src/tests/strToNum/strToNum.cpp index f06f53ace..993e029fb 100644 --- a/src/tests/strToNum/strToNum.cpp +++ b/src/tests/strToNum/strToNum.cpp @@ -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")); }