gpt4 book ai didi

c - SIGABRT 和损坏的双链表

转载 作者:行者123 更新时间:2023-11-30 15:13:17 25 4
gpt4 key购买 nike

我正在开展一个学校项目,我需要从文件中获取矩阵的信息(高度、宽度、单元格状态)。像这样的事情:

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: %d\n",
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: %d\n", coords.x);
valid = false;
}

if ( coords.y < 0 || coords.y >= matrix->dim.columns ) {
fprintf(stderr, "Invalid y coordinate: %d\n", coords.y);
valid = false;
}

if ( coords.z < 0 || coords.z >= matrix->dim.cells ) {
fprintf(stderr, "Invalid z coordinate: %d\n", 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$

关于c - SIGABRT 和损坏的双链表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34713665/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com