C - передача массива в узел связанного списка

У меня есть 2D-массив, уже заполненный целыми числами, готовый к разрезанию на строки и обработке, и мне нужно, чтобы каждая строка (1D-массив) передавалась узлу связанного списка. Каждый узел выглядит так:

struct node {
    int *val;
    struct node *next;
};

Новые узлы добавляются и связываются следующим образом:

struct node *addnode(int *val, struct node *next, int columns)
{
    struct node *tnode;
    tnode = (struct node*)malloc(sizeof(*tnode));
    if(tnode != NULL) {
        tnode->val = malloc(sizeof(int) * columns);
        memcpy(tnode->val, val, sizeof(int) * columns);
        tnode->val = val;
        tnode->next = next;
    };
    return tnode;
}

Фрагмент программы, который будет заполнять каждый узел, выглядит примерно так:

int table[rows][columns], i, j;
for (i = 0; i < rows; i++){
    head = addnode(*table, head, columns);
    for (j = 0; j < columns; j++){
        scanf("%d",&table[i][j]);
        head->val[j] = table[j];
        printf("%d ",head->val[j]);
    };
    puts("\n");
};  

Я не уверен, как действовать в указанных местах:

  1. Это malloc для всего узла, но что мне делать с malloc для val? Я знаю длину таблицы, которая должна быть в каждом узле, и это columns, полученное в основной функции. Где я должен выделить память для него?
  2. Выше этой строки находится место, где я выделил достаточно (columns) памяти для одной строки целых чисел. Это хороший выбор?
  3. Это, с предшествующим циклом, должно заполнить текущий head->val[j] адекватной i-строкой 2D-массива table, но это выглядит слишком хорошо, чтобы быть правдой. Можно я так оставлю?

РЕДАКТИРОВАТЬ: Я исправил его в некоторых местах, но затем после попытки сортировки он возвращает мусор. Я просто выкину сюда большую часть кода:

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

struct node {
    int *val;
    struct node *next;
};

struct node *addnode(int *val, struct node *next, int columns);
struct node *mergesort(struct node *head, int column);
struct node *merge(struct node *head_one, struct node *head_two, int column);

int main(int argc, char *argv[])
{

    struct node *head;
    struct node *current;
    struct node *next;
    int symbol = 0;
    int columns = 0;
    //int columns = atoi(argv[1]); //until sorting works, I'll keep it at 0
    int rows = 0;
    head = NULL;
    int column = 0; //temporary until I find the way to send one argument during executing it under linux like so 'name_of_program columns < test.txt'
    int lastSpace = 0;

    do {
        symbol = fgetc(stdin);

        if (rows == 0 && (lastSpace == 0 && (isspace(symbol) || feof(stdin)))) {
            columns++;
            lastSpace = 1;
        } else if (!isspace(symbol)) {
            lastSpace = 0;
        }
        if (symbol == '\n' || feof(stdin)) {
            rows++;
        };      
    } while (symbol != EOF);

    if (ferror(stdin))
    {
        printf("Error on reading from file.\n");
    } else {
        printf("The file contains %d row(s) and %d column(s).\n", rows, columns);
    };

    rewind(stdin); //I have heard conflicting opinions on that, but in this case it works, and in the end it's a school project, not commercial code

    int table[rows][columns], i, j;
    for (i = 0; i < rows; i++){
        head = addnode(*table, head, columns);
        for (j = 0; j < columns; j++){
            scanf("%d",&table[i][j]);
            head->val[j] = table[i][j];
            printf("%d ",head->val[j]);
        };
        puts("\n");
    };  


    head = mergesort(head, column);

    for(current = head; current != NULL; current = current->next){
        for (j = 0; j < columns; j++){
            printf("%d ", current->val[j]);
        };
        puts("\n");
    };

    for(current = head; current != NULL; current = next)
      next = current->next, free(current);
    return 0;
};


struct node *addnode(int *val, struct node *next, int columns)
{
    struct node *tnode;
    tnode = (struct node*)malloc(sizeof(*tnode));
    if(tnode != NULL) {
        tnode->val = malloc(sizeof(int) * columns);
        memcpy(tnode->val, val, sizeof(int) * columns);
        tnode->val = val;
        tnode->next = next;
    };
    return tnode;
}

struct node *mergesort(struct node *head, int column)
{
    struct node *head_one;
    struct node *head_two;
    if((head == NULL) || (head->next == NULL))
        return head;
    head_one = head;
    head_two = head->next;
    while((head_two != NULL) && (head_two->next != NULL)) {
        head = head->next;
        head_two = head->next->next;
    };
    head_two = head->next;
    head->next = NULL;
    return merge(mergesort(head_one, column), mergesort(head_two, column), column);
}

struct node *merge(struct node *head_one, struct node *head_two, int column)
{
    struct node *head_combined;
    if(head_one == NULL)
        return head_two;
    if(head_two == NULL)
        return head_one;
    if(head_one->val[column] < head_two->val[column]) {
        head_combined = head_one;
        head_combined->next = merge(head_one->next, head_two, column);
    } else {
        head_combined = head_two;
        head_combined->next = merge(head_one, head_two->next, column);
    };
    return head_combined;
}

Я запускаю его в Unix следующим образом:

name_of_program < test.txt

с test.txt, имеющим эту структуру http://pastebin.com/WL5brutf


person user2447592    schedule 05.06.2013    source источник
comment
откуда head?   -  person wildplasser    schedule 05.06.2013
comment
@wildplasser struct node *head;, если это то, о чем вы просите.   -  person user2447592    schedule 05.06.2013
comment
В новом фрагменте rows и columns не определены в main(). ТАКЖЕ int main(int column_to_sort) - странный способ использования argc...   -  person wildplasser    schedule 05.06.2013
comment
Было бы полезно, если бы вы включили полную программу, которая компилируется без ошибок.   -  person sigjuice    schedule 05.06.2013
comment
@wildplasser Исправил первое, что касается второго - мне нужно запустить эту программу вот так name_of_program column_to_sort < 2D_array.txt, и я понятия не имею, как это сделать по-другому. @sigjuice Он компилируется, я просто пропустил часть с чтением из стандартного ввода и помещением его в 2D-массив int, потому что он работает так, как задумано, и это смущающий фрагмент кода.   -  person user2447592    schedule 05.06.2013
comment
int main(int column_to_sort) совершенно неверен. Что вы получите, если поместите printf(column_to_sort %d\n, column_to_sort) в начало main()? Кроме того, отсутствие частей вашей программы мешает другим людям дать полезный совет.   -  person sigjuice    schedule 05.06.2013
comment
@sigjuice Вставил весь код, думаю, я понял, о чем вы говорите, но не могли бы вы привести пример правильного использования?   -  person user2447592    schedule 05.06.2013
comment
@wildplasser Все источники, которые я смог найти об использовании аргументов командной строки, написаны на языке, который я едва понимаю (английский язык не является моим родным). Не могли бы вы привести пример того, как я могу получить целое число таким образом?   -  person user2447592    schedule 05.06.2013


Ответы (1)


1) Вы передаете int *val функции, используя ее в узле. Если вы хотите отказаться от val переданной функции и сохранить еще одну ее копию, вам необходимо malloc памяти. Как вы сказали, вы знаете, сколько элементов находится в массиве, поэтому вы можете выделить для этого много и просто скопировать память из val как

 tnode->val = malloc(sizeof(int) * num_of_elements); //replace num_of_elements with appropriate variable/constant
    memcpy(tnode->val, val, sizeof(int) * num_of_elements);

2) Да, это правильное место.

3) Да, таким образом можно присвоить значения текущему узлу, на который указывает head. Вы можете перейти к следующему узлу после завершения цикла for j и присвоить новые значения в его val.

person Rohan    schedule 05.06.2013
comment
Я поправил код, но потом после сортировки получаю только массив последнего элемента несортированного списка. - person user2447592; 05.06.2013