2013-11-22 3 views
1

У меня есть список, как это:обновление списка с функцией (без возвращаемого значения)

typedef struct list { 
    char *key; 
    char *value; 
    struct list *next; 
} List; 

И использовать его в своей основной функции:

main(int argc, char *argv[]) { 
    List *list; 
    list = malloc(sizeof(struct list)); 

    list = insertToList("key", "value", list); 
} 

insertToList является:

List insertToList(char *key, char *value, List *list) { 
    List *newNode = malloc(sizeof(struct list)); 
    newNode->key = malloc(strlen(key)); 
    strcpy(newNode->key, key); 

    newNode->value = malloc(strlen(value)); 
    strcpy(newNode->value, value); 
    newNode->next = list; 
    list = newNode; 

    return list; 
} 

Это работает так, как ожидалось, но я хотел бы изменить список, указав вместо этого указатель, так что мне не нужно возвращать список. Я попытался передать список & в качестве аргумента insertToList, а затем получить его с ** списком, но это не сработало. Как мне это сделать?

+0

Что вы подразумеваете под «что не работает» для списка **? Что случилось, когда вы пробовали этот подход? – Derek

+0

ваш 'newNode-> key = malloc (strlen (ключ)); strcpy (newNode-> key, key); 'сломан и может вызвать переполнение, потому что вы не выделяете место для трейлинга' '\ 0''. Используйте 'newNode-> key = strdup (key)' – ensc

ответ

0

Что в принципе нужно, является указателем на указатель: List**:

void insertToList(char *key, char *value, List** list) { 
    List *newNode = malloc(sizeof(List)); 
    newNode->key = malloc(strlen(key)); 
    strcpy(newNode->key, key); 

    newNode->value = malloc(strlen(value)); 
    strcpy(newNode->value, value); 
    newNode->next = *list; 
    *list = newNode; 
} 

Переименовать List в ListNode для большей ясности

Альтернативой является, чтобы определить дополнительную структуру List, чтобы обернуть " указатель головы "(ListNode*). Эта структура может содержать дополнительные значения, такие как текущий размер списка.

typedef struct ListNode 
{ 
    char *key; 
    char *value; 
    struct ListNode *next; 
} ListNode; 

typedef struct List 
{ 
    struct ListNode* head; 
} List; 

void insertAtFront(char *key, char *value, List* list) 
{ 
    ListNode *newNode = malloc(sizeof(List)); 
    newNode->key = malloc(strlen(key)); 
    strcpy(newNode->key, key); 

    newNode->value = malloc(strlen(value)); 
    strcpy(newNode->value, value); 
    newNode->next = list->head; 
    list->head = newNode; 
} 

void insertBefore(char *key, char *value, ListNode** listNode) 
{ 
    ListNode* newNode = malloc(sizeof(List)); 
    newNode->key = malloc(strlen(key)); 
    strcpy(newNode->key, key); 

    newNode->value = malloc(strlen(value)); 
    strcpy(newNode->value, value); 
    newNode->next = *listNode; 
    *listNode = newNode; 
} 
+0

Должен ли я отправить & & функцию в функцию? – theva

+0

Да, чтобы изменить указатель снаружи – Sam

0

Ваша первая мысль об использовании списка **, вероятно, самая лучшая, но это сработает. Ваш последний узел в списке не содержит никаких данных, так как вы malloc'd его в основном и не заполнили. Вы можете вставить все новые узлы после первого, тогда вам не нужно возвращать указатель списка, так как он не меняется. Так, в insertToList, вы можете вставить newNode с:

newNode->next = list->next; 
list->next = newNode; 

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

Смежные вопросы