2017-02-02 8 views
-3

Итак, что я пытаюсь достичь с этим, заключается в создании связанного списка с тремя строками в качестве данных. Вывод показывает ожидаемые строки, но добавляет некоторые символы мусора, f.ex .: ожидаемый «string pierwszy», полученный: «string pierwszyn ~ rŚÝ».символы мусора при вставке строки в связанный список в c

Я также попытался распечатать strlen (tmp-> word), и я получил 3. Я не понимаю, я думал, что это будет 1. Я не понимаю, почему это так.

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

typedef struct element element; 

struct element{ 
    char * word; 
    element * next; 
}; 

element * head = NULL; 

void addWord(char * new_word){ 
    printf("new_word: %s\n\n\n", new_word); 

    element *tmp = NULL; 
    tmp = malloc(sizeof(element)); 

    element *current = head; 

    tmp->word = malloc(sizeof(char) * strlen(new_word)+1); 
    strncpy(tmp->word, new_word, strlen(new_word)); 
    tmp->word[strlen(new_word)] = "\0"; 

    tmp->next = current; 
    head = tmp; 

} 
void free_list(element * node){ 
    if(node != NULL){ 
     free_list(node->next); 
     free(node->word); 
     free(node); 
    } 
} 
void print_list(element * node){ 
    element * tmp = node; 
    while(tmp != NULL){ 
     printf("word: %s\n", tmp->word); 
     tmp = tmp->next; 
    } 
} 
int main() 
{ 
    char * name1 = "string pierwszy"; 
    char * name2 = "drugi"; 
    char * name3 = "333trzeci"; 

    addWord(name1); 
    addWord(name2); 
    addWord(name3); 
    print_list(head); 

    free_list(head); 
    return 0; 
} 
+1

'человек strncpy': * [...] Функция strncpy() аналогична, за исключением того, что в большинстве п байт СРК являются скопированный. Предупреждение: если не существует нулевого байта среди первых n байтов src, строка, помещенная в dest, не будет заканчиваться нулем. [...] * – EOF

+0

Следующий код 'tmp-> word [strlen (new_word)] = «\ 0»; 'не компилируется. замените '' \ 0 ";' (строку) на '' \ 0'' (символ нуль-терминатора). –

ответ

0

Проблема заключается в следующей строке:

tmp->word[strlen(new_word)] = "\0"; 

Существует разница между "\0" и '\0'. '\0' верен в этой ситуации, так как это просто нулевой символ. "\0" - это строка, содержащая нулевой символ, так что это точно так же, как
{'\0', '\0'} (один нулевой символ для введенного вами и тот, который добавляется автоматически).

Поскольку массивы в C рассматриваются в качестве указателей для некоторых целей, код, который вы написали создает массив из двух нулевых символов в памяти, принимает адрес первого элемента, преобразует его в char используя ASCII table и магазины это в строке. Так что вы делали в основном эквивалентна делать это:

char someString[2]; 
someString[0] = '\0'; 
someString[1] = '\0'; 
tmp->word[strlen(new_word)] = (char)&(someString[0]); 

Поскольку строка не имеет прекращен нулевой символ из-за этого, он не знает, где строка заканчивается так продолжается несколько символов, дающих вы, персонажи, которые только что оказались в памяти.

Итак, первый символ «мусора», как вы говорите, является эквивалентом ASCII адреса какой-либо строки, а другие - тем, что произошло в памяти прямо там и прямо.

Правильный код, конечно, следующее:

tmp->word[strlen(new_word)] = '\0';