Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed last year.
The community reviewed whether to reopen this question last year and left it closed:
Original close reason(s) were not resolved
Improve this question
I want to know if there is a lambda or a clean short format in order to find if a single string contains only numeric values e.g 0 - 9 and the full stop character e.g . only.
For example string "123.45" should pass and strings "12jd", "12.4f" etc should fail.
This would be the code for your check, the constexpr stuff makes the function evaluatable at compile time. And the static_assert checks the output at compile time. Basically doing a unit test at compile time.
string_view is a nice wrapper for string literals and makes the string literal more easy to pass into the function and allows the use of a range based for loop to loop over all the characters.
#include <cassert>
#include <string_view>
constexpr bool is_positive_number(const std::string_view number_string)
{
std::size_t number_of_points{ 0ul };
// loop over all characters in string
for (const auto character : number_string)
{
// a '.' is valid but there should only be one
if (character == '.')
{
number_of_points++;
if (number_of_points > 1) return false;
}
else
{
// if character is not a '.' then it must be betweern '0'-'9'
if ((character < '0') || (character > '9')) return false;
}
}
return true;
}
int main()
{
static_assert(is_positive_number("1"));
static_assert(is_positive_number("12"));
static_assert(is_positive_number("123"));
static_assert(is_positive_number("1."));
static_assert(is_positive_number("1.2"));
static_assert(is_positive_number("12.34"));
static_assert(is_positive_number("007"));
static_assert(!is_positive_number("12.3.4"));
static_assert(!is_positive_number("-123"));
static_assert(!is_positive_number("abc"));
//auto lambda = [](const char* number_string)
auto lambda = [](const std::string& number_string)
{
return is_positive_number(number_string);
};
auto is_ok = lambda("123");
assert(is_ok);
return 0;
}
Another way would be to use the open-source compile-time regex library:
#include <ctre.hpp>
constexpr bool is_positive_number(std::string_view const s) noexcept {
return static_cast<bool>(ctre::match<R"(\d+(?:\.\d+)?)">(s));
}
int main() {
static_assert(is_positive_number("1.2"));
static_assert(!is_positive_number("1..2"));
static_assert(!is_positive_number("1e2"));
}
See Online
This can be done with a straightforward scan of the text:
bool is_valid(const std::string& str) {
int dots = 0;
for (char c: str) {
if (c == '.')
++dots;
if (1 < dots || !std::isdigit(c))
return false;
}
return true;
}
Using std::regex produces a two-liner if you dont count the static pattern
#include <string>
#include <regex>
#include <cassert>
bool is_positive_number( const std::string& str ) {
static std::regex rx("^(\\+?)(0|([1-9][0-9]*))(\\.[0-9]*)?$"); // Getting the regex object
std::smatch match;
return std::regex_match(str,match,rx);
}
int main()
{
assert(is_positive_number("1"));
assert(is_positive_number("12"));
assert(is_positive_number("123"));
assert(is_positive_number("1."));
assert(is_positive_number("1.2"));
assert(is_positive_number("12.34"));
assert(is_positive_number("+12.34"));
assert(!is_positive_number("007"));
assert(!is_positive_number("123.23.23"));
assert(!is_positive_number("-123"));
assert(!is_positive_number("abc"));
return 0;
}
I don't think there is a built-in function that does exactly what you were looking for. There is std::stod that converts a string into a double and tells you how many characters were converted successfully. However, there are many non-conforming numbers that will work, such as -1, NAN, 10E+3.
One way you could do is first remove all numbers(0~9), then check against "" and ".":
constexpr bool is_num(std::string str)
{
std::erase_if(str, [](unsigned char c){ return std::isdigit(c);};
return str == "" || str == ".";
}
Note erase_if is from C++20, for pre-C++20, you would do:
constexpr bool is_num(std::string str)
{
str.erase(std::remove_if(str.begin(), str.end(),
[](unsigned char c){ return std::isdigit(c); }), str.end());
return str == "" || str == ".";
}
demo
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 months ago.
Improve this question
So I have an array with the following structure:
typedef struct {
int order_num;
string order_day; //Sort
string client;
string tech_type;
int serial_key;
long problem;
string technician_name;
string tech_fix;
int price;
int days_spent;
string status;
string order_type;
int problems_num;
faults problems[10];
}tech_info;
The customer provides data for the second field in format dd/mm/yyyy. I need to sort the array via that input. Here is what I have so far:
bool compare(const Date& d1, const Date& d2)
{
// All cases when true should be returned
if (d1.year < d2.year)
return true;
if (d1.year == d2.year && d1.month < d2.month)
return true;
if (d1.year == d2.year && d1.month == d2.month &&
d1.day < d2.day)
return true;
// If none of the above cases satisfy, return false
return false;
}
tech_info sort_date(tech_info* all_orders[]) {
vector<string> date;
string temp;
stringstream ss(temp);
for (int i = 0; i < counter; i++) {
temp = all_orders[i]->order_day;
while (ss.good()) { //Seperate date from '/' character
string substr;
getline(ss, substr, '/');
date.push_back(substr);
}
}
}
With this hopefully I'll be able to sort the date for every entry into a string. What would be the next step? How can I use this vector that holds the date information to sort the initial array?
Thank you.
To compare dates given as strings of the form dd/mm/yyyy you would first want to transform them into a range of the form {yyyy, mm, dd} and then compare this range lexicographically. In other words, you can solve your problem by first solving three subtasks:
You split your date string at / to obtain a range {dd, mm, yyyy}.
You reverse the words in the splitted range {yyyy, mm, dd}
You compare the splitted and reversed range lexicographically.
Here is a solution using C++20 and ranges:
#include <string>
#include <array>
#include <algorithm>
#include <vector>
#include <ranges>
#include <iostream>
struct tech_info {
std::string ordering_day;
// ... other stuff not relevant for question
};
auto split_and_reverse(std::string_view const& str)
{
return str | // example: 31/12/1999
std::views::reverse | // example: 9991/21/13
std::views::split('/') | // example: {9991, 21, 13}
std::views::transform(std::views::reverse) | // example: {1999, 12, 31}
std::views::transform([](auto&& rng){
return std::string_view{rng.begin(), rng.end()};
}); // converts inner ranges to string_views
};
void sort_by_ordering_day(auto&& rng)
{
std::ranges::sort(
rng,
std::ranges::lexicographical_compare,
[](auto const& ti) {
return split_and_reverse(ti.ordering_day);
}
);
};
int main() {
std::array<tech_info, 5> tech_infos {{
{ "31/12/1999" },
{ "25/11/1999" },
{ "31/12/2022" },
{ "13/12/2012" },
{ "01/01/1844" }
}};
sort_by_ordering_day(tech_infos);
for (auto const& ti : tech_infos){
std::cout << ti.ordering_day << std::endl;
}
}
Output:
01/01/1844
25/11/1999
31/12/1999
13/12/2012
31/12/2022
https://godbolt.org/z/n18Yd4bhe
You probably want to add some error checking to split_and_reverse if your input string conforms to your expected format. This alone justifies the creation of a dedicated Date class, or you use the ones provided by the standard library: https://en.cppreference.com/w/cpp/chrono/year_month_day. C++20 even comes with a function std::chrono::parse to parse instances of calendar classes from strings that offers error checking, but as of now not many compilers support it. Example: https://godbolt.org/z/3jnqfa373.
If you can't use C++20, I will leave solving the three subtasks as an exercise to you. You only really have to add bigger changes the split_and_reverse function:
sort_by_ordering_day uses std::ranges::sort which can be replaced by std::sort.
std::ranges::lexicographical_compare can be replaced by std::lexicographical_compare.
If you can't use C++17 you would also have to replace all occurances of std::string_view with std::string.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
I want to create a function to compare two strings in dictionary order so that I can sort the strings "aa", "AA", "Bb","bb" in the order "aa" < "AA" < "bb" < "Bb". How can I achieve this in C++?
You might do
auto compare_string = [](const auto& lhss, const auto& rhss){
return std::lexicographical_compare(
lhss.begin(), lhss.end(),
rhss.begin(), rhss.end(),
[](const auto& lhsc, const auto& rhsc){
auto proj = [](char c){ return std::tuple(std::tolower(c), std::isupper(c)); };
return proj(lhsc) < proj(rhsc);
}
);
});
Demo
Your desired way of sorting the string is not the one implemented by default by std::string. However, you can pass in your std::char_traits template parameter and customized the sorting.
https://en.cppreference.com/w/cpp/string/char_traits
Here a pretty old but still interesting discussion of the implementation of a case insensitive string: http://www.gotw.ca/gotw/029.htm
#include <string>
#include <string_view>
#include <iostream>
#include <cctype>
#include <cassert>
struct special_char_traits : public std::char_traits<char> {
static char to_upper(char ch) {
return std::toupper((unsigned char) ch);
}
static bool eq(char c1, char c2) {
return c1 == c2;
}
static bool lt(char c1, char c2) {
if (c1 == c2)
return false;
if (to_upper(c1) == to_upper(c2))
return !(c1 < c2);
return c1 < c2;
}
static int compare(const char* s1, const char* s2, std::size_t n) {
while ( n-- != 0 ) {
if ( lt(*s1,*s2)) return -1;
if ( !lt(*s1,*s2)) return 1;
++s1; ++s2;
}
return 0;
}
static const char* find(const char* s, std::size_t n, char a) {
while ( n-- != 0 )
{
if (*s == a)
return s;
s++;
}
return nullptr;
}
};
int main()
{
typedef std::basic_string<char,special_char_traits> ss;
//handle the case highligheted by Jarod42
assert(!special_char_traits::lt('a','a'));
assert(!special_char_traits::lt('A','A'));
assert(special_char_traits::lt('a','A'));
assert(!special_char_traits::lt('A','a'));
assert(!special_char_traits::lt('b','A'));
assert(special_char_traits::lt('A','b'));
std::cout << (std::string("AA") < std::string("aa")) << " " << (ss("AA") < ss("aa")) << std::endl;
}
STILL UNTESTED FOR SEVERAL CASES
The compare function is delegating the comparison of the single characters to the lt function provided above.
std::string a = "A";
std::string b = "B";
if(a < b)
// Do what you want.
std::string has the < operator overloaded and that is everything you need to sort them.
See also: Using the less than comparison operator for strings
just create a function which takes takes two strings as input. on the function creates STL set. Insert two strings.They are now sorted in dictionary order inside set.
The program I am writing reads a text file, breaks the paragraph into individual words, compares them to a list of "sensitive words" and if a word from the text file matches a word from the Sensitive word list, it is censored. I have wrote functions that find the beginning of each word, and a function that will censor or replace words on the Sensitive word list with "#####" (which I left out of this post). A word in this case is any string that contains alphanumeric characters.
The function I am having trouble with is the function that will "extract" or return the individual words to compare to the sensitive word list (extractWord). At the moment it just returns the first letter of the last word in the sentence. So right now all the function does is return "w". I need all the individual words.
Here is what I have so far ...
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
bool wordBeginsAt (const std::string& message, int pos);
bool isAlphanumeric (char c); //
std::string extractWord (const std::string& fromMessage, int beginningAt);
int main()
{
string word = "I need to break these words up individually. 12345 count as words";
string newWord;
for (int i = 0; i < word.length(); ++i)
{
if (wordBeginsAt(word, i))
{
newWord = extractWord(word, i);
}
}
//cout << newWord; // testing output
return 0;
}
bool wordBeginsAt (const std::string& message, int pos)
{
if(pos==0)
{return true;}
else
if (isAlphanumeric(message[pos])==true && isAlphanumeric(message[pos- 1])==false)
{
return true;
}
else
return false;
}
bool isAlphanumeric (char c)
{
return (c >= 'A' && c <= 'Z')
|| (c >= 'a' && c <= 'z')
|| (c >= '0' && c <= '9');
}
std::string extractWord (const std::string& fromMessage, int beginningAt)
{
string targetWord= "";
targetWord = targetWord + fromMessage[beginningAt];
return targetWord;
}
edit: after trying to use targetWord as an array (which I couldn't define the size) and using several different for and while loops within extractWord I found a solution:
std::string extractWord (const std::string& fromMessage, int beginningAt)
{
string targetWord= "";
while (isAlphanumeric(fromMessage[beginningAt++]))
{
targetWord = targetWord + fromMessage[beginningAt-1];
}
return targetWord;
Since this is a C++ question, how about using modern C++, instead of using dressed-up C code? The modern C++ library has all the algorithms and functions needed to implement all of this work for you:
#include <algorithm>
#include <cctype>
std::string paragraph;
// Somehow, figure out how to get your paragraph into this std::string, then:
auto b=paragraph.begin(), e=paragraph.end();
while (b != e)
{
// Find first alphanumeric character, using POSIX isalnum()
auto p=std::find_if(b, e, [](char c) { return isalnum(c); });
// Find the next non-alphanumeric chararacter
b=std::find_if(p, e, [](char c) { return !isalnum(c); });
if (isbadword(std::string(p, b)))
std::fill(p, b, '#');
}
This does pretty much what you asked, in a fraction of the size of all that manual code that manually searches this stuff. All you have to do is to figure out what...
bool isbadword(const std::string &s)
...needs to do.
Your homework assignment is how to slightly tweak this code to avoid, in certain specific situations, calling isbadword() with an empty string.
I'm looking for the most efficient (in terms of "fastest") way to replace all occurrences of a substring within a string with another string. All I've came up with so far is:
std::string StringReplaceAll(const std::string &cstSearch, const std::string &cstReplace, const std::string &cstSubject)
{
if(cstSearch.length() > cstSubject.length() || cstSearch == cstReplace || cstSubject.empty() || cstSearch.empty() || cstSubject.find(cstSearch) == std::string::npos)
{
return cstSubject;
}
std::ostringstream ossReturn;
std::string::const_iterator ci(cstSubject.cbegin());
const std::string::const_iterator::difference_type ciFindSize(std::distance(cstSearch.cbegin(), cstSearch.cend()));
for(std::string::const_iterator ciNow; (ciNow = std::search(ci, cstSubject.cend(), cstSearch.cbegin(), cstSearch.cend())) != cstSubject.cend(); ci = ciNow)
{
std::copy(ci, ciNow, std::ostreambuf_iterator<char> (ossReturn));
std::copy(cstReplace.cbegin(), cstReplace.cend(), std::ostreambuf_iterator<char> (ossReturn));
std::advance(ciNow, ciFindSize);
}
std::copy(ci, cstSubject.cend(), std::ostreambuf_iterator<char> (ossReturn));
return ossReturn.str();
}
... and this one is way(!!!) too slow for my needs :-(
Looking forward to learn from you guys!
First, I'd use std::string, rather than std::ostringstream, to build
up the results; std::ostringstream is for formatting, and there's no
formatting to be done here. Other than that, you've got basically the
correct algorithm; using std::search to find where the next
replacement should be done. I'd use a while loop to make things a bit
more readable, which gives:
std::string
replaceAll( std::string const& original,
std::string const& before,
std::string const& after )
{
std::string retval;
std::string::const_iterator end = original.end();
std::string::const_iterator current = original.begin();
std::string::const_iterator next =
std::search( current, end, before.begin(), before.end() );
while ( next != end ) {
retval.append( current, next );
retval.append( after );
current = next + before.size();
next = std::search( current, end, before.begin(), before.end() );
}
retval.append( current, next );
return retval;
}
(Note that using std::string::append will be faster than using
std::copy; the string knows how many it must add, and can resize the
string accordingly.)
Afterwards, it would be trivial to catch the special case where there is
nothing to replace, and return the initial string immediately; there
might be some improvements to be had using std::string::reserve as
well. (If before and after have the same length,
retval.reserve( original.size() ) is a clear win. Even if they don't,
it could be a win. As for first counting the number of substitutions, then
exactly calculating the final size, I don't know. You'll have to
measure with your actual use cases to find out.)
I asked about this same thing at http://hardforum.com/showthread.php?t=979477 years ago.
I don't remember it all that well, but the following code was in comment #31 and I think it was faster than my other attempts (but not faster than MikeBlas' metered_string example):
#include <iostream>
#include <string>
#include <algorithm>
#include <iterator>
#include <sstream>
using namespace std;
inline string replaceAll(const string& s, const string& f, const string& r) {
if (s.empty() || f.empty() || f == r || f.size() > s.size() || s.find(f) == string::npos) {
return s;
}
ostringstream build_it;
typedef string::const_iterator iter;
iter i(s.begin());
const iter::difference_type f_size(distance(f.begin(), f.end()));
for (iter pos; (pos = search(i , s.end(), f.begin(), f.end())) != s.end(); ) {
copy(i, pos, ostreambuf_iterator<char>(build_it));
copy(r.begin(), r.end(), ostreambuf_iterator<char>(build_it));
advance(pos, f_size);
i = pos;
}
copy(i, s.end(), ostreambuf_iterator<char>(build_it));
return build_it.str();
}
int main() {
const string source(20971520, 'a');
const string test(replaceAll(source, "a", "4"));
}
See the thread for more examples and lots of discussion.
If I remember correctly, it was really easy to make things faster than boost's replace_all.
Here's a clearer c++0x version:
#include <string>
#include <algorithm>
#include <iterator>
#include <sstream>
#include <ostream>
using namespace std;
string replace_all_copy(const string& s, const string& f, const string& r) {
if (s.empty() || f.empty() || f == r || f.size() > s.size()) {
return s;
}
ostringstream buffer;
auto start = s.cbegin();
while (true) {
const auto end = search(start , s.cend(), f.cbegin(), f.cend());
copy(start, end, ostreambuf_iterator<char>(buffer));
if (end == s.cend()) {
break;
}
copy(r.cbegin(), r.cend(), ostreambuf_iterator<char>(buffer));
start = end + f.size();
}
return buffer.str();
}
int main() {
const string s(20971520, 'a');
const string result = replace_all_copy(s, "a", "4");
}
// g++ -Wall -Wextra replace_all_copy.cc -o replace_all_copy -O3 -s -std=c++0x
I think std::search uses a trivial algorithm, at least the reference states the complexity of a naiive string matching algorithm. If you replace it by an implementation of Boyer-Moore, you should be able to see significant performances increases.
Apart from that you are heavily dependent on good compiler optimizations. By returning the string instead of passing a string* result, you cause unnecessary copying of the result. However, compilers may help you there. But just to be sure you can alos try passing a pointer to the result as argument and appending to that string. However, swapping std::search for an implementation of a non trivial algorithm (boyer-moore as mentioned above or knuth-morris-pratt) should have an impact that is larger by several orders of magnitude compared to fine-tuning the return mechanism.
Try this one.
template<class T> inline void Replace(T& str, const T& str1, const T& str2)
{
const T::size_type str2Size(str2.size());
const T::size_type str1Size(str1.size());
T::size_type n = 0;
while (T::npos != (n = str.find(str1, n))) {
str.replace(n, str1Size, str2);
n += str2Size;
}
}
std::string val(L"abcabcabc");
Replace(val, L"abc", L"d");
I found this one to be faster:
typedef std::string String;
String replaceStringAll(String str, const String& old, const String& new_s) {
if(!old.empty()){
size_t pos = str.find(old);
while ((pos = str.find(old, pos)) != String::npos) {
str=str.replace(pos, old.length(), new_s);
pos += new_s.length();
}
}
return str;
}
A comparison with James kanzes replaceAll function:
replaceAll : 28552
replaceStringAll: 33518
replaceAll : 64541
replaceStringAll: 14158
replaceAll : 20164
replaceStringAll: 13651
replaceAll : 11099
replaceStringAll: 5650
replaceAll : 23775
replaceStringAll: 10821
replaceAll : 10261
replaceStringAll: 5125
replaceAll : 10283
replaceStringAll: 5374
replaceAll : 9993
replaceStringAll: 5664
replaceAll : 10035
replaceStringAll: 5246
replaceAll : 8570
replaceStringAll: 4381
Times are calculated in nanoseconds with std::chrono::high_resolution_clock
I would propose an optimization step: make a preliminary pass to check if there is anything to replace at all. If there is nothing to replace, just return and avoid allocating memory and copying.
i tested 3 ways to replace substring
boost_replace_all
regex_replace_all
basic handmade string replace algorithm
void regex_replace_test(std::string &str) {
std::string res = std::regex_replace(str, std::regex(SUBSTRING), REPLACEABLE);
}
void boost_replace_all_test(std::string &str) {
boost::replace_all(str, SUBSTRING, REPLACEABLE);
}
void handmade_replace_test(std::string &str) {
size_t pos = 0;
while ((pos = str.find(SUBSTRING, pos)) != std::string::npos) {
str.replace(pos, SUBSTRING.length(), REPLACEABLE);
pos += REPLACEABLE.length();
}
}
input data info
test to replace SUBSTRING in BASE string.
BASE string length = 48004
SUBSTRING = fdkfgkd
SUBSTRING length = 7
SUBSTRING's quantity in BASE string= 4364
REPLACEABLE = ddddddd
REPLACEABLE length = 7
i got the following results:
regex_replace_test = 14 ms , 14921715 ns
boost_replace_all_test = 4 ms , 4167104 ns
handmade_replace_test = 0 ms , 372201 ns
fastest way is basic handmade substring replace method.
I'm very new to C++, boost etc.
I would like to know if there is already a function in boost or STL I can use to determine if a string is numeric.
Numeric strings may look like:
100
or
100.52
I know there are tons of examples how to write such a function but I would like to know if there is already a function I can use for this.
I'm looking for a pure C++-solution, not C.
[UPDATE:
I'm already using lexical_cast to convert my strings, I'm just wondering if there is a method like is_numeric I can use for this...]
No, there's not a ready-made way to do this directly.
You could use boost::lexical_cast<double>(your_string) or std::stod(your_string) and if it throws an exception then your string is not a double.
C++11:
bool is_a_number = false;
try
{
std::stod(your_string);
is_a_number = true;
}
catch(const std::exception &)
{
// if it throws, it's not a number.
}
Boost:
bool is_a_number = false;
try
{
lexical_cast<double>(your_string);
is_a_number = true;
}
catch(bad_lexical_cast &)
{
// if it throws, it's not a number.
}
boost::regex (or std::regex, if you have C++0x) can be used;
you can defined what you want to accept (e.g. in your context,
is "0x12E" a number or not?). For C++ integers:
"\\s*[+-]?([1-9][0-9]*|0[0-7]*|0[xX][0-9a-fA-F]+)"
For C++ floating point:
"\\s*[+-]?([0-9]+\\.[0-9]*([Ee][+-]?[0-9]+)?|\\.[0-9]+([Ee][+-]?[0-9]+)?|[0-9]+[Ee][+-]?[0-9]+)"
But depending on what you're doing, you might not need to
support things that complex. The two examples you cite would be
covered by
"[0-9]+(\\.[0-9]*)?"
for example.
If you're going to need the numeric value later, it may also be
just as easy to convert the string into an istringstream, and
do the convertion immediately. If there's no error, and you
extract all of the characters, the string was a number; if not,
it wasn't. This will give you less control over the exact
format you want to accept, however.
If performance is a concern at all, I would use boost.spirit.qi rather than std::stringstream:
#include <string>
#include <boost/spirit/include/qi_parse.hpp>
#include <boost/spirit/include/qi_numeric.hpp>
bool is_numeric(std::string const& str)
{
std::string::const_iterator first(str.begin()), last(str.end());
return boost::spirit::qi::parse(first, last, boost::spirit::double_)
&& first == last;
}
If you want to allow trailing whitespace then do the following instead:
#include <string>
#include <boost/spirit/include/qi_parse.hpp>
#include <boost/spirit/include/qi_numeric.hpp>
#include <boost/spirit/include/qi_char_class.hpp>
#include <boost/spirit/include/qi_operator.hpp>
bool is_numeric(std::string const& str)
{
std::string::const_iterator first(str.begin()), last(str.end());
return boost::spirit::qi::parse(first, last,
boost::spirit::double_ >> *boost::spirit::qi::space)
&& first == last;
}
Use a stringstream and return true if the convertion "ate" all the characters in the original string (=eof()).
bool is_numeric(const std::string& str) {
std::stringstream conv;
double tmp;
conv << str;
conv >> tmp;
return conv.eof();
}
bool is_numeric(std::string number)
{
char* end = 0;
std::strtod(number.c_str(), &end);
return end != 0 && *end == 0;
}
bool is_integer(std::string number)
{
return is_numeric(number.c_str()) && std::strchr(number.c_str(), '.') == 0;
}
Source
The following code
The following sentense, return true if "str" is composed of 0~9 only, otherwise, return false.
return str.find_first_not_of("0123456789") == std::string::npos
You could try a lexical_cast on the string.
From C++11, you can simply use one of std::stof, std::stod, std::stold for converting to float, double and long double, respectively. They convert a string to the numerical value or throw an exception, if there's a problem (see the reference). Here is an example with std::stod:
bool isNumeric(const std::string& str) {
try {
std::stod(str); // can safely ignore the return value, function is not [[nodiscard]]
return true;
}
catch (const std::exception&) {
return false;
}
}
Also have a look at the functions to convert a string to signed and unsigned integers.
There is no boost needed, only stl ...
A single char could be checked as an int (c >= '0' && c <= '9'), find_if_not will find the first char not matching the condition between [first] and [last]. If no match was found, it will return [last].
If additional chars like space,.- should be checked, add them.
#include <string>
#include <algorithm>
bool isNumeric(std::string strValue)
{
if (strValue.empty())
return false;
else
return (std::find_if_not( std::begin(strValue)
, std::end(strValue)
, [](char c)
{ return (c >= '0' && c <= '9'); }
) == std::end(strValue)
);
}
P.S.
#Jian Hu is an empty string numeric ?