函数找不到失败的内存分配

Function cannot find failed memory allocation

函数int load(const char *filename, int ***ptr, enum save_format_t format)应该从二进制或文本文件(名称保存在filename指针下)加载数据到[=14下的矩阵=] 指向矩阵的指针。文件扩展名取决于变量格式的值:0 或 1(在我展示的函数中,只有 format=0 的选项,主要用于文本文件,因为只有这个会带来麻烦)。文件中的正确数据如下所示:

10 20 30 40 50 60 70 -1

100 200 300 400 500 600 700 800 -1

对于与上面示例完全相同的数据,应按如下方式加载数据:

int A[] = {10, 20, 30, 40, 50, 60, 70, -1};

int B[] = {100, 200, 300, 400, 500, 600, 700, 800, -1};

int D[] = {A, B, C, NULL};

这意味着每一行都必须以“-1”结尾(数据必须加载到带有“-1”的矩阵)。指向最后一行之后的行的指针应等于 NULL。

如果在任何部分关闭函数分配失败,函数应该return 4.

对扩展名为“.bin”且堆限制为 return 的文件进行了测试,此错误:

Function should return 4, but it returned 0.

我使用像 **ptr 这样的符号,因为我不允许使用方括号。

谁能帮助我如何使我的函数 return 成为正确的整数。我的功能如下:

int load(const char *filename, int ***ptr, enum save_format_t format) {
    if (filename == NULL || ptr == NULL || format != 0 && format != 1) {
        return 1;
    }
    int val = 0;
    int **temp = NULL;
    FILE *fp, *pp;
    if (format == 0) {
        int i = 0, x = 0, h = 0, w = 0;
        fp = fopen(filename, "r");
        if (fp == NULL) {
            return 2;
        }
        pp = fopen(filename, "r");
        if (pp == NULL) {
            fclose(fp);
            return 2;
        }
        int val2 = 0;
        while (1) {
            if (fscanf(fp, "%d", &val2) != 1) {
                if (i == 0 || val != -1) {
                    fclose(fp);
                    fclose(pp);
                    return 3;
                }
                break;
            }
            val = val2;
            if (val == -1) {
                h++;
            }
            i++;
        }
        if (i == h) {
            fclose(fp);
            fclose(pp);
            return 3;
        }
        i = 0;
        fseek(fp, 0, SEEK_SET);
        temp = malloc(sizeof(temp) * (h + 1));
        if (temp == NULL) {
            fclose(fp);
            fclose(pp);
            return 4;
        }
        *(temp + h) = NULL;
        for (i = 0; i < h; i++) {
            val = 0, w = 0;
            while (val != -1) {
                if (fscanf(pp, "%d", &val) == EOF) {
                    break;
                }
                w++;
            }
            if (*(temp + i) != NULL) {
                *(temp + i) = (int *)malloc(sizeof(int) * w);
                if (*(temp + i) == NULL) {
                    for (int s = 0; s < i; s++) {
                        free(*(temp + s));
                    }
                    free(temp);
                    fclose(pp);
                    fclose(fp);
                    return 4;
                }
            } else {
                fclose(fp);
                fclose(pp);
                free(temp);
                return 0;
            }
            for (x = 0; x < w; x++) {
                fscanf(fp, "%d", *(temp + i) + x);
            }
        }
        fclose(fp);
        fclose(pp);
    }
    *ptr = temp;
    return 0;
}

考虑读取字符串并使用 strtol 进行解析。
当没有可用的 RAM 时,内存分配将 return NULL。

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

int load ( char const *filename, int ***ptr) {
    if ( filename == NULL || ptr == NULL) {
        return 1;
    }
    char entry[100] = "";
    char *end = NULL;
    int **temp = NULL;
    int *temprow = NULL;
    long int val = 0;
    int rows = 0;
    int cols = 0;
    int problem = 0;
    int result = 0;
    FILE* fp = NULL;

    fp = fopen ( filename, "r");
    if ( fp == NULL) {
        perror ( filename);
        return 2;
    }

    while ( 1 == ( result = fscanf ( fp, "%99s", entry))) {
        if ( -1 == val || ( 0 == rows && 0 == cols)) {
            if ( -1 == val) {
                ++rows;
            }
            if ( NULL == ( temp = realloc ( *ptr, sizeof **ptr * ( rows + 2)))) {
                fprintf ( stderr, "problem realloc *ptr\n");
                problem = 4;
                break;
            }
            *ptr = temp;
            *( ( *ptr) + rows) = NULL;
            *( ( *ptr) + rows + 1) = NULL;//sentinel

            cols = 0;
        }
        errno = 0;
        val = strtol ( entry, &end, 10);
        if ( entry == end) {//nothing could be parsed to int
            problem = 3;
            break;
        }
        else if ( 0 != *end) {//extra characters after int
            problem = 3;
            break;
        }
        if ( ( errno == ERANGE && ( val == LONG_MAX || val == LONG_MIN))
        || ( errno != 0 && val == 0)) {// parsing error from strtol
            perror ( "input error");
            problem = 3;
            break;
        }
        if ( val > INT_MAX || val < INT_MIN) {
            problem = 3;
            break;
        }
        if ( NULL == ( temprow = realloc ( *( ( *ptr) + rows), sizeof ***ptr * ( cols + 2)))) {
            fprintf ( stderr, "problem realloc *( (*ptr) + row)\n");
            problem = 4;
            break;
        }
        *( ( *ptr) + rows) = temprow;
        ++cols;
        *( *( ( *ptr) + rows)) = cols;//save cols in index 0
        *( *( ( *ptr) + rows) + cols) = val;
    }
    fclose(fp);
    if ( 0 == result) {
        problem = 3;
    }
    return problem;
}

int main ( void) {
    char const *filename = "ints.txt";
    int **array = NULL;
    int row = 0;
    int each = 0;

    load ( filename, &array);

    row = 0;
    while ( array && ( *(array + row))) {
        each = 0;
        while ( each <= *( *(array + row))) {
            printf ( "%d\n", *( *(array + row) + each));
            ++each;
        }
        ++row;
    }

    row = 0;
    while ( array && ( *(array + row))) {
        free ( *(array + row));
        ++row;
    }
    free ( array);

    return 0;
}

您的代码中存在多个问题:

  • if (i == h) 似乎不正确:如果文件包含带有 -1 终止符的单行,换句话说是空矩阵怎么办?
  • temp = malloc(sizeof(temp) * (h + 1)); 应该是 temp = malloc(sizeof(*temp) * (h + 1));
  • if (*(temp + i) != NULL) { 读取由 malloc() 分配的数组中的未初始化条目。应该删除测试,您应该始终分配行。

这是修改后的版本:

int load(const char *filename, int ***ptr, enum save_format_t format) {
    if (filename == NULL || ptr == NULL || format != 0 && format != 1) {
        return 1;
    }
    int **temp = NULL;
    FILE *fp, *pp;
    if (format == 0) {
        int i = 0, x = 0, h = 0, w = 0, val = 0;
        fp = fopen(filename, "r");
        if (fp == NULL) {
            return 2;
        }
        pp = fopen(filename, "r");
        if (pp == NULL) {
            fclose(fp);
            return 2;
        }
        // determine the number of rows
        val = 0;
        while (fscanf(fp, "%d", &val) == 1) {
            if (val == -1)
                h++;
        }
        if (val != -1) {
            // empty file or file does not end with -1
            fclose(fp);
            fclose(pp);
            return 3;
        }
        temp = malloc(sizeof(*temp) * (h + 1));
        if (temp == NULL) {
            fclose(fp);
            fclose(pp);
            return 4;
        }
        fseek(fp, 0, SEEK_SET);
        for (i = 0; i < h; i++) {
            w = 0;
            while (fscanf(pp, "%d", &val) == 1) {
                w++;
                if (val == -1)
                    break;
            }
            if (w == 0 || (*(temp + i) = malloc(sizeof(int) * w)) == NULL) {
                while (i-- > 0) {
                    free(*(temp + i));
                }
                free(temp);
                fclose(pp);
                fclose(fp);
                return 4;
            }
            for (x = 0; x < w; x++) {
                fscanf(fp, "%d", *(temp + i) + x);
            }
        }
        *(temp + h) = NULL;
        fclose(fp);
        fclose(pp);
    }
    *ptr = temp;
    return 0;
}