Не работает односвязный список списков в си

Мне надо сделать список списков в си реализованной структурой, но он ничего не сохраняет. Каждый раз, когда пытаюсь добавить новый элемент ко списку, список обнуляется. Остальной код работает корректно. Нужные данные правильно считываются из файла.

#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 шт):

Автор решения: avp

Я немного не понял вначале ваш алгоритм (то, что вы сразу создаете в 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$ 

Надеюсь, это поможет вам.

→ Ссылка