2013-09-30 4 views
0

В первый раз addToEnd() называется его работой, но во второй раз он сбой программы. Я пытался его отладить и обнаружил, что это происходит, когда происходит head->next. Я немного смущен, потому что он просто читается, может ли это сбой программы? Если да, как вы можете повторить этот файл?Ошибка программы при просмотре адреса следующего узла в списке; происходит только в очень странных обстоятельствах

Кажется, что работает с определенными значениями entry, но не с другими. Если две записи совпадают и состоят из одной буквы, она сработает. Поэтому, если вызывается addToEnd (head, «aaaaaaaaa»), то addToEnd (head, «aaaaaaaaa») называется сбоем программы, но если addToEnd (head, «aaaaaaaaa»), то addToEnd (head, «aaaaaaaab») это нормально.

Вот 100% всего кода

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

typedef struct node 
{ 
    char entry[21]; 
    struct node* next; 
} node; 

void readDic(); 
void reverStr(char *str); 
bool isInDic(char *reversed); 
void addToEnd(node* head, char entry[21]); 
unsigned int searchAndDestroy(node **head, char *entry); 
void printList(node* head); 
int main() 
{ 
    printf("Hello\n"); 
    readDic(); 
    printf("Goodbye!"); 
    return EXIT_SUCCESS; 
} 

void readDic() 
{ 
    FILE* words; 
    char singleLine[21]; 
    words = fopen("words.txt", "r"); 
    node* head = malloc(sizeof(node)); 
    fscanf(words, "%20s", head->entry);//need to do this initially 
    head->next = NULL; 
    printf("here 0"); 

    printf("here 0.1"); 
    if(words == NULL) 
     exit(EXIT_FAILURE); 
    printf("here 0.5"); 
    while(fscanf(words, "%20s", singleLine) == 1)assigned input terms 
    { 
     printf("\nhere 0.6\n|%s|", singleLine); 
     addToEnd(head, singleLine);//problem here 
     printf("here 0.7"); 
     reverStr(singleLine); 
     printf("here 1"); 
     if(isInDic(singleLine)){ 
      printf("here 2"); 
      searchAndDestroy(&head, singleLine); 
      printf("here 3"); 
     } 
    } 
    printf("here 4"); 
    fclose(words); 
    printList(head); 
    printf("here 5"); 
} 

//http://stackoverflow.com/questions/198199/how-do-you-reverse-a-string-in-place-in-c-or-c 
/* PRE: str must be either NULL or a pointer to a 
* (possibly empty) null-terminated string. */ 
void reverStr(char *str) 
{ 
    char temp, *end_ptr; 

    /* If str is NULL or empty, do nothing */ 
    if(str == NULL || !(*str)) 
     return; 

    end_ptr = str + strlen(str) - 1; 

    /* Swap the chars */ 
    while(end_ptr > str) 
    { 
    temp = *str; 
    *str = *end_ptr; 
    *end_ptr = temp; 
    str++; 
    end_ptr--; 
    } 
} 

bool isInDic(char* reversed) 
{ 
    FILE* words; 
    char singleLine[21]; 

    words = fopen("words", "r"); 
    if(words == NULL) 
     exit(EXIT_FAILURE); 
    while(fscanf(words, "%20s", singleLine) == 1)//the length of the string has to be 1 less than declared size for the newline character 
    { 
     //printf("singline: %s reversed: %s\n", singleLine, reversed); 
     if(strcmp(singleLine, reversed) == 0)//strcmp returns 0 if both cstrings are equal 
      return true; 
    } 
    fclose(words); 
    return false; 
} 

void addToEnd(node* head, char entry[21]) 
{ 
    printf("hi"); 
    //printf("\naddress of next %p\n", (void *)head->next); 
    while(head->next != NULL)//just reading head->next screws it up 
     head = head->next; 
    printf("in addToEnd 2\n"); 
    node* last = (node*)malloc(sizeof(node)); 
    printf("in addToEnd 3\n"); 
    head->next = last; 
    printf("in addToEnd 4\n"); 
    strcpy(last->entry, entry); 
    printf("in addToEnd 5\n"); 
    last->next = NULL; 
    printf("in addToEnd 6\n"); 
} 

unsigned int searchAndDestroy(node **head, char *entry) 
{ 
    unsigned int count = 0; 

    while(*head) 
    { 
     node *del; 
     if(strcmp((*head)->entry, entry)) 
     { //this node stays 
      head = &(*head)->next; 
      continue; 
     } 
     /* this node goes 
     at this point head MUST point to the pointer that points at the node to be deleted 
     */ 
     del = *head; 
     *head = (*head)->next; 
     free(del); 
     count++; 
    } 
    return count; //number of nodes deleted 
} 

void printList(node* head) 
{ 
    printf("\nprinting everything\n"); 
    if(head != NULL) 
    { 
     while(head->next != NULL) 
     { 
      printf("%s", head->entry); 
      head = head->next; 
     } 
     printf("%s", head->entry); 
    } 
} 

ответы правильны, что голова создается в null, но я не вижу, где?

+1

UB где-то. Трудно сказать, не зная определения структуры, контекста и т. Д. Используйте отладчик. –

+0

Как определяется последняя запись? Если head имеет значение null, это приведет к сбою. –

+0

@ H2CO3 Что такое UB? – Celeritas

ответ

1

Одна из трех вещей:

  1. Если головка NULL этот код аварии на линии вы упоминаете.

  2. Если last-> запись определяется как символ * Вы должны сказать «last-> запись = strdup (запись)

  3. Если last-> запись SizeOf меньше, чем 21, ваш зЬгсру переполнится он, который приведет к неопределенному поведению.

Хорошо, с вашим недавним редактированием, я утверждаю, что голова имеет значение null или мусор, когда вы вызываете эту функцию во второй раз.

1

При создании head вы не устанавливаете head->next на номер NULL.