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 Компилира се, просто пропуснах частта с четене от stdin и поставянето му в 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. Може да искате да преминете към следващия възел, след като j for-цикълът приключи и да присвоите нови стойности в неговия val.

person Rohan    schedule 05.06.2013
comment
Коригирах кода, но след като го сортирах, получавам само масива от последния елемент от несортирания списък. - person user2447592; 05.06.2013