我正在尝试使用fscanf
来读取数据,部分输入是一个浮点数后跟字母'e'
,例如41.72elapsed
。在为fscanf
编写strng时,我尝试使用"%felapsed"
,但这不起作用,因为%fe
是它自己的格式说明符。如何使用fscanf
?
编辑: 这是代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define CHAR_MAX 1024
int main(int argc, char **argv)
{
FILE *file_in = fopen(argv[1], "r+");
char out_name[CHAR_MAX];
strcpy(out_name, argv[1]);
strcat(out_name, ".csv");
FILE *csv_out = fopen(out_name, "w");
int minutes;
float seconds;
fprintf(csv_out, "Trial #, Execution Time\n");
for (int i = 0; fscanf(file_in, "%*fuser %*fsystem %d:%felapsed %*d%%CPU (%*davgtest+%*davgdata %*dmaxresident)k\n%*dinputs+%*doutputs (%*dmajor+%*dminor)pagefaults %*dswaps\n", &minutes, &seconds) == 2; i++) {
fprintf(csv_out, "%d, %d:%.2f\n", i, minutes, seconds);
};
return 0;
}
以下是一些示例输入:
283.97user 0.69system 1:13.77elapsed 385%CPU (0avgtext+0avgdata 107472maxresident)k
0inputs+4616outputs (0major+9550minor)pagefaults 0swaps
287.87user 0.35system 1:14.41elapsed 387%CPU (0avgtext+0avgdata 107328maxresident)k
0inputs+4616outputs (0major+9524minor)pagefaults 0swaps
答案 0 :(得分:6)
这是scanf()
"%f"
这样的FP格式将e
视为引入取幂。由于e
后面没有数字,因此扫描float
会停止。但是scanf()
已经准备好扫描一个e
,而C不需要scanf()
能够备份超过1个字符。因此,使用简单的"%f"
代码就会失败。
有些系统会备份超过1个字符,但C不需要该功能。
代码需要一种新方法 - 以秒为单位扫描
char sec[20];
int cnt = fscanf(file_in, "%d:%19[0-9. ]elapsed", &minutes, sec);
if (cnt == 2) {
seconds = atof(sec);
...
}
答案 1 :(得分:4)
您的格式中根本不需要"elapsed"
。只要可以从输入中读取scanf
family函数,对于浮点数,当它到达非数字字符时它将停止读取,即e
在elapsed
中}。
因此格式只需"%f"
即可,而且就是float value;
fscanf(file, "%f", &value);
。即。
elapsed
如果您想阅读并放弃"%*s"
部分,请使用float value;
fscanf(file, "%f%*s", &value);
,星号告诉scanf
(and family)阅读并忽略其余内容,因此完整调用看起来像
char input[512];
for (int i = 0; fgets(input, sizeof input, file_in) != NULL; ++i) {
if (sscanf(input, "%*f%*s %*f%*s %d:%f%*s", &minutes, &seconds) == 2) {
fprintf(csv_out, "%d, %d:%.2f\n", i, minutes, seconds);
}
}
看到你的代码之后,用
之类的东西可以更加简单和容易fgets
由于此循环使用fscanf
而不是直接fgets
,因此您将在输入文件中读取所有行,而不仅仅是第一行。此外,由于使用sscanf
,我们不需要sscanf
函数来实际解析我们不需要的字符串部分(大部分都是这样),而我们只有{{ }}
解析输入字符串,直到我们得到所需的数据。
答案 2 :(得分:2)
这有点像黑客,可能太脆弱了,但是:
您要解析的float似乎是以minute.second格式表示的时间,具有正整数。如果数据的生成者可靠地将小数字填充为零(例如1:02.03),则可以简单地使用固定字段长度5,因为秒和分钟永远不会大于59,因此每个字符宽度总是两个字符: / p>
sscanf("12.345678", "%5f%s, &f, buf)将12.34读入f,将5678读入buf。 (当然,同样的,&#34; 12.34elapsed&#34;。我只是想让它明确无误地表明只消耗了5个输入字符。)
答案 3 :(得分:1)
我们来做一个实验:
os.system(cmd)
输入:#include <stdio.h>
int main (void)
{
float fp;
scanf("%f", &fp);
printf("%f", fp);
}
输出:123e4
如您所见,“e”被视为“%f”指定的浮点数的一部分。
对我来说,最简单的解决方案是使用1230000.000000
。在被“%f”拒绝之后,“失效”被“%* s”消耗,而不会引起问题。当涉及到'e'时,它就被丢弃了,因为C规范有一个脚注“fscanf将最多一个输入字符推回到输入流上。”
scanf("%f%*s ", &f);
?