XCODE:线程 1:fscanf 上的 EXC_BAD_ACCESS(代码=1,地址=0x68)

XCODE: Thread 1: EXC_BAD_ACCESS (code=1, address=0x68) on fscanf

我在下面使用以下代码,但收到 Thread 1: EXC_BAD_ACCESS (code=1, address=0x68) 错误。我可以通过哪些方式更好地执行此操作?我只是加载了一个包含大约 500000 个数字的 txt 文件,它们每个都在一个新行上。我已经查看了一些如何执行此操作的资源,但我最终遇到了这些奇怪的事情。我希望 c 大师可以帮助我。

#include <stdio.h>
#include <time.h>
#include <limits.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>


#define COUNT_ARRAY_LENGTH 10
#define MAX_NUMBER 500001

int *load_file(){
    FILE *file;
    file = fopen("somefile.txt", "r");
    int a[MAX_NUMBER];

    int i=0;
    int num;
    while(fscanf(file, "%d", &num) > 0) {
        a[i] = num;
        i++;
    }
    fclose(file);
    return a;
}

int main(int argc, const char *argv[])
{
    int *a;
    a = load_file();
    for(int i = 0; i < MAX_NUMBER; i++){
        printf("%d\n", a[i]);
    }
    return 0;
}

正在将评论转化为答案。

我的直接猜测是您无法打开文件 — 您不检查但必须始终检查的错误。文件擅离职守,或者程序 运行 来自错误的目录,或者它们具有错误的权限。

if (file == NULL)
{
    fprintf(stderr, "Failed to open file '%' for reading\n", "somefile.txt");
    exit(EXIT_FAILURE);
}

文件名的重复字面说明了为什么不应该将字符串字面量作为文件名传递给 fopen();您应该有一个变量,以便您也可以在错误消息中报告文件名,而无需自己重复。

const char *filename = "somefile.txt";
if ((file = fopen(filename, "r")) == NULL)
{
    fprintf(stderr, "Failed to open file '%' for reading\n", filename); n. 
    exit(EXIT_FAILURE);
}

事实上,您应该将要加载的文件的名称传递给 load_file() 函数,以便您可以更轻松地更改它(例如,通过命令行参数)。那就是传递数组和数组的大小。这为您提供了一种更通用的功能,一种更容易适应其他用途的功能。

您也可以 #include <errno.h>#include <string.h> 并使用 strerror(errno) 来打印系统错误消息以给用户更多帮助(但知道文件名是一个巨大的进步正确的方向)。

另外,你应该 while (i < MAX_NUMBER && fscanf(file, "%d", &num) > 0) 这样你就不会溢出数组。

此外,您正在 returning load_file() 中本地数组的地址 — you can't do that safely。在main()中定义数组,并将指针作为参数传递。您的 main() 还假定数组已填满。将 load_file() 修改为 return 加载了多少号码,这样您就无法访问未加载的号码。

将所有这些更改放在一起可能会产生:

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

#define MAX_NUMBER 500001

static size_t load_file(const char *filename, size_t arrsiz, int *array)
{
    FILE *file;
    if ((file = fopen(filename, "r")) == NULL)
    {
        fprintf(stderr, "Failed to open file '%s' for reading\n", filename);
        exit(EXIT_FAILURE);
    }

    size_t i = 0;
    int num;
    while (i < arrsiz && fscanf(file, "%d", &num) > 0)
        array[i++] = num;

    fclose(file);

    return i;
}

int main(void)
{
    int a[MAX_NUMBER];
    size_t num = load_file("somefile.txt", MAX_NUMBER, a);

    for (size_t i = 0; i < num; i++)
        printf("%d\n", a[i]);

    return 0;
}

已编译但未编译 运行。

您可以像这样处理 command-line 参数:

int main(int argc, char **argv)
{
    if (argc > 2)
    {
        fprintf(stderr, "Usage: %s [filename]\n", argv[0]);
        exit(EXIT_FAILURE);
    }
    const char *filename = (argc == 2) ? argv[1] : "somefile.txt";

    int a[MAX_NUMBER];
    size_t num = load_file(filename, MAX_NUMBER, a);

    for (size_t i = 0; i < num; i++)
        printf("%d\n", a[i]);

    return 0;
}

或者您可以允许多个参数并遍历所有参数。 有时,最好在 main() 中进行文件打开和关闭,并将打开的文件流传递给函数。如果没有 command-line 参数,您可以从 stdin 读取。选项很多!