首页 > 解决方案 > 我应该如何使用命令行参数从文件中填充整数数组?文件的大小和编号。的元素可能会有所不同

问题描述

我对 C 编程真的很陌生。我有一个任务,我必须使用命令行参数从文本文件中填充整数数组。该数组应该能够从文件中获取所有数字。这是应该执行上述操作的代码段,但它失败了。我仍然需要添加错误检查,但我只需要知道我哪里出错了,以及我是否走在正确的道路上。

据我目前所知,我将不得不使用内存分配来使我的数组动态化。我已经使用 ftell() 来查找文件的大小(以字节为单位),因此我可以相应地分配内存。

#include <stdio.h>
#include <math.h>
#include <stdbool.h>
#include <fstream>
#include <stdlib.h>

int main(int argc, char *argv[]) {

    if (argc > 2) {
        printf(stderr, "Error, too many arguments supplied.");
        exit(1);
    }

    if (argc == 2) {
        int *numArray = NULL; //pointer to integer

        FILE* inputFile = fopen(argv[1], "r");

        fseek(inputFile, 0, SEEK_END);

        // calculating the size of the file 
        int fileSize = ftell(inputFile);

        numArray = malloc(fileSize * sizeof(int));

        if (numArray == NULL) {
            printf(stderr, "Error: File is empty.");
            exit(1);
        }

        int num;
        int arraySize = sizeof(numArray) / sizeof(numArray[0]);

        for (int i = 0; i < arraySize; i++) {
            fscanf(inputFile, "%d", &num);
            numArray[i] = num;
        }

        fclose(inputFile);
    }

}

如果文件包含:67、66、353、789、2342,NumArray = {67、66、353、789、2342}

标签: cmemory-managementcommand-line-argumentsfilestreamdynamic-memory-allocation

解决方案


代码中存在多个问题:

  • <fstream>是 C++ 头文件,不要混合 C 和 C++。
  • printf(stderr, "Error, too many arguments supplied.");应该在其第一个参数上产生关于类型不匹配的警告。用于fprintf打印到stderr.
  • 该文件以文本模式打开,而不是二进制模式,因此ftell()可能不会返回文件中的字节数。
  • 文件打开失败未测试。
  • 分配fileSize * sizeof(int)是多余的。这些数字是文本格式的,所以最多fileSize / 2可以在文件中找到数字,而且可能比这要少得多。
  • 分配字节失败并不意味着文件为空。
  • 当您从文件中读取更多数字时,您应该重新分配数组。这也允许从诸如终端和命名管道等不可查找的设备中读取。
  • arraySize = sizeof(numArray) / sizeof(numArray[0])不计算数组中元素的数量,因为numArray它是指向数组的指针,而不是数组。此外,您应该只保留读取的实际数字的数量,这是循环i中的最终值。for
  • 您应该测试以下返回值fscanf():1 表示转换成功,0 表示存在无效输入,无法转换为整数,EOF表示文件结束,或者可能是 I/O 错误。

这是修改后的版本:

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

int main(int argc, char *argv[]) {

    if (argc != 2) {
        fprintf(stderr, "The program expects a single command line argument\n");
        return 1;
    } else {
        int *numArray = NULL;
        size_t arraySize = 0;
        size_t arrayCount = 0;
        FILE *inputFile = fopen(argv[1], "r");
        int res, num;

        if (inputFile == NULL) {
            fprintf(stderr, "Cannot open file %s: %s\n", strerror(errno));
            return 1;
        }
        while ((res = fscanf(inputFile, "%d", &num)) == 1) {
            if (arrayCount >= ArraySize) {
                size_t newSize = arraySize ? arraySize * 2 : 32;
                int *newArray = realloc(numArray, newSize * sizeof(int));
                if (newArray == NULL) {
                    fprintf(stderr, "Out of memory for %zu elements\n", newSize);
                    exit(1);
                }
                numArray = newArray;
                arraySize = newSize;
            }
            numArray[arrayCount++] = num;
        }
        if (res != EOF) {
            fprintf(stderr, "Invalid input for element %zu\n", arrayCount);
        }
        if (arrayCount == 0) {
            if (res == EOF) {
                fprintf(stderr, "File %s is empty\n", argv[1]);
            }
            fclose(inputFile);
            return 1;
        }
        ...  // do something with the arrayCount elements in numArray
        free(numArray);
        fclose(inputFile);
    }
    return 0;
}

推荐阅读