Не работает односвязный список списков в си
Мне надо сделать список списков в си реализованной структурой, но он ничего не сохраняет. Каждый раз, когда пытаюсь добавить новый элемент ко списку, список обнуляется. Остальной код работает корректно. Нужные данные правильно считываются из файла.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include <stdio.h>
#define MAX_SIZE_OF_MATRIX 3
#define MAX_SIZE_OF_VAL 4
typedef struct STR {
int Val;
int Row;
struct STR* Next;
} STR;
typedef struct ListSTR {
STR* row;
struct ListSTR* Next;
} ListSTR;
void Add(STR** point, int Val, int Row) {
if (*point == NULL) {
*point = (STR*)malloc(sizeof(STR));
(*point)->Row =Row;
(*point)->Val = Val;
(*point)->Next = NULL;
return 0;
}
while ((*point)->Next != NULL) {
(*point) = (*point)->Next;
}
(*point)->Next = (STR*)malloc(sizeof(STR));
(*point)->Next->Val = Val;
(*point)->Next->Row = Row;
(*point)->Next->Next = NULL;
}
void AddToIndex(ListSTR** matrix, int index, int Val, int Row) {
for (int i = 0; i < index; i++) {
if ((*matrix)->Next != NULL) {
(*matrix) = (*matrix)->Next;
}
else {
printf("Error");
exit(1);
}
}
STR* point = (*matrix)->row;
if (point == NULL) {
point = (STR*)malloc(sizeof(STR));
point->Row = Row;
point->Val = Val;
point->Next = NULL;
return 0;
}
while (point->Next != NULL) {
point = point->Next;
}
point->Next = (STR*)malloc(sizeof(STR));
point->Next->Val = Val;
point->Next->Row = Row;
point->Next->Next = NULL;
}
void clean(STR* point) {
STR* start = point->Next;
while (start != NULL) {
STR* next = start->Next;
free(start);
start = next;
}
free(point);
}
int isNum(char c) {
switch (c) {
case '1':
return 1;
case '2':
return 1;
case '3':
return 1;
case '4':
return 1;
case '5':
return 1;
case '6':
return 1;
case '7':
return 1;
case '8':
return 1;
case '9':
return 1;
case '0':
return 1;
default:
return 0;
}
}
int isWhitespace(char c) {
switch (c) {
case' ':
return 1;
case'\n':
return 1;
case'\0':
return 1;
default:
return 0;
}
}
void GetRowsAndColums(char* filename, int* ROWS, int* COLUMNS) {
FILE* fp = fopen(filename, "r");
char rows[MAX_SIZE_OF_MATRIX];
char c;
while (isWhitespace(c = getc(fp))) {}
int i = 0;
while (1) {
i = 0;
if (isNum(c)) {
rows[i] = c;
i++;
}
else if (isWhitespace(c)) {
if (c == '\n') {
printf("Error");
exit(1);
}
*ROWS = strtol(rows, NULL, 10);
break;
}
else {
printf("Error");
exit(1);
}
c = getc(fp);
}
while (isWhitespace(c = getc(fp))) {}
char column[MAX_SIZE_OF_MATRIX];
i = 0;
while (1) {
i = 0;
if (isNum(c)) {
column[i] = c;
i++;
}
else if (isWhitespace(c)) {
*COLUMNS = strtol(column, NULL, 10);
break;
}
else {
printf("Error");
exit(1);
}
c = getc(fp);
}
fclose(fp);
}
void TestAdd(ListSTR* matrix) {
for (int i = 0; i < 3; i++) {
matrix->row = (STR*)malloc(sizeof(STR));
matrix->row->Row = i;
matrix->row->Val = i + 1;
matrix->row->Next = NULL;
matrix = matrix->Next;
}
}
void printMatrix(ListSTR* matrix, int ROWS, int COLUMNS) {
STR* point;
for (int i = 0; i < ROWS; i++) {
point = matrix->row;
int lastRow = 0;
for (int j = 0; j < COLUMNS; j++) {
if (point == NULL) {
for (int k = 1; k <= COLUMNS - lastRow; k++) {
printf("0 ");
}
break;
}
int Val = point->Val;
int Row = point->Row;
if (Row == 0) {
printf("%d ", Val);
}
else if (Row >= COLUMNS) {
printf("Error");
exit(1);
}
else if (Row - lastRow >= 1) {
for (int k = 1; k <= Row - lastRow; k++) {
printf("0 ");
}
printf("%d ", Val);
lastRow = Row;
}
else if (Row <= lastRow) {
printf("Error");
exit(1);
}
else {
printf("%d ", Val);
}
point = point->Next;
}
printf("\n");
matrix = matrix->Next;
}
}
void Initialize(ListSTR* matrix, int ROWS) {
for (int i = 0; i < ROWS; i++) {
matrix->row = NULL;
matrix->Next = malloc(sizeof(ListSTR));
matrix = matrix->Next;
}
}
void ReadMatrix(ListSTR** matrix, int ROWS, int COLUMNS, char* filename) {
FILE* fp = fopen(filename, "r");
char c;
int count = 0;
while(c=getc(fp)!='\n'){}
while (1) {
while (1) {
while (isWhitespace(c = getc(fp))) {}
int i = 0;
char val[MAX_SIZE_OF_VAL];
int value;
int row;
while (1) {
if (c == '-' && i == 0) {
val[i] = c;
i++;
}
else if (isNum(c)) {
val[i] = c;
i++;
}
else if (isWhitespace(c)) {
if (c == '\n') {
printf("Error");
exit(1);
}
value = strtol(val, NULL, 10);
break;
}
else {
printf("Error");
exit(1);
}
c = getc(fp);
}
while (isWhitespace(c = getc(fp))) {}
char rows[MAX_SIZE_OF_MATRIX];
i = 0;
while (1) {
if (isNum(c)) {
rows[i] = c;
i++;
}
else if (isWhitespace(c)) {
row = strtol(rows, NULL, 10);
if (row >= ROWS) {
printf("Error");
exit(1);
}
break;
}
else if (c == EOF) {
row = strtol(rows, NULL, 10);
if (row >= ROWS) {
printf("Error");
exit(1);
}
break;
}
else {
printf("Error");
exit(1);
}
c = getc(fp);
}
Add((*matrix)->row, value, row);
if (c == '\n' || c==EOF) {
break;
}
}
count++;
if (count >= ROWS) {
break;
}
(*matrix) = (*matrix)->Next;
}
fclose(fp);
}
int Main() {
int ROWS, COLUMNS;
char* file = "Text.txt";
GetRowsAndColums(file, &ROWS, &COLUMNS);
ListSTR* matrix = malloc(sizeof(ListSTR));
Initialize(matrix, ROWS);
//ListSTR* result = malloc(sizeof(ListSTR));
//Initialize(result, COLUMNS);
ReadMatrix(&matrix, ROWS, COLUMNS, file);
printMatrix(matrix, ROWS, COLUMNS);
return 0;
}
Вот текстовый файл
3 3
1 0 7 2
-3 2
10 0 4 1
Ответы (1 шт):
Я немного не понял вначале ваш алгоритм (то, что вы сразу создаете в Initialize() весь список строк, а не добавляете их динамически по мере чтения файла в ReadMatrix()), поэтому поотлаживав ваш код понял, что ошибся в некоторых комментариях.
Я так и не понял, что именно вы печатаете в функции printMatrix(), но добавив свой код (ниже он закоментирован) убедился, что матрица строится верно.
У вас также были ошибки при чтении чисел из файла. Вы не записывали после чтения последней цифры завершающий строку nil. Я это подправил, записывая в строку nil после каждой прочитанной цифры.
Также я переписал функцию Add(), imho она стала проще (по крайней мере теперь в ней нет повторов кода).
Не знаю, в какой ОС вы пишете, но у себя (в Линуксе) я заменил Main() на main().
Вот что получилось в результате (ваши строки, которые я заменял, я закомменировал вот так -- ////):
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include <stdio.h>
#define MAX_SIZE_OF_MATRIX 3
#define MAX_SIZE_OF_VAL 4
typedef struct STR {
int Val;
int Row;
struct STR* Next;
} STR;
typedef struct ListSTR {
STR* row;
struct ListSTR* Next;
} ListSTR;
void Add(STR** point, int Val, int Row) {
/*
if (*point == NULL) {
*point = (STR*)malloc(sizeof(STR));
(*point)->Row =Row;
(*point)->Val = Val;
(*point)->Next = NULL;
return;
}
while ((*point)->Next != NULL) {
(*point) = (*point)->Next;
}
(*point)->Next = (STR*)malloc(sizeof(STR));
(*point)->Next->Val = Val;
(*point)->Next->Row = Row;
(*point)->Next->Next = NULL;
*/
STR *t = malloc(sizeof(STR));
t->Row = Row;
t->Val = Val;
t->Next = NULL;
STR **p = point;
if (*p)
for (p = &(*p)->Next; *p; p = &(*p)->Next);
*p = t;
}
void AddToIndex(ListSTR** matrix, int index, int Val, int Row) {
for (int i = 0; i < index; i++) {
if ((*matrix)->Next != NULL) {
(*matrix) = (*matrix)->Next;
}
else {
printf("Error");
exit(1);
}
}
STR* point = (*matrix)->row;
if (point == NULL) {
point = (STR*)malloc(sizeof(STR));
point->Row = Row;
point->Val = Val;
point->Next = NULL;
//// return 0;
return;
}
while (point->Next != NULL) {
point = point->Next;
}
point->Next = (STR*)malloc(sizeof(STR));
point->Next->Val = Val;
point->Next->Row = Row;
point->Next->Next = NULL;
}
void clean(STR* point) {
STR* start = point->Next;
while (start != NULL) {
STR* next = start->Next;
free(start);
start = next;
}
free(point);
}
int isNum(char c) {
switch (c) {
case '1':
return 1;
case '2':
return 1;
case '3':
return 1;
case '4':
return 1;
case '5':
return 1;
case '6':
return 1;
case '7':
return 1;
case '8':
return 1;
case '9':
return 1;
case '0':
return 1;
default:
return 0;
}
}
int isWhitespace(char c) {
switch (c) {
case' ':
return 1;
case'\n':
return 1;
case'\0':
return 1;
default:
return 0;
}
}
void GetRowsAndColums(char* filename, int* ROWS, int* COLUMNS) {
FILE* fp = fopen(filename, "r");
char rows[MAX_SIZE_OF_MATRIX];
char c;
while (isWhitespace(c = getc(fp))) {}
int i = 0;
while (1) {
i = 0;
if (isNum(c)) {
//// rows[i] = c;
//// i++;
rows[i++] = c; rows[i] = 0;
}
else if (isWhitespace(c)) {
if (c == '\n') {
printf("Error");
exit(1);
}
*ROWS = strtol(rows, NULL, 10);
break;
}
else {
printf("Error");
exit(1);
}
c = getc(fp);
}
while (isWhitespace(c = getc(fp))) {}
char column[MAX_SIZE_OF_MATRIX];
i = 0;
while (1) {
i = 0;
if (isNum(c)) {
//// column[i] = c;
//// i++;
column[i++] = c; column[i] = 0;
}
else if (isWhitespace(c)) {
*COLUMNS = strtol(column, NULL, 10);
break;
}
else {
printf("Error");
exit(1);
}
c = getc(fp);
}
fclose(fp);
}
void TestAdd(ListSTR* matrix) {
for (int i = 0; i < 3; i++) {
matrix->row = (STR*)malloc(sizeof(STR));
matrix->row->Row = i;
matrix->row->Val = i + 1;
matrix->row->Next = NULL;
matrix = matrix->Next;
}
}
void printMatrix(ListSTR* matrix, int ROWS, int COLUMNS) {
/*
for (ListSTR *mx = matrix; mx; mx = mx->Next) {
for (STR *point = mx->row; point; point = point->Next)
printf("%p: %d %d ", point, point->Val, point->Row);
puts("");
}
puts("");
*/
STR* point;
for (int i = 0; i < ROWS; i++) {
point = matrix->row;
int lastRow = 0;
for (int j = 0; j < COLUMNS; j++) {
if (point == NULL) {
for (int k = 1; k <= COLUMNS - lastRow; k++) {
printf("0 ");
}
break;
}
int Val = point->Val;
int Row = point->Row;
if (Row == 0) {
printf("%d ", Val);
}
else if (Row >= COLUMNS) {
printf("Error");
exit(1);
}
else if (Row - lastRow >= 1) {
for (int k = 1; k <= Row - lastRow; k++) {
printf("0 ");
}
printf("%d ", Val);
lastRow = Row;
}
else if (Row <= lastRow) {
printf("Error");
exit(1);
}
else {
printf("%d ", Val);
}
point = point->Next;
}
printf("\n");
matrix = matrix->Next;
}
}
void Initialize(ListSTR* matrix, int ROWS) {
for (int i = 0; i < ROWS; i++) {
matrix->row = NULL;
matrix->Next = malloc(sizeof(ListSTR));
matrix = matrix->Next;
}
}
////void ReadMatrix(ListSTR** matrix, int ROWS, int COLUMNS, char* filename) {
void ReadMatrix(ListSTR *matrix, int ROWS, int COLUMNS, char* filename) {
FILE* fp = fopen(filename, "r");
char c;
int count = 0;
while(c=getc(fp)!='\n'){}
while (1) {
while (1) {
while (isWhitespace(c = getc(fp))) {}
int i = 0;
char val[MAX_SIZE_OF_VAL];
int value;
int row;
while (1) {
if (c == '-' && i == 0) {
//// val[i] = c;
//// i++;
val[i++] = c; val[i] = 0;
}
else if (isNum(c)) {
//// val[i] = c;
//// i++;
val[i++] = c; val[i] = 0;
}
else if (isWhitespace(c)) {
if (c == '\n') {
printf("Error");
exit(1);
}
value = strtol(val, NULL, 10);
break;
}
else {
printf("Error");
exit(1);
}
c = getc(fp);
}
while (isWhitespace(c = getc(fp))) {}
char rows[MAX_SIZE_OF_MATRIX];
i = 0;
while (1) {
if (isNum(c)) {
//// rows[i] = c;
//// i++;
rows[i++] = c; rows[i] = 0;
}
else if (isWhitespace(c)) {
row = strtol(rows, NULL, 10);
if (row >= ROWS) {
printf("Error");
exit(1);
}
break;
}
else if (c == EOF) {
row = strtol(rows, NULL, 10);
if (row >= ROWS) {
printf("Error");
exit(1);
}
break;
}
else {
printf("Error");
exit(1);
}
c = getc(fp);
}
//// Add((*matrix)->row, value, row);
Add(&(matrix->row), value, row);
if (c == '\n' || c==EOF) {
break;
}
}
count++;
if (count >= ROWS) {
break;
}
//// (*matrix) = (*matrix)->Next;
matrix = matrix->Next;
}
fclose(fp);
}
void *
FreeMatrix (ListSTR *matrix)
{
ListSTR *next = 0;
for (ListSTR *mx = matrix; mx; mx = next) {
STR *next_p = 0;
for (STR *point = mx->row; point; point = next_p) {
next_p = point->Next;
free(point);
}
next = mx->Next;
free(mx);
}
return 0;
}
////int Main() {
int main() {
int ROWS, COLUMNS;
char* file = "Text.txt";
GetRowsAndColums(file, &ROWS, &COLUMNS);
ListSTR* matrix = malloc(sizeof(ListSTR));
Initialize(matrix, ROWS);
//ListSTR* result = malloc(sizeof(ListSTR));
//Initialize(result, COLUMNS);
//// ReadMatrix(&matrix, ROWS, COLUMNS, file);
ReadMatrix(matrix, ROWS, COLUMNS, file);
printMatrix(matrix, ROWS, COLUMNS);
matrix = FreeMatrix(matrix);
return 0;
}
Функции, которые в данном примере не вызываются, например, AddToIndex() я вообще не смотрел (т.е. не знаю, правильный там код или нет).
Пример запуска с вашими данными (и добавленной мной печатью матрицы, как она построена в памяти):
avp@avp-desktop:~/avp/hashcode$ gcc tt2.c && ./a.out
0x55893face520: 1 0 0x55893face540: 7 2
0x55893face560: -3 2
0x55893face580: 10 0 0x55893face5a0: 4 1
1 0 0 7 0
0 0 -3 0
10 0 4 0 0
avp@avp-desktop:~/avp/hashcode$
Надеюсь, это поможет вам.