2015-02-09 5 views
1

У меня есть следующий код я "м преобразование строки, хранящейся в связанном списке . Пример: ABC A-> B-> C-> NULLСтрока связанного списка, используя двойной указатель

Проблемы : При печати списка, это не дает желаемого output.Following является код и примеры входы/выходы

код

#include<stdio.h> 
#include<stdlib.h> 
typedef struct node 
{ 
    char ch; 
    struct node *next; 
}node; 
void create(node **head,char ch) 
{ 
    node *new; 
    new=malloc(sizeof(node)); 
    new->next=NULL; 
    new->ch=ch; 
    if(*head==NULL) 
    { 
     *head=new; 
     printf("%c",(*head)->ch); 
     return ; 
    } 
    while((*head)->next) 
    { 
     (*head)=(*head)->next; 
    } 
    (*head)->next=new; 


} 
void printList(node *head) 
{ 
    printf("\nThe list has - "); 
    while(head) 
    { 
     printf("%c",head->ch); 
     head=head->next; 
    } 
    printf("\n\n"); 
} 
int main() 
{ 
    node *head=NULL; 
    int i=0; 
    char *str=NULL; 
    str=malloc(sizeof(char)*15); 
    printf("\nEnter the string - "); 
    scanf("%s",str); 

    while(str[i]!='\0') 
    { 
     create(&head,str[i]); 
     i++; 
    } 
    printList(head); 
    return 0; 
} 
.

Пример ввода/выходы

вход 1

Enter the string - abc 
a 
The list has - bc 

вход 2

Enter the string - abcde 
a 
The list has - de 

вход 3

Enter the string - ab 
a 
The list has - ab 

Примечание:

Если изменить мои функции создания этого, все работает отлично !. Я хочу знать, в чем тут разница? Это как-то связано с двойной стрелкой?

void create(node **head,char ch) 
{ 
    node *new,*ptr; 
    new=malloc(sizeof(node)); 
    new->next=NULL; 
    new->ch=ch; 
    ptr=*head; 
    if(ptr==NULL) 
    { 
     ptr=new; 
     return; 
    } 
    while(ptr->next) 
    { 
     ptr=ptr->next; 
    } 
    ptr->next=new; 

} 

Спасибо!

+1

Вы не описываете желаемый результат – user590028

+0

@ user590028 не очевидно. Я сказал, что пытаюсь скопировать строку в связанный список. – psychoCoder

ответ

3

Существует проблема с функцией вставки в первом кодовом Snipper, где вы переместите *head так к тому времени, вставить последний узел в список голова указывая на один перед последним узлом

a->b->c->d 
     | 
     | 

Head is at c now 

Таким образом, вы никогда не должны перемещать голову и использовать временную переменную, чтобы получить значение головы и скорость перемещения.

a->b->c->d 
|  | 
|  | 
Head temp 

Имеет это что-то делать с двойным указателем ??

Нет, во втором фрагменте вы используете ptr как временный указатель и не двигаете головой, как работает код.

+0

Поскольку я использую условие '(* head-> next)' in 'while' loop, поэтому цикл должен выйти, когда' (* head) 'должен указывать на' d' и '(* head-> next = NULL) '. Почему цикл выходит, когда голова указывает на 'c'? – psychoCoder

+1

@NitinPandey Когда (* head) указывает на c '(* head) -> next = NULL' .. То есть, когда вы идете вперед и добавляете узел (d), теперь ваша' * head' останется там .. Получил ? – Gopi

+0

Ох! Да Да. Что я думал? Понял ! Спасибо – psychoCoder

0

Гопи уже указал на проблему с вашим кодом. Вы можете использовать этот совет для вставки нового узла, если вы различаете два случая вставки первого узла в пустой список (в этом случае вы должны обновить head) и добавить к существующему списку. (Вы уже поймали два случая.)

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

void create(node **head, char ch) 
{ 
    /* create new node */ 
    node *nd = malloc(sizeof(*nd)); 
    nd->next=NULL; 
    nd->ch=ch; 

    /* advance to end of list */ 
    while (*head) { 
     head = &(*head)->next; 
    } 

    /* assign */ 
    *head = nd; 
} 

Кстати, ваша вторая функция не работает нормально, потому что вы никогда не обновит голову. Вы получите пустой список и утечки памяти.

+0

Это работает, потому что я никогда не меняю голову и использую временный указатель 'ptr' для перемещения по списку, и я вставляю его в конец. Так есть ли проблема с этим подходом? – psychoCoder

+0

Когда я запускаю ваш код и заменяю функцию 'create' тем, что в вашем последнем фрагменте кода, я получаю то, что ожидаю: пустой список. Перемещение списка с временным указателем в порядке, потому что вы не изменяете этот список. Но когда список можно изменить, вы должны отразить обновления. Ключевым случаем здесь является добавление первого узла в пустой список: 'head' должен измениться; он не может быть «NULL» после вставки. После этого ваш подход работает, потому что вы изменяете значение в структуре узла. –

+0

О, у меня есть небольшой код, вы правы. Я забыл поставить во втором фрагменте кода '* head = new 'в разделе' (ptr == NULL)'. В моем ноутбуке у меня так работает! Только что замечено – psychoCoder