2015-05-21 2 views
0

Я создаю программу, которая будет читать слово из текстового файла в main.c и отправить его в файл list.c, чтобы создать новый узел для хранения этого слова. Узел также сохранит три ints: сначала (количество раз это слово появляется в txt-файле 1), второе (количество раз это слово появляется в txt-файле 2) и dif (abs (первая секунда)). После добавления всех новых слов в файл и подсчета количества раз, когда каждое слово существует в каждом txt-файле, main.c вызовет метод, который будет вычислять разницу между первым и вторым для каждого узла. Это разность (хранится в dif для каждого узла) будет использоваться для сортировки связанных узлов в порядке убывания.C - LinkedList Сортировка бесконечной петли

EX. слово: the first: 2888, second: 2466, dif: 422. red, 39 12 27 .....

Однако, когда основной вызов метода сортировки, возникает бесконечный цикл. Этот бесконечный цикл исходит из внутреннего цикла алгоритма сортировки, где текущему узлу присваивается узел из указателя curr-> next. Где-то во время метода сортировки следующий указатель текущего узла указывает на текущий узел, а не на следующий следующий узел в связанном списке. Если метод сортировки dactivated, то все остальные функции работают нормально, включая printAll, который проходит весь список и печатает данные в каждом узле (см. Мой пример выше).

Моя проблема в том, что я не могу найти, где в моем методе сортировки, как current-> next начал указывать на текущий узел. Любая помощь приветствуется!

/* 
* list.h 
*/ 

#ifndef LIST_H_ 
#define LIST_H_ 

typedef struct node Node; 

void findWord(char *word, int book); 
void addWord(char *word, int book); 
void editWord(Node **endPtr, int book); 
void sort(); 
void swap(Node **a, Node **b); 
void calculateDiff(); 
void printAll(); 


#endif /* LIST_H_ */ 




/* 
* list.c 
*/ 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include "list.h" 

typedef struct node{ 
    int first; 
    int second; 
    int dif; 
    char name[20]; 
    struct node *next; 
}Node; 

Node *front = NULL; 

/* 
* Sees if the current word exists in the 
* linkedlist. 
*/ 
void findWord(char *word, int book) { 
    Node *curr = front; 
    int boolean = 0; 

    while (curr != NULL) { 
     if(strcmp(curr->name, word) == 0) { 
      boolean = 1; 
      editWord(&curr, book); 
      break; 
     } 
     curr = curr->next; 

    } 

    if(!boolean) { //Add word if it does not exist. 
     addWord(word, book); 
    } 
} 

/* 
* Creates a new node for the added word. Adds to front. 
*/ 
void addWord(char *word, int book) { 
    Node *newNode = malloc (sizeof(Node)); 

    /* 
    * Since this word is being added 
    * to the linkedlist with a newly 
    * created node, either the 
    * first or second int must be to 1 
    * while the other is set to 0. Based 
    * off of book int. 
    */ 
    if(book == 1) { 
     newNode->first = 1; 
     newNode->second = 0; 
    } else { 
     newNode->first = 0; 
     newNode->second = 1; 
    } 

    newNode->dif = 0; 
    strcpy(newNode->name, word); 

    newNode->next = front; 
    front = newNode; 

} 

/* 
* Edits the data for an existing word. 
* Only called if current word exists in 
* the linkedlist. 
*/ 
void editWord(Node **endPtr, int book) { 
    if (book == 1) { 
     (*endPtr)->first++; 
    } else { 
     (*endPtr)->second++; 
    } 
} 

/* 
* Sorts the list in descending order based on 
* difference value. 
*/ 
void sort() { 
    Node *curr, *last = NULL; 
    curr = front; 

    while (curr != last) { 
     while (curr->next != last) { 
      if(curr->dif < curr->next->dif) { 
       swap(&curr, &curr->next); 
      } 
      curr = curr->next; 
     } 
     last = curr; 
     curr = front; 
    } 
} 

/* 
* Swaps the data in the current and next node in the list. 
*/ 
void swap(Node **a, Node **b) { 
    int temp; 
    char nameTemp[20]; 


    //Swap first 
    temp = (*a)->first; 
    (*a)->first = (*b)->first; 
    (*b)->first = temp; 

    //Swap second 
    temp = (*a)->second; 
    (*a)->second = (*b)->second; 
    (*b)->second = temp; 

    //Swap dif 
    temp = (*a)->dif; 
    (*a)->dif = (*b)->dif; 
    (*b)->dif = temp; 

    //Swap name 
    strcpy(nameTemp, (*a)->name); 
    strcpy((*a)->name, (*b)->name); 
    strcpy((*b)->name, nameTemp); 
} 

/* 
* Calculates the difference between first and second 
*/ 
void calculateDiff() { 
    Node *curr = front; 
    while(curr != NULL) { 
     curr->dif = abs((curr->first - curr->second)); 
     curr = curr->next; 
    } 
} 

/* 
* Prints all the data from the nodes. 
*/ 
void printAll() { 
    printf("|| Word || RedBadge || LittleRegiment || Diff\n"); 
    Node *curr = front; 
    while (curr != NULL ) { 
     printf("%s, %d, %d, %d\n", curr->name, curr->first, curr->second, curr->dif); 
     curr = curr->next; 
    } 
} 

/* 
* main.c 
*/ 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <ctype.h> 
#include "list.h" 

void readBook(int book, FILE *infile); 
void readLine(char *line, int book); 

int main (void) { 
    setvbuf(stdout, NULL, _IONBF,0); 
    FILE *infile = fopen("RedBadge.txt", "r"); 
    FILE *infile2 = fopen("LittleRegiment.txt", "r"); 
    readBook(1, infile); 
    readBook(2, infile2); 
    fclose(infile); 
    fclose(infile2); 
    calculateDiff(); 
    sort(); 
    printAll(); 
    return 0; 
} 

void readBook(int book, FILE *infile) { 
    char line[70]; 

    //Read in each line 
    while (!feof(infile)) { 
     fgets(line, 70, infile); 
     readLine(line, book); 
    } 
} 

void readLine(char *line, int book) { 
    int i = 0, j = 0; 
    char word[20]; 


    while (line[i]) { 
     line[i] = tolower(line[i]); //Convert line to lowercase 
     if((line[i] <= 'z' && line[i] >= 'a') || line[i] == 39 || line[i] == '-') { 
      word[j] = line[i]; 
      j++; 
     } else if (j != 0) { 
      word[j] = '\0'; 
      findWord(word, book); 
      j = 0; 
     } 
     i++; 
    } 
} 
+0

Вы проверили с помощью gdb, чтобы узнать, что случилось в цикле? –

ответ

1

Я считаю, что ваша ошибка на самом деле является переполнением буфера. Есть слова в тех книгах, длина которых превышает 19 символов (максимальная, которая будет соответствовать вашей переменной word). Когда ваша функция readline пытается прочитать эти слова, она будет писать вне границ массива word, что является неопределенным поведением. Затем он будет использовать strcpy для копирования слова в узел, который также переполнит массив word узла.

Быстрое решение состоит в том, чтобы просто выбросить лишние символы 19, которые не будут вписываться в ваш массив слов. В readline добавить тест для того, как большой j является:

 if (j < sizeof word - 1) { 
      word[j] = line[i]; 
      j++; 
     } 

Одно из слов в вопросе «ain't - грабя ----» (по крайней мере, в копии текста я загруженный), что заставляет меня думать, может быть, вам также следует разделить слова на пунктуацию.

+0

Вы правы сэр или мадам! Я просто понимаю это после того, как я разместил эту тему здесь. Я ненавижу такие моменты. -_- –

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