J. Shephard
J. Shephard

Reputation: 93

Using sscanf to extract an int from a string in C++

My function must process strings that look like say hello y(5) or data |x(3)|, and I need to be able to extract the integer shown and store it into a separate int variable called address. However, some strings passing through will not have any integers, and for these the address must default to 0. When a string contains an integer, it will always be in between parentheses. I've attempted to use sscanf, but, being very new to sscanf, I'm encountering problems.. For some reason, the address always reads as 0. Here's my code:

void process(string info)
{
int address = 0; // set to 0 in case info contains no digits
sscanf(info.c_str(), "%d", address);
.
.
.
// remainder of code makes other function calls using the address, etc
}

Any ideas as to why the sscanf fails to find the integer in between parentheses? Thanks!

Upvotes: 8

Views: 14309

Answers (4)

Shakil Ahamed
Shakil Ahamed

Reputation: 577

When a string contains an integer, it will always be in between parentheses

To strictly conform with this requirement you can try:

void process(string info)
{
    int address;
    char c = '5'; //any value other than ) should work

    sscanf(info.c_str(), "%*[^(](%d%c", &address, &c);
    if(c != ')') address = 0;
    .
    .
    .
}

Upvotes: 2

chux
chux

Reputation: 153457

why the sscanf fails to find the integer in between parentheses

The "%d" in sscanf(info.c_str(), "%d", address) will cause sscanf() to stop scanning once a non-numeric sequence detected. Text like "(5)" will simply stop scanning at the "(".

Instead code need to to skip over non-numeric text.


Pseudo-code

  in a loop
    search for any of "-+0123456789"
    if not found return 0
    convert from that point using sscanf() or strtol()
    if that succeeds, return number
    else advance to next character

Sample code

int address;
const char *p = info.c_str();
for (;;) {
  p += strcspn(p, "0123456789+-");
  if (*p == 0) return 0;
  if (sscanf(p, "%d", &address) == 1) {
    return address;
  }
  p++;
}

Notes:

The strcspn function computes the length of the maximum initial segment of the string pointed to by s1 which consists entirely of characters not from the string pointed to by s2. C11 7.24.5.3 2


If code wants to rely on " it will always be in between parentheses." and input like "abc()def(123)" does not occur which has preceding non-numeric data between ().:

const char *p = info.c_str();
int address;
if (sscanf(p, "%*[^(](%d", &address)==1) {
  return address;
}
return 0;

or simply

int address = 0;
sscanf(info.c_str(), "%*[^(](%d", &address);
return address;

Upvotes: 9

AndersK
AndersK

Reputation: 36082

You could use something as simple as this where strchr finds the first occurrence of "(" then use atoi to return the integer which will stop at the first non-digit.

  char s1[] = "hello y(5)";
  char s2[] = "data [x(3)]";
  char s3[] = "hello";

  int a1 = 0;
  int a2 = 0;
  int a3 = 0;

  char* tok = strchr( s1, '(');
  if (tok != NULL)
    a1 = atoi(tok+1);

  tok = strchr( s2, '(');
  if (tok != NULL)
    a2 = atoi(tok+1);

  tok = strchr(s3,'(');
  if (tok != NULL)
    a3 = atoi(tok+1);

  printf( "a1=%d, a2=%d, a3=%d", a1,a2,a3);

  return 0;

Upvotes: 2

William Ku
William Ku

Reputation: 798

link to a solution

int address;

sscanf(info.c_str(), "%*[^0-9]%d", &address);
printf("%d", address);

this should extract the integer between the parenthesis

Upvotes: 0

Related Questions