【发布时间】:2014-07-21 22:45:31
【问题描述】:
我在 Ubuntu 12.04.4 LTS 32 位上使用编译器 gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3,使用 fscanf 函数从文件中读取有点问题.格式说明符 %f 无法读入代码中声明为双精度的变量,但 %lf 有效。这种差异背后的原因是什么?我在下面提供了一个代码 sn-p 和一个数据文件:
编辑:我在使用以下代码 sn-p 的较大代码中遇到分段错误。我已经尝试删除前两行并摆脱 char 和两个 fgets 调用,但它不起作用。
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <complex.h>
#include <fftw3.h>
#define N 3500
int main(void)
{
FILE * data = fopen("data_1657.dta", "r"), * fft = fopen("fftq3.dat", "w+");
if(!data) // Checking if the file opened succesfully
return 1;
fftw_complex *in, *out;
fftw_plan forward;
forward = fftw_plan_dft_1d(N, in, out, FFTW_FORWARD, FFTW_ESTIMATE);
double *t, *ft, *err;
int i = 0;
t = (double *) malloc(sizeof(double) * N);
ft = (double *) malloc(sizeof(double) * N);
err = (double *) malloc(sizeof(double) * N);
char str [100];
fgets(str, 100, data);
fgets(str, 100, data);
while (fscanf(data, "%lf %lf %lf", &t[i], &ft[i], &err[i]) == 3)
{
printf("%lf \t %lf \n", t[i], ft[i]);
i++;
}
fftw_execute(forward);
fclose(data);
fclose(fft);
fftw_destroy_plan(forward);
fftw_free(in);
fftw_free(out);
free(t);
free(ft);
return 0;
}
编辑:更正循环
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main(void)
{
FILE * data = fopen("data_1657.dta", "r");
double t, count, err;
while (fscanf(data, "%lf %lf %lf", &t, &count, &err) == 3)
{
printf("%f \t %f \t %f \n", t, count, err);
}
return 0;
}
time in seconds count rate(c/s) error
--------------------- -------- -------
281.3251281976699829 115.639 21.228
281.8250962048768997 149.639 22.774
282.3250641971826553 111.639 21.039
282.8250322043895721 155.639 23.036
283.3250001966953278 141.639 22.420
283.8249682039022446 107.639 20.848
284.3249361962080002 135.639 22.151
284.8249042034149170 151.639 22.861
285.3248721957206726 127.639 21.786
285.8248402029275894 143.639 22.509
286.3248081952333450 129.639 21.878
286.8247760981321335 123.639 21.602
287.3247441053390503 93.639 20.166
287.8247120976448059 95.639 20.264
288.3246801048517227 131.639 21.969
288.8246480971574783 127.639 21.786
289.3246161043643951 107.639 20.848
289.8245840966701508 91.639 20.066
290.3245521038770676 77.639 19.356
290.8245200961828232 115.639 21.228
291.3244881033897400 109.639 20.944
291.8244560956954956 125.639 21.694
292.3244241029024124 107.639 20.848
292.8243920952081680 105.639 20.752
293.3243599981069565 133.639 22.060
293.8243280053138733 183.639 24.221
294.3242959976196289 161.639 23.295
294.8242640048265457 141.639 22.420
顺便说一句,在不删除数据文件中的两个标题行的情况下,是否可以从数据文件的第三行开始读取?
提前致谢
【问题讨论】:
-
您可以使用 fgets() 读取一行文本。对前两行执行两次,使用之后丢弃的缓冲区。或者,您可以只读取字符,直到您点击两次
'\n'。 -
我一点也不知道为什么
%lf为你工作而%f不是,但从长远来看,如果你用@ 一次阅读整行,你会更快乐987654321@(不是标准的,但本系统应该存在),然后使用strtod解析行并将字符串转换为浮点数。strtod加上列上的内部循环是解析此输入格式所需的全部内容。您将跳过外部getline循环中的前两行。 -
@Zack 我可以试试,谢谢你的建议。
-
您的代码只保存(打印)奇数行(第 1、3、5 ...)。
-
您的
do { fscanf(…); printf(…); } while (fscanf(…) != 3);循环是错误的,因为它为每个打印的一个数字读取两组数字,并且因为它不检查第一个fscanf()的状态。一般来说,您应该警惕do … while循环; I/O 更是如此。你需要while (fscanf(…) == 3) { printf(…); }——在顶部测试循环并明确检查每个输入操作。