C语言 如何使用输入验证循环从包含一行不同值的数据文件中获取特定值?

k7fdbhmy  于 2023-06-21  发布在  其他
关注(0)|答案(2)|浏览(97)

我想在一个数据文件上取一行不同的值,在分别阅读前几个值之后,使用for循环读取随后的每个值。然而,程序似乎并没有阅读每个后续值,并且不显示任何内容。我该如何着手解决这个问题?
让我们假设这些值看起来像这样:

4.2 2.0 8.0 3.4 5.1 8.9 7.9

这是我到目前为止的代码:

#include <stdio.h>
int main (void)
{
    int i=0,count;
    FILE *ptr;
    ptr = fopen("datafile.data","r");
    fscanf(ptr,"%d ",&count);
    double arr[count];
    for(i=0;i<count;i++)
    {
        fscanf(ptr,"%lf ",&arr[i]);
        printf("%lf\n",arr[i]);
    }
    fclose (ptr);
    return(0);
}

编辑:%d的开头应该有一个5,所以该行看起来像5 4.2 2.0 8.0 3.4 5.1 8.9 7.9

0h4hbjxa

0h4hbjxa1#

我修复了代码中的一些错误,首先是检查文件是否存在,然后我将文件的扩展名更改为.txt,然后从文件中读取值,如下所示。

#include <stdio.h>

int main (void)
{
    int i=0,count;
    FILE *ptr;
    ptr = fopen("datafile.txt","r");

    if (ptr == NULL) // check if file exists
    {
        printf("Error!");
        return 1;
    }

    double buffer[20];

    while (fscanf(ptr, "%lf", &buffer[i]) == 1) // read file contents till end of file
    {
        printf("%.2lf\n", buffer[i]);
        i++;
    }

    return(0);
}

输出

4.20
2.00
8.00
3.40
5.10
8.90
7.90
kmynzznz

kmynzznz2#

给定的输入文件为

5
4.2 2.0 8.0 3.4 5.1 8.9 7.9

首先要做的是确保文件是opened correctly

FILE *file = fopen("datafile.data", "r");

if (!file) {
    perror("fopen");
    exit(1);
}

您必须做的第二件事是确保初始值被正确读取,并且在创建VLA时不会导致Undefined Behaviour的适当范围内。这意味着大于零,并且低于某个合理的限制,以免溢出程序的stack(即ulimit -s等)。
fscanf的返回值应始终检查为 * 预期的成功转换数 *。这里我们转换 one 值。

#define MAXSIZE 128

size_t size = 0;

if (1 != fscanf(file, "%zu", &size) || !size || size > MAXSIZE) {
    fprintf(stderr, "Invalid size.\n");
    return 1;
}
  • size_t是最适合用于内存大小和偏移量的类型。)*

现在,上面的评论
[...]并扫描行 * 末尾 * 的5个值,同时跳过4.2和2.0。
引入了一个问题:
除非你的输入总是一个静态的大小,否则我们怎么知道要跳过多少个值呢?
如果流是可查找的,一种方法是简单地读取并计算有多少个值。从这个计数中减去初始值,就得到了要跳过的数量。然后,* 倒带 * 文件并对其进行适当的读取和存储。
另一个选项将是仅存储最近读取的 N 个值,丢弃较早的值。这可以通过一种类型的循环缓冲器/队列来实现。
一个基本的例子:

double data[size];
size_t total_read = 0;
size_t index = 0;

while (1 == fscanf(file, "%lf", data + index)) {
    total_read++;
    index = (index + 1) % size;
}

if (total_read < size)
    fprintf(stderr, "WARN: Did not read all [%zu] values.\n", size);

之后,如果需要(即顺序和total_read > size),可以通过围绕index * 旋转 * 缓冲区来将值返回到其读取顺序。

相关问题