Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

sscanf & newlines

Tags:

c

newline

eof

scanf

I need to parse a response from a server like this:

risposta:

200\n
Len 1040\n
Expire 30\n
\n
1111111111111111111111111\n
1111111111111111111111111\n
1111111111111111111111111\n

I'm trying with sscanf:

sscanf(risposta, "%d\nLen %d\nExpire %d\n\n%s[^\0]", &risp->type, &risp->len, &risp->expire, risp->risorsa);

but it puts only 1111111111111111111111111 in risp->risorsa. How to resolve?

P.s. struct risp:

typedef struct Server_risp {
   int type;
   int expire;
   int len;
   int sup;
   int inf;
   char risorsa[5000];
 }Server_risp;
like image 703
Gorgo Avatar asked Apr 07 '12 14:04

Gorgo


1 Answers

A scanset specification is not %s[whatever], it's just %[whatever], so your format string should be more like: "%d\nLen %d\nExpire %d\n\n%[^\0]".

As a side note, scanf and friend consider any white space in a format string is equivalent to any other whitespace -- any whitespace in the format matches an arbitrary sequence of whitespace characters in the input (and a new-line is considered whitespace). Your current format string does a nice job of documenting the format you expect, but from a viewpoint of what it really matches, you can change it to something like: "%d Len %d Expire %d %[^\0]" without affecting what it'll do. In particular, your two consecutive new-lines aren't really accomplishing much.

Edit: Thinking about it, the [\0] causes just a bit of a problem: the "\0" terminates the string, so you end up with an invalid scan-set specification. Since you just want the rest of the input to go into risorsa, it's probably easiest to use %c: "%d Len %d Expire %d %4999c".

And yes, this time I actually tested it:

#include <stdio.h>

char *riposta = "200\n"
    "Len 1040\nExpire 30\n"
    "\n1111111111111111111111111\n"
    "1111111111111111111111111\n"
    "1111111111111111111111111\n";

typedef struct Server_risp {
    int type;
    int expire;
    int len;
    int sup;
    int inf;
    char risorsa[5000];
}Server_risp;

int main() {
    Server_risp risp;
   sscanf(riposta, "%d Len %d Expire %d %4999c", &risp.type, &risp.len, &risp.expire, risp.risorsa);

   printf("%s\n", risp.risorsa);
}

result:

1111111111111111111111111
1111111111111111111111111
1111111111111111111111111

Edit 2: I'm not sure exactly what problem you're running into here. I modified it a bit to show reading both leading and embedded white-space:

#include <stdio.h>

char *riposta = "200\n"
"Len 1040\nExpire 30\n"
"|        |"
"\n1111111111111111111111111\n"
"1111111111111111111111111\n"
"1111111111111111111111111\n";

typedef struct Server_risp {
    int type;
    int expire;
    int len;
    int sup;
    int inf;
    char risorsa[5000];
}Server_risp;

int main() {
    Server_risp risp;
    sscanf(riposta, "%d Len %d Expire %d%4999c", &risp.type, &risp.len, &risp.expire, risp.risorsa);

    printf("%s\n", risp.risorsa);
}

...and got pretty much the expected result:

|        |
1111111111111111111111111
1111111111111111111111111
1111111111111111111111111
like image 172
Jerry Coffin Avatar answered Oct 15 '22 03:10

Jerry Coffin