百分号作为fscanf中的格式分隔符

时间:2016-04-22 15:56:34

标签: c delimiter scanf

我正在处理这段代码,该代码读取带有由百分号(%)分隔的记录的文件,然后将值保存在节点结构中。输入如下:

2%C1%D3%33445.000000%2016%4%11
1%C2%D2%234.500000%2016%4%11
0%C1%D1%123.400000%2016%4%11

每一行都是一个包含由百分号分隔的数据的节点。我使用fscanf读取格式化的输入并将值保存在特定的变量中。如果分隔符是任何字符但是'%'。

,它的效果很好

我尝试通过做' %%'来逃避百分号。但它不会起作用,而fscanf会返回-1。我到处寻找一种方法,但却无法找到任何东西。任何帮助将不胜感激。以下是代码摘录。

int recordID;
char category[255];
char detail[255];
float amount;
int year;
int month;
int day;

while(fscanf(pFile, "%d%%%s%%%s%%%f%%%d%%%d%%%d", &recordID, category, detail, &amount, &year, &month, &day) == 7) {

    struct node* p = (struct node*) malloc(sizeof(struct node));

    p->recordID = recordID;
    copy_array(category, p->category, 255);
    copy_array(detail, p->detail, 255);
    p->amount = amount;
    p->year = year;
    p->month = month;
    p->day = day;

    add_node(p);
}

pFile是包含上面指定的输入的文件。

谢谢!

2 个答案:

答案 0 :(得分:1)

问题是%s读取了一个字符串,并且你没有告诉它停在分隔符处,所以它吞噬了%以及它之后的所有内容。使用%[^%]代替%s:

fscanf(pFile, "%d%%%[^%]%%%[^%]%%%f%%%d%%%d%%%d", ...

如果您从未见过scanf说明符%[,则其工作原理如下:%[abc]会扫描a,b&s和c&#39的任意组合; S。 %[^abc]会扫描包含a,b或c的任何字符串 。您还可以使用范围,例如%[0-9]。否则,它大部分都像%s,写入char *目的地缓冲区。

(顺便说一下,任何选择%作为分隔符的人都应该被拍摄。我将所有%改为|' s你的代码和你的数据文件,所以我可以调试它而不会失去理智,然后在我开始工作之后,我将它们全部更改回%。)

附录:John Bollinger绝对正确,你需要担心缓冲区溢出,正如他的解决方案所示。

答案 1 :(得分:0)

function deployTask(grunt) { var deployPath = (this.args[0] === 'prod') ? 'myApp' : 'myApp_rc'; grunt.option('deployPath', deployPath); grunt.task.run('ftp-deploy'); } grunt.registerTask('deploy', deployTask); 没有按照您希望的方式进行模式匹配。特别是,[f]scanf()字段描述符匹配空格分隔的字符串,而您需要匹配由%s字符分隔的字符串。如果您已经检查了实际的'%'返回值,那么您可能已经对此有了一些线索(但至少将它与您预期的值进行比较,这对您有好处。)。

您可以通过scanf()字段描述符匹配给定集合中的字符串,如@SteveSummit在其答案中所述。此外,最好以格式指定最大字段宽度,以避免超出数组的范围。对于您正在扫描的格式,这将特别有效,因为您的任一字符串的超长输入字段将导致与后续分隔符匹配失败:

%[