c-SIGABRT和损坏的双链表



我正在做一个学校项目,需要从文件中获取矩阵的信息(高度、宽度、单元格状态)。类似这样的东西:

30 40    /*height and width*/
3        /*nr of lines to read from the file*/
10 11 1  /*coordinates, and cell status (0,1,2)*/
10 12 1
10 13 2

出于某种原因,它一直在调试器或损坏的双链接列表中给我SIGABRT。我知道代码并没有尽可能完美,但我开始修改它,看看是否能找到问题。

这是我的代码:

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int ***getFileLoad(char *fileName)
{
    char strLines[5], strColumns[5], strCells[5], strTemp[3];
    int i = 0, j = 0, k = 0, l = 0, lines = 0, columns = 0, cells = 0, intTemp = 0;
    int ***array = NULL;
    FILE *file = NULL;
    file = fopen(fileName, "r"); /*opens file*/
    if (file == NULL)
    {
        printf("Error opening file!n");
        exit(EXIT_FAILURE);
    }
    fscanf(file, "%s %s %s", &strLines, &strColumns, &strCells);
    lines = atoi(strLines);
    if (lines <= 0) /*lines*/
    {
        printf("Invalid value, lines!");
        exit(EXIT_FAILURE);
    }
    columns = atoi(strColumns);
    if (columns <= 0)  /*columns*/
    {
        printf("Invalid value, columns!");
        exit(EXIT_FAILURE);
    }
    cells = atoi(strCells);
    if (cells <= 0)  /*cells*/
    {
        printf("Invalid value, cells!");
        exit(EXIT_FAILURE);
    }
    array = (int ***)malloc(sizeof(int **) * lines); /*allocating lines*/
    if (array == NULL)
    {
        printf("No memory!");
        exit(EXIT_FAILURE);
    }
    for (i = 0; i < columns; i++)            /*allocating columns*/
    {
        array[i] = (int **)malloc(sizeof(int *) * columns);
        if (array[i] == NULL)
        {
            printf("No memory!");
            for (j = 0; j < i; j++)
            {
                free(array[j]);
            }
            free(array);
            array = NULL;
            exit(EXIT_FAILURE);
        }
    }
    for (i = 0; i < lines; i++)            /*allocating nr of cells*/
    {
        for (j = 0; j < columns; j++)
        {
            array[i][j] = (int *)malloc(sizeof(int) * cells);
            if (array[i][j] == NULL)
            {
                printf("No memory!");
                for (k = 0; k < i; k++)
                {
                    for (l = 0; l < j; l++)
                    {
                        free(array[k][l]);
                    }
                }
                for (k = 0; k < i; k++)
                {
                    free(array[k]);
                }
                free(array);
                array = NULL;
                exit(EXIT_FAILURE);
            }
        }
    }
    array[0][0][0] = lines;
    array[0][0][1] = columns;
    array[0][0][2] = cells;
    for (i = 0; i < 1; i++)         /*nr arrays*/
    {
        for (j = 1; j < cells + 1; j++) /*nr cells*/
        {
            for (k = 0; k < 4; k++) /*values from file*/
            {
                if (k == 3)         /*getting to the next line*/
                {
                    intTemp = fgetc(file);
                    if (intTemp == 'n' || intTemp == EOF)
                    {
                        continue;
                    }
                    else
                    {
                        while (intTemp != 'n' || intTemp != EOF)
                        {
                            intTemp = fgetc(file);
                            if (intTemp == 'n' || intTemp == EOF)
                            {
                                break;
                            }
                        }
                    }
                }
                else
                {
                    fscanf(file, "%s", strTemp);
                    if (isdigit(strTemp))
                    {
                        intTemp = atoi(strTemp);
                        if (k == 0)         /*accepting lines with values between1->lines*/
                        {
                            if (!(intTemp >= 1 && intTemp < lines))
                            {
                                printf("Invalid value!");
                                exit(EXIT_FAILURE);
                            }
                            else
                            {
                                array[i][j][k] = intTemp;
                            }
                        }
                        else if (k == 1)    /*accepting columns with values between 1->columns*/
                        {
                            if (!(intTemp >= 1 && intTemp < columns))
                            {
                                printf("Invalid value!");
                                exit(EXIT_FAILURE);
                            }
                            else
                            {
                                array[i][j][k] = intTemp;
                            }
                        }
                        else if (k == 2)    /*accepting cells with values between 0->2*/
                        {
                            if (!(intTemp >= 0 && intTemp < 3))
                            {
                                printf("Invalid value!");
                                exit(EXIT_FAILURE);
                            }
                            else
                            {
                                array[i][j][k] = intTemp;
                            }
                        }
                    }
                }
            }
        }
    }
    intTemp = fgetc(file); /*checking for EOF*/
    if (intTemp != EOF)
    {
        printf("Impossible reading every value!");
        exit(EXIT_FAILURE);
    }
    fclose(file);
    return array;
}

基本问题与这些类型的问题通常相同-你的任务对自己来说太复杂了,原因是:

  • 在一个巨大的函数中填充太多,而不是将其分解为可消化的片段

  • 使用像fscanf()fgetc() 这样笨拙的文件读取功能

  • 重复代码,包括可以转移到单独功能的错误检查代码

所有这些都使得跟踪你正在做的事情变得极其困难,因为你庞大的函数读起来像意大利面条,而你对它没有全局的看法。它变成了一大堆代码,任何一个都可能是错误的。

以下是一些操作的示例,您可以也应该具有单独的功能:

  • 创建矩阵

  • 摧毁你的矩阵

  • 设置矩阵单元格的值

  • 获取矩阵单元格的值

  • 从文件中获取一组坐标

  • 从文件中获取尺寸

  • 从文件中获取行数

此外,您应该将相关值封装在数据结构中,例如矩阵的维度(以及矩阵数据本身的维度)和坐标。

下面是一个更好的编写方法的快速示例。例如,看看main()函数,看看它有多容易理解。如果你的代码很容易理解,那么它就很容易维护,也更容易发现(和避免)错误。

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define MAX_LINE_LENGTH 1024

/*  Holds dimensions for a matrix  */
struct dimensions {
    int lines;
    int columns;
    int cells;
};

/*  Holds a set of three-dimensional coordinates  */
struct coords {
    int x;
    int y;
    int z;
};

/*  Holds a three-dimensional matrix  */
struct matrix {
    struct dimensions dim;
    int *** lines;
};
void * xmalloc(const size_t sz);
void * xcalloc(const size_t nmemb, const size_t size);
struct matrix * matrixCreate(struct dimensions * dim);
void matrixDestroy(struct matrix * matrix);
void matrixSet(struct matrix * matrix, struct coords coord, const int value);
int matrixGet(struct matrix * matrix, struct coords coord);
FILE * openDataFile(const char * filename);
void getLineFromFile(FILE * fp, char * buffer, const size_t length);
struct dimensions getDimensionsFromFile(FILE * fp);
struct coords getCoordsFromFile(FILE * fp);
void validateCoords(struct matrix * matrix, struct coords coords);
int getSingleIntegerLine(FILE * fp);
int main(void)
{
    /*  Set up matrix and data file  */
    FILE * fp = openDataFile("matrix.dat");
    struct dimensions dim = getDimensionsFromFile(fp);
    const int numLines = getSingleIntegerLine(fp);
    struct matrix * matrix = matrixCreate(&dim);

    /*  Populate matrix cells specified in file  */
    for ( size_t i = 0; i < numLines; ++i ) {
        struct coords coords = getCoordsFromFile(fp);
        validateCoords(matrix, coords);
        matrixSet(matrix, coords, 1);
    }

    /*  Test and print the value of some matrix cells  */
    struct coords coords[6] = {
        {10, 11, 1},
        {10, 11, 2},
        {10, 12, 1},
        {10, 12, 2},
        {10, 13, 1},
        {10, 13, 2}
    };
    for ( size_t i = 0; i < 6; ++i ) {
        const int value = matrixGet(matrix, coords[i]);
        printf("Value at %d, %d, %d: %dn",
               coords[i].x, coords[i].y, coords[i].z, value);
    }

    /*  Clean up and exit  */
    matrixDestroy(matrix);
    fclose(fp);
    return 0;
}
void * xmalloc(const size_t sz)
{
    void * p = malloc(sz);
    if ( !p ) {
        perror("couldn't allocate memory");
        exit(EXIT_FAILURE);
    }
    return p;
}
void * xcalloc(const size_t nmemb, const size_t size)
{
    void * p = calloc(nmemb, size);
    if ( !p ) {
        perror("couldn't allocate memory");
        exit(EXIT_FAILURE);
    }
    return p;
}
struct matrix * matrixCreate(struct dimensions * dim)
{
    int *** lines = xmalloc(dim->lines * sizeof *lines);
    for ( size_t i = 0; i < dim->lines; ++i ) {
        int ** columns = xmalloc(dim->columns * sizeof *columns);
        for ( size_t j = 0; j < dim->columns; ++j ) {
            int * cells = xcalloc(dim->cells, sizeof *cells);
            columns[j] = cells;
        }
        lines[i] = columns;
    }
    struct matrix * matrix = xmalloc(sizeof *matrix);
    matrix->lines = lines;
    matrix->dim = *dim;
    return matrix;
}
void matrixDestroy(struct matrix * matrix)
{
    for ( size_t i = 0; i < matrix->dim.lines; ++i ) {
        for ( size_t j = 0; j < matrix->dim.columns; ++j ) {
            free(matrix->lines[i][j]);
        }
        free(matrix->lines[i]);
    }
    free(matrix->lines);
    free(matrix);
}
void matrixSet(struct matrix * matrix, struct coords coords, const int value)
{
    matrix->lines[coords.x][coords.y][coords.z] = value;
}
int matrixGet(struct matrix * matrix, struct coords coords)
{
    return matrix->lines[coords.x][coords.y][coords.z];
}
FILE * openDataFile(const char * filename)
{
    FILE * fp = fopen(filename, "r");
    if ( !fp ) {
        perror("couldn't open file");
        exit(EXIT_FAILURE);
    }
    return fp;
}
void getLineFromFile(FILE * fp, char * buffer, const size_t length)
{
    if ( !fgets(buffer, length, fp) ) {
        fprintf(stderr, "Couldn't read dimensions from file.n");
        exit(EXIT_FAILURE);
    }
}
struct dimensions getDimensionsFromFile(FILE * fp)
{
    char buffer[MAX_LINE_LENGTH];
    getLineFromFile(fp, buffer, MAX_LINE_LENGTH);
    struct dimensions dim;
    if ( sscanf(buffer, "%d %d", &dim.lines, &dim.columns) != 2 ) {
        fprintf(stderr, "Couldn't read dimensions from file.n");
        exit(EXIT_FAILURE);
    } 
    dim.cells = 3;
    return dim;
}
struct coords getCoordsFromFile(FILE * fp)
{
    char buffer[MAX_LINE_LENGTH];
    getLineFromFile(fp, buffer, MAX_LINE_LENGTH);
    struct coords coords;
    if ( sscanf(buffer, "%d %d %d", &coords.x, &coords.y, &coords.z) != 3 ) {
        fprintf(stderr, "Couldn't read coordinates from file.n");
        exit(EXIT_FAILURE);
    } 
    return coords;
}
void validateCoords(struct matrix * matrix, struct coords coords)
{
    bool valid = true;
    if ( coords.x < 0 || coords.x >= matrix->dim.lines ) {
        fprintf(stderr, "Invalid x coordinate: %dn", coords.x);
        valid = false;
    }
    if ( coords.y < 0 || coords.y >= matrix->dim.columns ) {
        fprintf(stderr, "Invalid y coordinate: %dn", coords.y);
        valid = false;
    }
    if ( coords.z < 0 || coords.z >= matrix->dim.cells ) {
        fprintf(stderr, "Invalid z coordinate: %dn", coords.z);
        valid = false;
    }
    if ( !valid ) {
        exit(EXIT_FAILURE);
    }
}
int getSingleIntegerLine(FILE * fp)
{
    char buffer[MAX_LINE_LENGTH];
    getLineFromFile(fp, buffer, MAX_LINE_LENGTH);
    int value;
    if ( sscanf(buffer, "%d", &value) != 1 ) {
        fprintf(stderr, "Couldn't read single value from file.n");
        exit(EXIT_FAILURE);
    } 
    return value;
}

使用您的示例文件:

paul@thoth:~/src/sandbox$ ./matrix
Value at 10, 11, 1: 1
Value at 10, 11, 2: 0
Value at 10, 12, 1: 1
Value at 10, 12, 2: 0
Value at 10, 13, 1: 0
Value at 10, 13, 2: 1
paul@thoth:~/src/sandbox$ 

我不确定,但当变量j引用的数组大小为i3时,您可以将其从0循环到3。可能来自:的长宁86号线

for (j = 1; j<cells + 1; j++) {   /*nr cells*/

至:

for (j = 1; j<cells; j++) {   /*nr cells*/

将解决问题。

相关内容

  • 没有找到相关文章

最新更新