Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
unix环境中的C语言-Fscanf和sprint命令_C_Unix_Printf_Scanf - Fatal编程技术网

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

unix环境中的C语言-Fscanf和sprint命令,c,unix,printf,scanf,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) {

我正在尝试读取分隔符为“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++; }

成功后,
fscanf
返回成功读取的项目数。 此计数可以与预期数字匹配,如果匹配失败,则可以小于预期数字


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

fscanf()字符串中的\t字符不是必需的-制表符是空白,因此您可以说“%s%s%s”-可以想象,两个scanf实现对它们的处理方式不同。此外,您应该检查fscanf是否返回除EOF以外的值,但不等于预期的转换次数,这表明存在某种类型的转换错误。

更仔细地检查
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;
}
#包括
内部主(空)
{
字符b1[20]、b2[20]、b3[20]、b4[20]、b5[20];
而(fscanf(stdin,“%s\t%s\t%s\t%s\t”,b1、b2、b3、b4、b5)=5)
printf(“%s\t%s\t%s\t%s\t%s\t%s\n”,b1、b2、b3、b4、b5);
返回0;
}
然而,它确实将字符串“
k
”(5个单字母用空格分隔)视为等同于5个制表符分隔。因此,问题在于C标准第§7.19.6.2节规定:

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

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

另外,关于“%s”说明符,它表示:

匹配一系列非空白字符


要强制匹配实际制表符,您必须更加努力。使用“将行读入缓冲区(
fgets()
)并手动拆分”会更容易。这还允许您在一行上强制执行5个字,如果字段太少或太多,您可以生成错误或警告。使用
fscanf()
,您不能这样做。如果您在一行中键入8个单词,它将第一次读取前5个单词,然后在这行中读取剩余的3个单词,再加上下一行中的前两个单词,依此类推。

您能发布一个示例行并告诉我们读取了多少吗?您使用的是完全相同的文件吗?Windows/Unix选项卡的解释可能不同。可能,当复制到unix时,在windows上使用制表符创建的文件可能不符合预期。@Gunner-你确定你没有将制表符与行尾标记混淆吗?我同意。当然制表符的
\t
是通用的吗?不要像前面所说的那样,将格式字符串中的
\n
\r
n`空格混淆,例如\t,将t中的空格清空输入,如\t和\r和\n以及空格。此程序使用\t是模糊但有效的。“您不妨说”%s%s%s”“--不,即使我们将您的键入错误修复为“%s%s%s%s”(五个字符串而不是4个字符串),它仍然不能作为替代。但是用“%s%s%s%s\t”清除尾随空白将是一种替代方法。