C语言 - unix环境中的Fscanf和sprint命令

时间:2010-06-08 07:40:24

标签: c unix printf scanf

我正在尝试使用“tab”分隔符读取包含30行和5列的文件。每次我只获得部分行。 在Windows环境中它运行良好。知道为什么在unix中它不起作用?

while (fscanf(FFMapFile, "%s\t%s\t%s\t%s\t%s\t", fnfMap[i].COS_ID, fnfMap[i].FF_First_Act, fnfMap[i].FF_Next_Act, nfMap[i].Free_FF_allowed, fnfMap[i].FF_Change_Charge) != EOF)
{ 
    sprintf(s,"%s\t%s\t%s\t%s\t%s\t", nfMap[i].COS_ID, fnfMap[i].FF_First_Act, fnfMap[i].FF_Next_Act, fnfMap[i].Free_FF_allowed, fnfMap[i].FF_Change_Charge);
    error_log(s,ERROR);
    i++; }

3 个答案:

答案 0 :(得分:1)

fscanf()字符串中的\ t字符不是必需的 - 制表符是空格,所以你也可以说“%s%s%s%s” - 可以想象,两个scanf实现对它们的处理方式不同。此外,您应检查fscanf返回EOF以外的值但不等于预期转换的数量,这表示某种转换错误。

答案 1 :(得分:0)

成功时,fscanf会返回成功阅读的项目数。 此计数可以匹配预期的数量,或者在匹配失败的情况下更少。

您应该检查fscanf的返回值以查看未正确解析的行并检查您的输入数据。

答案 2 :(得分:0)

更仔细地检查fscanf()的返回值;例如,如果匹配3个字段,它将返回3。您可能需要注意各种字符串的大小以避免缓冲区溢出 - 但是,这可能是另一天的主题。

令我震惊的可能性是格式字符串中的最后一个标签可能更好作为换行符 - 但fscanf()通常对格式字符串和数据中的空格采取相当自由的态度。

这个简化(但完整,有效)的代码版本在MacOS X上或多或少地表现得很好。

#include <stdio.h>

int main(void)
{
    char b1[20], b2[20], b3[20], b4[20], b5[20];
    while (fscanf(stdin,"%s\t%s\t%s\t%s\t%s\t", b1, b2, b3, b4, b5) == 5)
        printf("%s\t%s\t%s\t%s\t%s\n", b1, b2, b3, b4, b5);
    return 0;
}

但是,它确实将字符串“k k k k k”(由空格分隔的5个单个字母)视为等效于由5个制表符分隔。因此,问题在于C标准的第7.19.6.2节规定:

  

格式由零个或多个指令组成:一个或多个空格   字符,普通的多字节字符(既不是%也不是空白字符),或者是   转换规范。

     

跳过输入的空白​​字符(由isspace函数指定),除非   规范包括[,c或n说明符。

另外,关于'%s'说明符,它说:

  

匹配一系列非空白字符。

要强制匹配实际标签,您必须更加努力地工作。使用“将一行读入缓冲区(fgets())并手动拆分”会更容易。这也允许您在一行上强制执行5个单词,如果字段太少或太多,您可以生成错误或警告。使用fscanf(),您无法做到这一点。如果你在一行上键入8个单词,它将在第一次读取前五个单词,然后在行上读取剩余的三个单词加上下一个单词的前两个单词,依此类推。