c - fscanf 在输入的最后一行失败(仅负值?)
问题描述
我写了一个函数来解析文件输入。该文件包含一行浮点数,该函数应该将它们放入一组向量中。
文件的最后一行有时会出现在结果中,有时不会。fscanf 返回 1,最后一行的输入将失败。我添加了一个示例来重现该问题。
源代码:
typedef struct vectors {
double** vecs;
int n; /* number of vectors */
} vectors;
vectors* parseInput(char* file_name, int dim) {
float coordinate;
char c;
double *vec;
int i=0, ind=0, j=0, debug;
FILE* input;
vectors* datapoints;
double** vex = (double**) calloc (1000*dim, sizeof (double*));
assert(vecs != NULL);
datapoints = (vectors*)malloc(sizeof(vectors));
assert(datapoints != NULL);
input = fopen(file_name, "r");
assert(input != NULL);
while (1) { /* loop until EOF */
debug= fscanf(input, "%f%c", &coordinate, &c);
printf("%d%s", debug, "\n");
if(debug!=2)
{
printf("%s%d%s","fscanf value: ",debug,"\n"); // if in last row (that has negative values), will print 1
printf("value: ");
printf("%lf",coordinate);
printf(" char: ");
printf("%c", c);
break;
}
if (j == 0)
{
vec = (double *)calloc(dim, sizeof(double));
assert(vec != NULL);
}
if(c!='\n' && coordinate!='\n')
{
vec[j] = coordinate;
j++;
}
if (j == dim)
{
print_vec(vec, dim);
vecs[i] = vec;
i++;
j = 0;
}
}
vecs = (double**)realloc(vecs, i*sizeof(double*));
assert(vecs != NULL);
datapoints->vecs = vecs;
datapoints->n = i;
fclose(input);
return datapoints;
}
在输入上(作为 txt 文件)
-5.05604381
,11.01146785 -6.40861975,-7.96222506
5.69419195,9.60601354
6.60569313,9.39602582
-6.771797,-5.72717303
-4.49752324,8.39891449
-4.98452388,9.0760693
4.42351449,8.81860878
-7.59529807,-7.21054155
-4.19783158,8.37108438
输出将是:
-5.0560,11.0115
-6.4086,-7.9622
5.6942,9.6060
6.6057,9.3960
-6.7718,-5.7272
-4.4975,8.3989
-4.9845,9.0761
4.4235,8.8186 **
105.5953,-7
**2最后一行
我使用的主要功能:
int main(int argc, char** argv){
int i;
int k = atoi(argv[1]);
int dim = get_dim_from_file(argv[3]); // works fine
vectors* datapoints = parseInput (argv[3], dim); //the function in discussion
double** vecs = datapoints->vecs;
int n = datapoints->n;
const char* goal = argv[2];
if(!strcmp(goal, "parse"))
{
printf("%s%d%s","\n", datapoints->n,"\n" );
print_matrix(datapoints->vecs, datapoints->n, dim);
}
}
void print_matrix(double** A, int n, int k) {
int row, col;
for (row = 0; row < n; row++) {
for (col = 0; col < k-1; col++) {
if ((A[row][col] < 0) && (A[row][col] > -0.00005)) {
A[row][col] = 0;
}
printf("%.4f%s", A[row][col], ",");
}
if ((A[row][k-1] < 0) && (A[row][k-1] > -0.00005)) {
A[row][k-1] = 0;
}
printf("%.4f%s", A[row][k-1], " \n");
}
}
如果有人知道如何解决这个问题,那就太好了!
谢谢!
解决方案
某些文本文件的最后一行末尾没有换行符。
格式良好的文件:
-5.05604381,11.01146785\n
-6.40861975,-7.96222506\n
...
-4.19783158,8.37108438\n
一个格式不太好的 [但仍然有效的] 文件:
-5.05604381,11.01146785\n
-6.40861975,-7.96222506\n
...
-4.19783158,8.37108438
您fscanf
将处理第一个文件,但不处理第二个文件。
此外, in fscanf
,"%f"
代表 a float
,但是 [如果] 你有 a double
,你想要"%lf"
.
实际上,您正在扫描coordinate
的是 afloat
但您的向量是double
,因此您[可能]从一开始就失去了精度。最好直接扫描到向量元素中。
注意:为简洁起见,我省略了动态数组分配。
如果每行有固定数量的数字,您可以执行以下操作:
int count;
double vec[1000];
while (1) {
if (fscanf(input,"%lf,%lf",&vec[count + 0],&vec[count + 1]) != 2)
break;
count += 2;
}
这适用于任何一种情况,并且更常见/惯用。
如果每行有一个变量计数,最好使用fgets
and strtod
。
就个人而言,我更喜欢这个,因为它可以提供更好的错误检测/控制。
int count;
double vec[1000];
char buf[100];
while (1) {
char *cp = fgets(buf,sizeof(buf),input);
if (cp == NULL)
break;
while (1) {
vec[count++] = strtod(cp,&cp);
// no newline
if (*cp == 0)
break;
// has a newline
if (*cp == '\n')
break;
// syntax error
if (*cp++ != ',')
break;
}
}
推荐阅读
- amazon-web-services - 由于错误的过滤器表达式,我无法从 aws lambda 查询我的 dynamodb 表?
- java - 无法使用 javamail 和 zimbra 服务器发送电子邮件
- pyspark - 在 Spark 数据框中的列表中查找最大值
- javascript - 为什么我的 Google Maps API 被嵌入但没有显示在 HTML 页面上?
- javascript - 为什么在 ES6 中用 [] 解构之前需要分号?
- python - 使用 Table.objects.filter(condition) 时,Django API 返回单个对象而不是我的整个列表
- pyspark - 如何在 pyspark 数据框中找到相似的行?
- python - 是否有更 Pythonic 的方式来嵌套条件语句以填充 pandas df 中的新列?
- c - 删除所有节点链表
- javascript - 具有背景滤镜的元素的平均颜色?html、css、jquery