sscanf&换行符

时间:2012-04-07 14:05:01

标签: c newline eof scanf

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

risposta:

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

但它只在risp-> risorsa中放入1111111111111111111111111。 怎么解决?

P.S。 struct risp:

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

3 个答案:

答案 0 :(得分:7)

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

作为旁注,scanf和朋友认为格式字符串中的任何空格都等同于任何其他空格 - 格式中的任何空格都与输入中的任意空白字符序列相匹配(并且是新的-line被认为是空格)。您当前的格式字符串可以很好地记录您期望的格式,但从它真正匹配的角度来看,您可以将其更改为:"%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

答案 1 :(得分: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);

也许这就是你想要做的第一件事。

答案 2 :(得分:-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无法处理它。