逐行读取制表符分隔的内容,最后一列为空字符串
Read tab separated content line by line with last column empty string
我有这样的文件格式
1.9969199999999998 2.4613199999999997 130.81278270000001 AA
2.4613199999999997 2.5541999999999998 138.59131554109211 BB
2.5541999999999998 2.9953799999999995 146.83238401449094 CC
...........................
我必须将前三列读取为 float
,将最后一列读取为 C
中的数组 char
。所有列均以制表符分隔,每行末尾都有一个换行符。 fscanf(fp1, "%f\t%f\t%f\t%s\n", ...)
一切正常,直到我在每行的末尾都有一些文本(字符字符串部分)。
在某些情况下,我的文件中没有 AA/BB/CC,而是一个空字符串。如何处理这种情况。我已经尝试了 fscanf(fp1, "%f\t%f\t%f\t%s[^\n]\n", ...)
和许多其他的东西,但我无法找出正确的方法。你能帮帮我吗?
使用 float
而不是 double
将丢弃显示的大约一半数字。 float
得到 6-7 位小数; double
.
你得到 15 个以上的数字
关于您的主要问题:使用 fgets()
(或 POSIX
getline()
) to read lines and then sscanf()
解析读取的行。这将避免混淆。当输入是基于行但不够规则时,不要使用 fscanf()
和 family 来读取数据——文件读取 scanf()
函数不关心换行符,即使你这样做。
注意 sscanf()
将 return 为 3 或 4,表示行尾是否有字符串(或 EOF
、0
, 1
或 2
如果给定一个空字符串,或者一个不以数字开头的字符串,或者一个只包含一个或两个数字的字符串)。始终测试来自 scanf()
和朋友的 return 值——但要小心。查找您期望的值数(本例中为 3 或 4),而不是 'not EOF'.
这大致导致:
#include <stdio.h>
int main(void)
{
double d[3];
char text[20];
char line[4096];
while (fgets(line, sizeof(line), stdin) != 0)
{
int rc = sscanf(line, "%lf %lf %lf %19s", &d[0], &d[1], &d[2], &text[0]);
if (rc == 4)
printf("%13.6f %13.6f %13.6f [%s]\n", d[0], d[1], d[2], text);
else if (rc == 3)
printf("%13.6f %13.6f %13.6f -NA-\n", d[0], d[1], d[2]);
else
printf("Format error: return code %d\n", rc);
}
return 0;
}
如果将此文件作为标准输入:
1.9969199999999998 2.4613199999999997 130.81278270000001 AA
2.4613199999999997 2.5541999999999998 138.59131554109211 BB
2.5541999999999998 2.9953799999999995 146.83238401449094 CC
19.20212223242525 29.3031323334353637 3940.41424344454647
19.20212223242525 29.3031323334353637 3940.41424344454647 PolyVinyl-PolySaccharide
输出为:
1.996920 2.461320 130.812783 [AA]
2.461320 2.554200 138.591316 [BB]
2.554200 2.995380 146.832384 [CC]
19.202122 29.303132 3940.414243 -NA-
19.202122 29.303132 3940.414243 [PolyVinyl-PolySacch]
您可以调整输出格式以适合自己。请注意,即使文本超过 19 个字符,%19s
也会避免缓冲区溢出。
我有这样的文件格式
1.9969199999999998 2.4613199999999997 130.81278270000001 AA
2.4613199999999997 2.5541999999999998 138.59131554109211 BB
2.5541999999999998 2.9953799999999995 146.83238401449094 CC
...........................
我必须将前三列读取为 float
,将最后一列读取为 C
中的数组 char
。所有列均以制表符分隔,每行末尾都有一个换行符。 fscanf(fp1, "%f\t%f\t%f\t%s\n", ...)
一切正常,直到我在每行的末尾都有一些文本(字符字符串部分)。
在某些情况下,我的文件中没有 AA/BB/CC,而是一个空字符串。如何处理这种情况。我已经尝试了 fscanf(fp1, "%f\t%f\t%f\t%s[^\n]\n", ...)
和许多其他的东西,但我无法找出正确的方法。你能帮帮我吗?
使用 float
而不是 double
将丢弃显示的大约一半数字。 float
得到 6-7 位小数; double
.
关于您的主要问题:使用 fgets()
(或 POSIX
getline()
) to read lines and then sscanf()
解析读取的行。这将避免混淆。当输入是基于行但不够规则时,不要使用 fscanf()
和 family 来读取数据——文件读取 scanf()
函数不关心换行符,即使你这样做。
注意 sscanf()
将 return 为 3 或 4,表示行尾是否有字符串(或 EOF
、0
, 1
或 2
如果给定一个空字符串,或者一个不以数字开头的字符串,或者一个只包含一个或两个数字的字符串)。始终测试来自 scanf()
和朋友的 return 值——但要小心。查找您期望的值数(本例中为 3 或 4),而不是 'not EOF'.
这大致导致:
#include <stdio.h>
int main(void)
{
double d[3];
char text[20];
char line[4096];
while (fgets(line, sizeof(line), stdin) != 0)
{
int rc = sscanf(line, "%lf %lf %lf %19s", &d[0], &d[1], &d[2], &text[0]);
if (rc == 4)
printf("%13.6f %13.6f %13.6f [%s]\n", d[0], d[1], d[2], text);
else if (rc == 3)
printf("%13.6f %13.6f %13.6f -NA-\n", d[0], d[1], d[2]);
else
printf("Format error: return code %d\n", rc);
}
return 0;
}
如果将此文件作为标准输入:
1.9969199999999998 2.4613199999999997 130.81278270000001 AA
2.4613199999999997 2.5541999999999998 138.59131554109211 BB
2.5541999999999998 2.9953799999999995 146.83238401449094 CC
19.20212223242525 29.3031323334353637 3940.41424344454647
19.20212223242525 29.3031323334353637 3940.41424344454647 PolyVinyl-PolySaccharide
输出为:
1.996920 2.461320 130.812783 [AA]
2.461320 2.554200 138.591316 [BB]
2.554200 2.995380 146.832384 [CC]
19.202122 29.303132 3940.414243 -NA-
19.202122 29.303132 3940.414243 [PolyVinyl-PolySacch]
您可以调整输出格式以适合自己。请注意,即使文本超过 19 个字符,%19s
也会避免缓冲区溢出。