如何扫描一个浮点然后紧跟c中的字母'e'?

时间:2016-03-18 14:12:17

标签: c gcc scanf format-specifiers

我正在尝试使用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

4 个答案:

答案 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函数,对于浮点数,当它到达非数字字符时它将停止读取,即eelapsed中}。

因此格式只需"%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将最多一个输入字符推回到输入流上。”

BTW:你必须处理浮点数吗?如果没有,那么简单地将它们视为字符串呢?例如,scanf("%f%*s ", &f);