2016-12-07 7 views
2

Я написал программу связанного списка, которая хранит элемент данных как void *. при попытке сохранить печать annd с помощью функций scanf/printf, я получаю ошибку сегментации.Сохранение и печать строки в указателе void

определение узла ->

typedef struct node { 
     struct node *next; 
     void *data; 
     }node; 

главная функция ->

   head=(node *)malloc(sizeof(node)); 
       if (head==NULL){ 
         printf("error in allocation of memory\n"); 
         exit(EXIT_FAILURE); 
       } 
       tail=(node*)create(head); 

создать функцию ->

void *create(node *current) 
{ 
     int user_choice; 
     while(current){ 
       printf("\nEnter the data:"); 
       scanf("%s",current->data); 
       printf("stored at %p\n",(void*)current->data); 
       printf("%s",(char*)current->data); 
       printf("\nType '1' to continue, '0' to exit:\n"); 
       scanf("%d",&user_choice); 

       if(user_choice == 1){ 
         current->next=(node*)malloc(sizeof(node)); 
         current=current->next; 
       } 
       else{ 
         current->next=NULL; 
       } 
     } 
     return current; 
} 

может кто-нибудь сказать, что является правильным аргументом для scanf & prinf должен быть ..?


рабочего кода после включения точек, приведенных в ответах ...

void *create(node *current) 
{ 
     node *temp; 
     int user_choice; 
     while(current){ 
       printf("\nEnter the data:"); 
       current->data=(char*)malloc(10*sizeof(char)); 
       scanf("%s",current->data); 
       printf("stored at %p\n",(void*)current->data); 
       printf("%s",(char*)current->data); 
       printf("\nType '1' to continue, '0' to exit:\n"); 
       scanf("%d",&user_choice); 

       if(user_choice == 1){ 
         current->next=(node*)malloc(sizeof(node)); 
       } 
       else{ 
         current->next=NULL; 
         temp=current; 
       } 
       current=current->next; 
     } 
     return temp; 
} 
+0

[Пожалуйста, смотрите эту дискуссию о том, почему не бросить возвращаемое значение 'таНос()' и семьи в 'C'.] (HTTP://stackoverflow.com/q/605845/2173917). –

+1

Когда пользователь нажимает 0, функция возвращает NULL. Есть много ошибок. Пожалуйста, прочитайте книгу, переосмыслите свой код и вернитесь, если у вас возникнут проблемы. –

+1

Когда 'head' равно null, и вы печатаете сообщение об ошибке (которое должно идти в stderr, а не stdout), вы должны сделать что-то другое, кроме продолжения следующей строки, для которой' head' будет не нулевым. Ваша программа имеет неопределенное поведение. –

ответ

3

В коде

scanf("%s",current->data); 

является попытка использовать в инициализированы указатель, он вызывает undefined behavior.

Вы должны следовать либо из сильфона подхода,

  • сделать точку указателя на действительный участок памяти (с использованием malloc() и семьи для динамического распределения, например)
  • использовать массив.
+0

Я выделил память на голову в основной функции, которая передается как текущая в функции создания ... –

+4

@HimanshuSourav точно, вы выделили для ' head', а не 'head-> data'. подумайте с этой точки зрения. –

1

Вы должны сначала инициализировать элемент данных структуры, потому что

current->data = malloc("passes size here"); 

Для ввода данных вы должны типаж первую эти данные, потому что пустота не тип хранения. Указатель void может использоваться для указания на любой тип данных.

Как

*(char *)(current->data) = 1; 
-1

Пожалуйста, попробуйте с этим

void *create(node *current) 
{ 
     int user_choice; 
     while(true){ 
       if(current == NULL) { 
        current = (node *)malloc(sizeof(node)); 
        current->data = NULL; 
        current->next = NULL; 
       } 
       printf("\nEnter the data:"); 
       scanf("%s",current->data); 
       printf("stored at %p\n", (void *)current->data); 
       printf("%s",current->data); 
       //printf("%s",(char*)current->data); 
       printf("\nType '1' to continue, '0' to exit:\n"); 
       scanf("%d",&user_choice); 

       if(user_choice == 1){ 
         current->next=(node*)malloc(sizeof(node)); 
         current=current->next; 
       } 
       else{ 
         current->next=NULL; 
         tail = current; 
         current=current->next; 
         break; 
       } 
     } 
     return current; 
} 

Примечание: Элемент должен быть инициализирован (т.е., оно должно быть отведенное с некоторой памятью), прежде чем мы пытаемся использовать из этого.

+0

Вы не показываете, что в какой-то момент вы выделили любую память для 'current-> data'. Вы также не инициализируете все элементы недавно выделенного узла. В C вы всегда должны думать о «где мои указатели указывают». –

+0

'current = (node ​​*) malloc (sizeof (node));' выделение памяти узла выделяет память для своих элементов, таких как 'current-> data' и' current-> next' – lsof

+2

Но 'current-> data' будет удерживайте указатель 'void *', который нужно выделить перед использованием. – RoadRunner

1

Как уже сказал:

scanf("%s",current->data); 

неопределен в C. current->data должен указывать где-то прежде, чем вы можете хранить все, что в нем.

Вы должны вместо этого:

  1. Принимать входные данные из scanf.
  2. Хранить во временном буфере.
  3. Вставить в связанный список
  4. распечатать весь связанный список в конце
  5. free() связанный список в конце.

Я также считаю, что текущая void *create функция делает слишком много, и было бы легче разбить код на различные функции, просто чтобы сделать его легче обрабатывать все операции с указателями, вставляя и т.д.

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

Здесь:

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

#define MAXSTRLEN 100 

typedef struct node { 
    void *data; 
    struct node *next; 
} node_t; 

typedef struct { 
    node_t *head; 
    node_t *foot; 
} list_t; 

list_t *create_list(void); 
node_t *generate_node(void); 
list_t *insert_node(list_t *list, char *data); 
void print_list(list_t *list); 
void free_list(list_t *list); 

int 
main(int argc, char *argv[]) { 
    list_t *list; 
    char data[MAXSTRLEN]; 
    int user_choice; 

    list = create_list(); 

    while (1) { 
     printf("Enter the data: "); 
     scanf("%s", data); 

     printf("\nType '1' to continue, '0' to exit:\n"); 
     if (scanf("%d",&user_choice) != 1) { 
      printf("Invalid input\n"); 
      exit(EXIT_FAILURE); 
     } 

     if (user_choice == 1) { 
      list = insert_node(list, data); 
     } else { 
      list = insert_node(list, data); 
      break; 
     } 
    } 

    print_list(list); 

    free_list(list); 
    list = NULL; 

    return 0; 
} 

/* inserting at foot, you can insert at the head if you wish. */ 
list_t 
*insert_node(list_t *list, char *data) { 
    node_t *newnode = generate_node(); 

    newnode->data = malloc(strlen(data)+1); 
    strcpy(newnode->data, data); 

    newnode->next = NULL; 
    if (list->foot == NULL) { 
     list->head = newnode; 
     list->foot = newnode; 
    } else { 
     list->foot->next = newnode; 
     list->foot = newnode; 
    } 
    return list; 

} 

node_t 
*generate_node(void) { 
    node_t *new = malloc(sizeof(*new)); 
    new->data = NULL; 
    return new; 
} 

void 
print_list(list_t *list) { 
    node_t *curr = list->head; 

    printf("\nlinked list data:\n"); 
    while(curr != NULL) { 
     printf("%s\n", (char*)curr->data); 
     curr = curr->next; 
    } 
} 

list_t 
*create_list(void) { 
    list_t *list = malloc(sizeof(*list)); 

    if (list == NULL) { 
     fprintf(stderr, "%s\n", "Error allocating memory"); 
     exit(EXIT_FAILURE); 
    } 

    list->head = NULL; 
    list->foot = NULL; 
    return list; 
} 

void 
free_list(list_t *list) { 
    node_t *curr, *prev; 
    curr = list->head; 
    while (curr) { 
     prev = curr; 
     curr = curr->next; 
     free(prev); 
    } 
    free(list); 
} 

UPDATE:

Также обратите внимание, как я выделил память для newnode->data?

Как это:

newnode->data = malloc(strlen(data)+1); //using buffer from scanf 

Теперь это означает, что я могу хранить данные в этом указателе, ваш current->data нужно будет сделать что-то подобное.

1

рабочий код ->

void *create(node *current) 
{ 
     node *temp; 
     int user_choice; 
     while(current){ 
       printf("\nEnter the data:"); 
       current->data=(char*)malloc(10*sizeof(char)); 
       scanf("%s",current->data); 
       printf("stored at %p\n",(void*)current->data); 
       printf("%s",(char*)current->data); 
       printf("\nType '1' to continue, '0' to exit:\n"); 
       scanf("%d",&user_choice); 

       if(user_choice == 1){ 
         current->next=(node*)malloc(sizeof(node)); 
       } 
       else{ 
         current->next=NULL; 
         temp=current; 
       } 
       current=current->next; 
     } 
     return temp; 
} 
+0

Ницца @ Химаншу Сурав, мой код вообще помог? – RoadRunner

+0

@RoadRunner это действительно так :) –