【问题标题】:How do you properly use the fstat() function and what are its limits?您如何正确使用 fstat() 函数以及它的限制是什么?
【发布时间】:2015-02-02 23:29:03
【问题描述】:

所以我对 C 很陌生。我用 Java 做了很多编程,发现学习 C 非常困难。

目前我被分配从我们的终端窗口读取一个文件,该文件将包含一个整数列表。从这个列表中,我们必须读取值并计算平均值,我相信我做对了。

我唯一的问题是我不明白如何正确使用 fstat(),我阅读了手册页但仍然很难理解。在下面的代码中,我想使用 fstat() 来查找正在读取的文件的大小,这样我就可以为我的数组分配正确的空间量,用于存储从输入文件中读取的值。我只需要知道 fstat() 的正确用法和语法,从那里我相信我可以取得重大进展。提前致谢!

    char *infile;
    int fileSize;
    int fd;
    int i;
    int j;
    int temp;
    int sum = 0;
    int average;
    /* enforce proper number of arguments
    */
    if (argc != 1)
    {
            fprintf(stderr, "Too many arguments.\n");
            exit(1);
    }

    infile = argv[1];

    //open file
    fd = open(infile, O_RDONLY);

    //exit if open fails
    assert (fd > -1);

    //find size of file
    fileSize = fstat(fd, blksize_t st_blksize); 

    //fine perfect size for array
    temp =  malloc(temp * sizeof(int));

    //create file of perfect size
    int intArray[temp];

    //scan integers into our array
    for (i = 0; i < fileSize; i++)
    {
            fscanf(infile, "%d", intArray[i]);
    }
    fclose(fd);

    //add all integers into the array up
    for (j = 0; j < fileSize; j++);
     {
            sum = sum + intArray[j];
     }

    //calculat average
    average = (sum)/fileSize;

    printf("Number of numbers averaged: %d\n Average of numbers: %d\n", fileSize, average);

    if ( close(fd) == -1 )
     {
             fprintf(stderr, "error closing file -- quitting");
             exit(1);
     }

return 0;

}

【问题讨论】:

  • 注意:malloc(temp * sizeof(int)) temp 在此处使用时是不确定的,因此会调用未定义的行为,因此了解fstat 的工作原理不是唯一的问题。对temp 的赋值,一个int 而不是指针类型,只是在伤口上加了盐。

标签: c arrays malloc


【解决方案1】:

库函数fstat()不返回文件大小,如果成功则返回0。它通过填写作为参数传递的结构来通知文件大小。

if (fstat( fd, &buf))
    printf("Bad call\n");
else
    printf("File size : %ld\n", buf.st_size);

但正如@chux(已删除的帖子)所回答的那样,它以字节为单位告诉您文件大小,而不是整数。函数fscanf()text输入数据,所以文件大小和字段数没有直接关系。

不幸的是,在回答您的标题问题时,使用fstat() 确定文件大小对您没有实际用途。您的第二个隐含问题是如何为数组分配足够的内存。我在不同的上下文中发布了一个答案,一开始数组大小是未知的。 C reading a text file separated by spaces with unbounded word size

但在这里我使用了一种更简单的技术——两次解析文件以找出它包含多少文本整数。然后它会倒回文件并为数组分配内存,尽管在此示例中,数组不是计算值的总和和平均值所必需的,并且双文件解析也不是必需的,除非您打算这样做更多的价值观。

#include <stdio.h>
#include <stdlib.h>

void fatal(char *msg) {
    printf("%s\n", msg);
    exit (1);
    }

int main(int argc, char *argv[])
{
    FILE *fil;
    int *array;
    int items = 0;
    int sum = 0;
    int avg;
    int value;
    int i;

    if (argc < 2)                                       // check args
        fatal ("No file name supplied");
    if ((fil = fopen (argv[1], "rt")) == NULL)          // open file
        fatal ("Cannot open file");
    while (fscanf(fil, "%d", &value) == 1)              // count ints
        items++;
    printf ("Found %d items\n", items);
    if (items == 0)
        fatal ("No integers found");
    if ((array = malloc(items * sizeof (int))) == NULL) // allocate array
        fatal ("Cannot allocate memory");

    if (fseek (fil, 0, SEEK_SET))                       // rewind file
        fatal ("Cannot rewind file");
    for (i=0; i<items; i++) {
        if (fscanf(fil, "%d", &value) != 1)             // check int read
            fatal ("Cannot read integer");
        array[i] = value;
        sum += value;
    }
    fclose(fil);
    printf ("Sum = %d\n", sum);
    printf ("Avg = %d\n", (sum+items/2) / items);       // allow rounding
    free(array);
    return 0;
}

输入文件:

1 2   3
4 5
6
   -1   -2

程序输出:

Found 8 items
Sum = 18
Avg = 2

【讨论】:

  • @MisterZenious 我发布了更完整的答案。
  • 好的。但是我需要给 main() 一个参数,因为我将通过终端通过命令行向它传递一个文件。所以不是 if ((fil = fopen ("test.txt", "rt")) == NULL) 我需要做 If((fil = fopen(*arg[1], "rt")) = = NULL) 对吗?
  • @MisterZenious 几乎是正确的 - 我再次修改了答案,将文件名作为程序参数。
【解决方案2】:

您声称已阅读 fstat() 的联机帮助页,这似乎与:
fileSize = fstat(fd, blksize_t st_blksize);
您需要在函数范围内声明一个struct stat,并将指向它的指针传递给fstat()

struct stat finfo;
fstat(fd, &finfo);

然后就可以从struct stat读取文件大小:

off_t filesize = finfo.st_size;

我还建议使用size_t 而不是int 来处理与对象大小有关的一切。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多