I'd like to test a std::string
for containing numbers of any range e.g 5 to 35
in a std::string s = "XDGHYH20YFYFFY"
would there be function or I would have to convert a number to string and then use a loop to find each one?
views:
112answers:
5As much as some people are going to immediately go to regex on this, I think your best bet is actually a hybrid solution. Use REGEX to find numbers, then parse them and see if they're in range.
Something like this in C#. Not sure what regex libraries are available to you in C++.
using System.Text.RegularExpressions.Regex;
using System.Text.RegularExpressions.Match;
using System.Text.RegularExpressions.MatchCollection;
private static const Regex NUMBER_REGEX = new Regex(@"\d+")
public static bool ContainsNumberInRange(string str, int min, int max)
{
MatchCollection matches = NUMBER_REGEX.Matches(str);
foreach(Match match in matches)
{
int value = Convert.ToInt32(match.Value);
if (value >= min && value <= max)
return true;
}
return false;
}
I'd probably use a locale that treated everything except digits as white-space, and read the numbers from a stringstream imbued with that locale and check if they're in range:
#include <iostream>
#include <algorithm>
#include <locale>
#include <vector>
#include <sstream>
struct digits_only: std::ctype<char>
{
digits_only(): std::ctype<char>(get_table()) {}
static std::ctype_base::mask const* get_table()
{
static std::vector<std::ctype_base::mask>
rc(std::ctype<char>::table_size,std::ctype_base::space);
std::fill(&rc['0'], &rc['9'], std::ctype_base::digit);
return &rc[0];
}
};
bool in_range(int lower, int upper, std::string const &input) {
std::istringstream buffer(input);
buffer.imbue(std::locale(std::locale(), new digits_only()));
int n;
while (buffer>>n)
if (n < lower || upper < n)
return false;
return true;
}
int main() {
std::cout << std::boolalpha << in_range(5, 35, "XDGHYH20YFYFFY");
return 0;
}
If you are searching for all of the numbers in the range then use string::find function in a loop. Here is the reference for the function:
http://www.cplusplus.com/reference/string/string/find/
Also do you want to use the numbers in the string only once? For example SDFSD256fdsfs will give you the numbers 2 5 6 25 56 256 if you don't remove them from the string after each match.
Are you allowed to have multiple numbers in one string? If so, this solution won't work.
val.erase( remove_if( val.begin(), val.end(), ptr_fun( isalpha ) ) );
which should give you a string containing just the numbers.
You can do this iteratively with a stringstream
object.
#include <iostream>
#include <string>
#include <sstream>
#include <cctype>
void check (std::string& s) {
std::stringstream ss(s);
std::cout << "Searching string: " << s << std::endl;
while (ss) {
while (ss && !isdigit(ss.peek ()))
ss.get ();
if (! ss)
break;
int i = 0;
ss >> i;
std::cout << " Extraced value: " << i << std::endl;
}
}
int main () {
std::string s1 = "XDGHYH20YFYFFY";
std::string s2 = "20YF35YFFY100";
check (s1);
check (s2);
return 0;
}
Yields:
Searching string: XDGHYH20YFYFFY
Extraced value: 20
Searching string: 20YF35YFFY100
Extraced value: 20
Extraced value: 35
Extraced value: 100
Adding parameters to the check
function to limit the results accepted would be trivial.