if you know for sure that there are only going to be 2 places where you have a list of digits in your string and that is the only thing you are going to pull out then you should be able to simply use
\d+
Answer from Seattle Leonard on Stack Overflowif you know for sure that there are only going to be 2 places where you have a list of digits in your string and that is the only thing you are going to pull out then you should be able to simply use
\d+
^\s*(\w+)\s*\(\s*(\d+)\D+(\d+)\D+\)\s*$
should work. After the match, backreference 1 will contain the month, backreference 2 will contain the first number and backreference 3 the second number.
Explanation:
^ # start of string
\s* # optional whitespace
(\w+) # one or more alphanumeric characters, capture the match
\s* # optional whitespace
\( # a (
\s* # optional whitespace
(\d+) # a number, capture the match
\D+ # one or more non-digits
(\d+) # a number, capture the match
\D+ # one or more non-digits
\) # a )
\s* # optional whitespace
$ # end of string
C++ Extract number from the middle of a string - Stack Overflow
c - Extracting numbers from the string using regex - Stack Overflow
Newest Questions - Stack Overflow
regex - Extract number from string using regular expressions [multiple formatting options] - Stack Overflow
You can also use the built in find_first_of and find_first_not_of to find the first "numberstring" in any string.
std::string first_numberstring(std::string const & str)
{
char const* digits = "0123456789";
std::size_t const n = str.find_first_of(digits);
if (n != std::string::npos)
{
std::size_t const m = str.find_first_not_of(digits, n);
return str.substr(n, m != std::string::npos ? m-n : m);
}
return std::string();
}
This should be more efficient than Ashot Khachatryan's solution. Note the use of '_' and '-' instead of "_" and "-". And also, the starting position of the search for '-'.
inline std::string mid_num_str(const std::string& s) {
std::string::size_type p = s.find('_');
std::string::size_type pp = s.find('-', p + 2);
return s.substr(p + 1, pp - p - 1);
}
If you need a number instead of a string, like what Alexandr Lapenkov's solution has done, you may also want to try the following:
inline long mid_num(const std::string& s) {
return std::strtol(&s[s.find('_') + 1], nullptr, 10);
}
match[0] refers to the part of the text matched by the entire pattern. match[1] is the match corresponding to the first capture (parenthesized subpattern).
Note that &s[match[1].rm_so] gives you a pointer to the start of the capture, but if you print the string at that point, you will get the part of the string starting at the beginning of the capture. In this case, that doesn't really matter. Since you're using sscanf to extract the integer value of the captured text, the fact that the substring isn't terminated immediately doesn't matter; it's not going to be followed by a digit, and sscanf will stop at the first non-digit.
But in the general case, it's possible that it will not be so easy to identify the end of the matched capture, and you can use one of these techniques:
If you want to print the capture, you can use a computed string width format: (See Note 1.)
printf("%.*s\n", match[1].rm_eo - match[1].rm_so, &s[match[1].rm_so]);
If you have strndup, you can easily create a dynamically-allocated copy of the capture: (See Note 2.)
char* capture = strndup(&s[match[1].rm_so], match[1].rm_eo - match[1].rm_so);
As a quick-and-dirty hack, it is also possible to just insert a NUL terminator (assuming that the searched string is not immutable, which means that it cannot be a string literal). You'll probably want to save the old value of the following character so that you can restore the string to it's original state:
char* capture = &s[match[1].rm_so];
char* rest = &s[match[1].rm_eo];
char saved_char = *rest;
*rest = 0;
/* capture now points to a NUL-terminated string. */
/* ... */
/* restore s */
*rest = saved_char;
None of the above is really necessary in the context of the original question, since the sscanf as written will work perfectly if you change the start of the string to scan from match[0] to match[1].
Notes:
In the general case, you should test to make sure that a capture was actually found before trying to use its offset. The
rm_somember will be -1 if the capture was not found during the regex search That doesn't necessarily mean that the search failed, because the capture could be part of an alternative not used in the match.Don't forget to free the copy when you no longer need it. If you don't have
strndup, it's pretty easy to implement. But watch out for the corner cases.
Since you are using sscanf(), there is no need to use a regex. You can parse the two numbers from your string using sscanf() alone using the format string: "%*[^0-9]%d%*[^0-9]%d" where "%*[^0-9]" uses the assignment suppression '*' to read and discard all non-digit characters and then uses "%d" to extract the integer value. The full format-string just repeats those two patterns twice.
A short example using your input could be:
#include <stdio.h>
int main (void) {
char *s = "/ab/cd__my__sep__4__some__sep__3";
int a, b;
if (sscanf (s, "%*[^0-9]%d%*[^0-9]%d", &a, &b) == 2)
printf ("a: %d\nb: %d\n", a, b);
else {
fputs ("error: parse of integers failed.\n", stderr);
return 1;
}
}
Example Use/Output
$ ./bin/parse2ints
a: 4
b: 3
If you find yourself attempting to parse something that sscanf() cannot handle, then a regex is appropriate. Here, sscanf() is more than capable of handling your needs alone.
Hi I am new to Python but am working on a project where I want to extract numbers from a string. For example I have the string "CORSAIR VENGEANCE RGB 16GB (2X8GB) DDR4 3200MHZ CL 16" where I want to extract the "16" from "16GB" as well as the "2" and "8" in "(2x8GB)" and "3200" from "3200MHZ".
What is the best way to do this? Thanks in advance!
Edit: Thanks everyone for the help! Regex seems to help do the trick
You can do it with strtol, like this:
char *str = "ab234cid*(s349*(20kd", *p = str;
while (*p) { // While there are more characters to process...
if ( isdigit(*p) || ( (*p=='-'||*p=='+') && isdigit(*(p+1)) )) {
// Found a number
long val = strtol(p, &p, 10); // Read number
printf("%ld\n", val); // and print it.
} else {
// Otherwise, move on to the next character.
p++;
}
}
Link to ideone.
A possible solution using sscanf() and scan sets:
const char* s = "ab234cid*(s349*(20kd";
int i1, i2, i3;
if (3 == sscanf(s,
"%*[^0123456789]%d%*[^0123456789]%d%*[^0123456789]%d",
&i1,
&i2,
&i3))
{
printf("%d %d %d\n", i1, i2, i3);
}
where %*[^0123456789] means ignore input until a digit is found. See demo at http://ideone.com/2hB4UW .
Or, if the number of numbers is unknown you can use %n specifier to record the last position read in the buffer:
const char* s = "ab234cid*(s349*(20kd";
int total_n = 0;
int n;
int i;
while (1 == sscanf(s + total_n, "%*[^0123456789]%d%n", &i, &n))
{
total_n += n;
printf("%d\n", i);
}
You need to call matcher.find() recursively until it returns false. Use a do/while block.
String str = '123-456/7890';
Pattern p = Pattern.compile('(\\d+)');
Matcher m = p.matcher( str );
if(m.find()) {
do {
system.debug( '-->>' + m.group() );
} while(m.find());
}
If you want to separate all the numbers into separate strings you can do the following.
String numsplit = str.replaceAll('[^0-9]+', ';');
list<String> nums = numsplit.split(';');
If you also want to extract the other characters there is a built-in splitbycharactertype method.