读取fscanf上的空间

时间:2014-01-29 00:02:11

标签: c scanf

我有一个字段允许我的文本文件中的空格是'citepage'。 fscanf是否可以在标签之间使用空格读取字段,然后在printf中显示? citepage正在获取时间戳的数据。

例如.txt:

1[tab]AAAI[tab]Low-cost Outdoor Robot Platform for the Penn State Abington Mini Grand Challenge[tab]2005[tab]Robert Avanzato[tab]1[tab][espaco][tab]2013-03-07 16:49:1

我目前的代码:

while (!feof(fp)){
    fscanf(fp,"%d\t %19[^\t]\t %300[^\t]\t %d\t %100[^\t]\t %d\t %s\t %19[^\t]\n  ",&artigos.id,artigos.sigla,artigos.titulo,&artigos.ano,artigos.autores,&artigos.citacoes,artigos.citepage,artigos.timestamp);        
    printf("\nid: %d ",artigos.id);
    printf("\nsigla: %s ",artigos.sigla);
    printf("\ntitulo: %s ",artigos.titulo);
    printf("\nano: %d ",artigos.ano);
    printf("\nautores: %s ",artigos.autores);
    printf("\ncitacoes: %d ",artigos.citacoes);
    printf("\ncitepage: %s ",artigos.citepage);
    printf("\ntimestamp: %s ",artigos.timestamp);   
}

2 个答案:

答案 0 :(得分:0)

fscanf不适合基于制表符或换行符而不是空格来分隔内容,因为它将所有空格视为相同 - 要跳过和忽略的内容。每当你的格式字符串中有空白字符时(如果它是空格或制表符或换行符都无关紧要;它们都做同样的事情),fscanf会读取并丢弃空格,直到找到非空格字符。因此,在您的情况下,当\t读取%d之后到达citacoes时,它将跳过输入中的以下
\t \t,并且要读取的下一个字符为2,因此它将开始为citepage读取。

现在,您可以在格式字符串中使用%*1[\t]来跳过单个制表符(而不是所有空格),但这样做很麻烦且容易出错。它也很容易被不正确的输入混淆,几乎不可能为用户提供有关格式错误输入的正确诊断。但是如果你想这样做,用%*1[\t]替换格式字符串中的所有选项卡,并删除所有空格,它应该可以工作。

更好的选择是将整行读入缓冲区(使用fgets),然后使用strsep将其拆分为制表符。

此外,您永远不应该使用feof - 在 之后,您尝试读取文件末尾未成功后才会返回true。请务必检查fscanf或fgets调用的返回值。

答案 1 :(得分:0)

'\t'' '指令执行相同的操作:跳过任何空格。要在scanf()中使用标签作为分隔符,需要使用"%*1[\t]"strtok()或简单循环可能更容易。见@Chris Dodd

建议fgets()/sscanf()以便更好地处理错误,特别是对于这种复杂的扫描 此外,artigos.citepage的格式说明符需要调整。

char buf[200];
if (fgets(buf, sizeof buf, fp) == NULL) Handle_EOFIOError();

// scan, but do not save 1 `\t`
#define TF   "*1[\t]"
if (8 == sscanf(buf,
    "%d"        TF "%19[^\t]" TF "%300[^\t]" TF "%d" TF
    "%100[^\t]" TF "%d"       TF "%19[^\t]"  TF "%19[^\t]",
    &artigos.id, artigos.sigla, artigos.titulo, &artigos.ano, 
    artigos.autores, &artigos.citacoes, artigos.citepage, artigos.timestamp) {
  Success();
}