2014-01-29 133 views
1

我有一个字段,允许在我的文本文件中有'citepage'的空格。 fscanf是否可以通过选项卡之间的空格读取字段,然后在printf中显示它?该引用页面正在获取时间戳的数据。在fscanf上读取空间

为例.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); 
} 

回答

0

fscanf不利于separting基于选项卡或换行的事,而不是空间,因为它把所有空白的同样的 - 有些东西会被忽略和忽略。每当你的格式字符串中有一个空格字符时(无论它是空格还是制表符还是换行符都无关紧要;它们都会做同样的事情),fscanf将读取并删除空白字符,直到找到非空白字符。所以在你的情况下,当它到达\t之后%d读取citacoes时,它将在输入中跳过以下
\t \t,并且要读取的下一个字符将是2,所以这就是它开始读取的位置citepage

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

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

此外,你永远不应该使用feof - 它不会返回true,直到之后你已经尝试不成功地读取文件的末尾。总是检查fscanf或fgets调用的返回值。

+0

'strsep'是否便携? – dreamlax

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