4

Recently I have need to extract a number from a string, but on really old C with means functions like strtok are not supported. I would prefer sscanf, but i can't understand it. Note that the integer is in random place (user-defined).

In general thats what i want to happan as an example:

Input: char * string = "He is 16 years old."; Output: 16 
4

4 Answers 4

3

A combination of digit filtering and sscanf() should work.

int GetNumber(const char *str) { while (!(*str >= '0' && *str <= '9') && (*str != '-') && (*str != '+') && *str) str++; int number; if (sscanf(str, "%d", &number) == 1) { return number; } // No int found return -1; } 

Additional work needed for numbers that overflow.

A slower, but pedantic method follows

int GetNumber2(const char *str) { while (*str) { int number; if (sscanf(str, "%d", &number) == 1) { return number; } str++; } // No int found return -1; } 
Sign up to request clarification or add additional context in comments.

10 Comments

Actually i've been trying proceed and finally made str to int function: int strtoint(char source[]) { int multiplier = 1; int i, result; for (i=strlen(source)-1; i>=0; i--) { if(source[i] >= '0' && source[i] <= '9') { result = result + ((source[i]-'0') * multiplier); multiplier *= 10; } } return result; }
@Lively Could go in the forward direction. { size_t i; int result = 0; for (i=0; source[i]; i++) { if(source[i] >= '0' && source[i] <= '9') { result = result*10 + source[i] - '0'; }
@JasonC isdigit(*str) is UB when *str < 0. (*str >= '0' && *str <= '9') does not have that problem. An alternative is to use isdigit((unsigned char) *str) which handles most other cases.
@JasonC C specifies '0' through '9' as sequential, so (*str >= '0' && *str <= '9') is good, ASCII or not as is '0' + value. static_cast<unsigned char>(*str) is a compiler error in C as this post is tagged. I suspect you are thinking of some other language.
@JasonC Ref: "In both the source and execution basic character sets, the value of each character after 0 in the above list of decimal digits shall be one greater than the value of the previous." C17dr § 5.2.1 3
|
2

scanf tries to match a pattern.... so if you knew the string was "He is 16 years old." where 16 was an integer number you wished to decode.

( I think your input string implies your format is somewhat free form. I'm assuming its predictable. )

{ char* inputstr = "He is 16 years old."; int answer = 0; int params = sscanf (inputstr, "He is %d years old.", &answer); if (params==1) printf ("it worked %d",answer); else printf ("It failed"); } 

3 Comments

With sscanf this is as far as you could get Lively (OP). If you are to acquire some other non-standard input, anything else than "He is x years old.", sscanf won't do it.
The string given is like example. Basically the user will just write random string with integer somewhere in it.. And the function has to output those integers. Is it even possible.. i just saw similar questions with sscanf as an answer, but not explanation how sscanf could be used.
Usually input strings conform to some agreed syntax. If it is totally free form then I would write a routine to split the input string between white space into an array of smaller strings. Then step through the array calling scanf on each. The Params value returns how many %d in out example decoded to a int (a maximum of one) in our example.
1

For starters, you should know that the strtok function is pretty ancient as well. It's in the C89 standard, but probably existed in many implementations before that (for example in 4.3BSD which was released in 1986). In fact, the sscanf function is probably newer than the strtok function.

But if you have such an ancient compiler that, and actually don't have the strtok function, and your input string doesn't follow the exact format you have in the question, but can be more free-form (and so can't really use the pattern-matching functionality of sscanf) then you have to parse the string manually.

This manual parsing can actually be quite simple, just loop over the string until you find a digit, then collect all consecutive digits while constructing the number. Once you get a non-digit character, you have your number. Of course, this will only get the first number in the string.

3 Comments

The compiler is even more then ancient.. strtok is not supported and even God do not know why. You mean convert the string in array and set compare if the first char is 0-10 then return it.. if not skip to the next?
@Lively Oh my, I feel really sorry for you then! But yeah, that's the gist of it.
Well hehe @Joachim i gotta get used doing this. Seems i will create a compare input-output function by myself. Thanks.
1
#include <stdio.h> int main() { char * string = "He is 16 years old."; int age; if(sscanf(string, "%*[^0123456789]%d", &age)==1) printf("%d\n", age); else printf("not found\n"); return 0; } 

1 Comment

Fails corner case when string begins with am int like `"123abc".

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.