8

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!

2
  • 1
    hello doesn't match %d . You need to find a way to skip up to the beginning of your integer before applying %d. The strchr function could be one way. Also you forgot & before address. Commented Nov 23, 2015 at 5:06
  • Can't you use standard parsing techniques to construct some AST or embed some existing interpreter (like Guile or Lua...)? Commented Nov 23, 2015 at 6:13

4 Answers 4

9

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;
Sign up to request clarification or add additional context in comments.

2 Comments

+1 didn't saw the last edit. answer the same thing. anyway, what should be returned if the string is data(5. Your code seems like 5. even though not inside the parenthesis.
@silentboy The simplified code takes advantage of OP's "When a string contains an integer, it will always be in between parentheses." so (5 does not occur.
2

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;

Comments

2

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;
    .
    .
    .
}

Comments

0

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

3 Comments

note: this will fail if there are no characters before the integer, because %[ must always match at least one character
the behaviour of - with %[ is implementation-defined ; various compilers may or may not support this. (But you could use ^0123456789).
This will convert "-123" into 123. if will convert "123" into undefined value.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.