当我使用fscanf
阅读时:
nscan = fscanf(input_file, "%30[^,], %d, %lf, %d%c",
array[i].epwnymo, &array[i].ypolipo,
&array[i].epitokio, &array[i].meromhnia, &termch);
termch
应为\n
,但在Linux中,我得到\r
,这会使我的程序给出错误的结果。我在某处看过\n
\r\n
\r
,但为什么我在Linux中获得{{1}}?
答案 0 :(得分:7)
这在技术上不是C问题,因为你会在所有编程语言中注意到同样的事情。
如果您已经将文件从Windows直接复制到Linux而没有转换换行符(FTP通过选择TEXT或ASCII传输模式为您提供了选项),那么您的Linux程序会看到{{1字符;这些通常会被翻译为Windows中'\r'
序列的一部分,但Linux不会自动执行此类翻译。
我建议,当您将文本文件从Windows复制到Linux时,运行"\r\n"
来转换这些文本文件(除非您使用为您执行此转换的FTP客户端) )...同样,当您将文本文件从Linux复制到Windows时,您应该使用dos2unix
(同样,除了FTP方案)。
答案 1 :(得分:2)
我建议您可以通过先读取字符串,删除所有newline
字符,然后扫描字符串,而不进行任何newline
测试来处理newline
结尾的不同约定。< / p>
#include <stdio.h>
#include <string.h>
//...
char input[100];
if (fgets(input, sizeof input, input_file) != NULL) {
input [ strcspn(input, "\r\n") ] = 0; // remove trailing newline etc
nscan = sscanf(input, "%30[^,], %d, %lf, %d",
array[i].epwnymo, &array[i].ypolipo, &array[i].epitokio, &array[i].meromhnia);
}
这适用于MSVC中包含以\r
和\n
以及\r\n
结尾的行的文件,我无法在Linux上试用。
答案 2 :(得分:0)
推荐一种新方法。当代码需要读取文本的行时,请从fgets()
开始。
遇到的问题是因为1)各种操作系统使用不同的行结尾,例如\n
\r\n
和\r
2)代码正在处理使用备用行结尾的文本文件和3)OP的代码并未尝试读取行。
以下将接受并使用以5个位置结尾的候选行 - 不仅仅是在结尾。
vv vv vv v
"%30[^,], %d, %lf, %d%c"
"%c"
的问题在于它只接受结束\r\n
的2个字符行中的1个字符。编译代码时,如果文本文件以\r\n
结束,因为流处于文本模式,\r\n
将转换为\n
,因此这不是问题。但是,如果代码是在只需要1个行尾字符的系统上编译的,则\r\n
将保留为2个字符。
经典方法是使用" "
中的fscanf()
来消耗这些不同的空格。
" %30[^,], %d, %lf, %d"
"%30[^,], %d, %lf, %d "
IMO,阅读行文本的最佳第一步是使用fgets()
,然后解析。
// [],sp %d ,sp %lf ,sp %d /r/n/0
#define LINE_EXPECT_MAX (30+1+1+20+1+1+(309+1+6)+1+1+20+2+1)
char buf[LINE_EXPECT_MAX];
if (fgets(buf, sizeof buf, input_file) == NULL) return EOF;
使用" %n"
检测完整扫描并查找尾随的额外非空白文本很容易:
int n = 0;
sscanf(buf, "%30[^,], %d, %lf, %d %n",
array[i].epwnymo, &array[i].ypolipo, &array[i].epitokio, &array[i].meromhnia, &n);
if (n == 0) Handle_Incomplete_Scan();
if (buf[n] != '\0') Handle_Unxpected_Text();
最后,"%d"
和"%lf"
之前的空格没什么用处,因为即使没有前导空格,这些说明符也会消耗前导空格。是","
之前的空格,将在数字之后和逗号之前传递空格。
" %30[^,],%d ,%lf ,%d %n"