Ricibob
Ricibob

Reputation: 7705

Particular sscanf usage

Im using sscanf to read/parse a 3 char string into an int as:

char strId[4] = "123";
int i;
int count = sscanf(strId, "%i" &i); 

Im testing count==1 to check if the parse suceeds or fails.
"123" suceeds correctly - I want to consider this a number.
"aaa" fails correctly - I don't want to consider this a number.
but
"2aa" suceeds (count==1, i==2)- but I would like to identify this as a failure as I don't want to consider this a number.
How to simply parse strId to meet the above conditions?

Upvotes: 1

Views: 201

Answers (4)

chux
chux

Reputation: 153303

A sscanf() approach, use "%n".

"%n" saves the location where scanning stopped.

char strId[4] = "123";
int n = 0
sscanf(strId, "%i %n" &i, &n);
if (n == 0 || strId[n] != '\0') Handle_ProblemInput(strId);

This will pass: "123", " 123", "123 ".
And fail: "123a", "", " abc".
May/may not detect int overflow "12345678901234567890".


[Edit]

What is nice about the "%n" is that it can be used with complicated formats and with formats that otherwise end with fixed text. IOWs, simply detect if the scan made it all the way to '\0'?

int n = 0;
sscanf(buf, " %i %f %7s ,,, %c blah foo %n", ...);
if (n == 0 || buf[n] != '\0') Handle_ProblemInput(buf);

Upvotes: 2

AnthonyLambert
AnthonyLambert

Reputation: 8830

char str[255];
int count = sscanf((const char*)strId, "%i%254s", &i, str); 

if it comes back with count == 1 it is okay?

Upvotes: 0

Iharob Al Asimi
Iharob Al Asimi

Reputation: 53006

With strtol that's an easy task just do this

#include <stdio.h>
#include <stdlib.h>

char  string[] = "123xyz";
char *endptr;
int   value;

value = strtol(string, &endptr, 10);
if ((*string != '\0') && (*endptr == '\0'))
    printf("%s is a number and has no unconvertible characters", string);
/* and now 'value' contains the integer value. */

If you want to use sscanf() then this should do it too

#include <stdio.h>
#include <string.h>

char  string[] = "123";
int   count;
int   value;
int   length;

length = strlen(string);
if ((sscanf(string, "%d%n", &value, &count) == 1) && (count == length))
    printf("%s is a number and has no unconvertible characters", string);
/* and now 'value' contains the integer value. */

Upvotes: 1

emvee
emvee

Reputation: 4449

Use strtol(3). It allows specification of an "end-of-parsing" pointer (endptr below). After the conversion has finished you can check wether or not it points at the end of string. If it doesn't, there were non-number characters left in the input.

long strtol(const char *restrict str, char **restrict endptr, int base);

From man strtol:

If endptr is not NULL, strtol() stores the address of the first invalid character in *endptr. If there were no digits at all, however, strtol() stores the original value of str in *endptr. (Thus, if *str is not '\0' but **endptr is '\0' on return, the entire string was valid.)

Upvotes: 2

Related Questions