10

我需要像这样解析来自服务器的响应:

意大利饭:

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

我正在尝试使用 sscanf:

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

但它只将 1111111111111111111111111 放在 risp->risorsa 中。如何解决?

ps 结构 risp:

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

3 回答 3

7

扫描集规范不是%s[whatever],它只是%[whatever],所以你的格式字符串应该更像:"%d\nLen %d\nExpire %d\n\n%[^\0]"

作为旁注,scanf朋友认为格式字符串中的任何空格都等效于任何其他空格——格式中的任何空格都匹配输入中的任意空格字符序列(并且换行符被认为是空格)。您当前的格式字符串很好地记录了您期望的格式,但从它真正匹配的角度来看,您可以将其更改为:"%d Len %d Expire %d %[^\0]"而不影响它将做什么。特别是,您连续的两条换行符并没有真正取得太大成就。

编辑:考虑一下,[\0]原因只是有点问题:“\ 0”终止了字符串,因此您最终得到了无效的扫描集规范。由于您只希望输入的其余部分进入risorsa,因此使用它可能是最简单的%c: "%d Len %d Expire %d %4999c"

是的,这次我实际测试了它:

#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);
}

结果:

1111111111111111111111111
1111111111111111111111111
1111111111111111111111111

编辑2:我不确定您在这里遇到了什么问题。我对其进行了一些修改以显示读取前导和嵌入的空白:

#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);
}

...并得到了几乎预期的结果:

|        |
1111111111111111111111111
1111111111111111111111111
1111111111111111111111111
于 2012-04-07T14:19:41.353 回答
0

我想指出解决问题的方法:

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

代码中的问题是 '\0' 在右括号 ']' 之前终止字符串。你可以使用'\1'。然后,字符串不会被提前终止,sscanf 将继续扫描,直到用完字符串。

更正后的代码是:

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

也许这就是你一开始想做的事情。

于 2015-01-29T00:57:45.333 回答
-1

以下代码存在一些问题:

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

它应该是:

char tmp_str[100]; 

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

您应该处理字符串“Len”和“Expire”,而 sscanf 无法处理。

于 2012-04-07T14:12:08.150 回答