2015-05-20 2 views
1

У меня есть программа, которая читает в гигантском текстовом файле строк в этом формате, и мне нужно построить структуру данных из этого текстового файла.Реконструкция индекса в C

microfinance 5 41 5 1650 2 1667 1 1811 1 1988 5 
subminiature 1 432 1 

Номер 1-го числа после слова - это количество документов, в которых находится слово. Следующие номера чередуются между идентификационным номером документа и количеством вхождений слова, найденного в документе. Таким образом, для микрофинансирования существует 5 документов, первый из которых - документ 41 с 5 вхождениями, следующий - документ 1650 с 2 и т. Д.

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

DocumentNode *myDoc; 
while (fgets(theLine, sizeof(theLine), newPointer) != NULL) 
    { 
     counter = 0; 
     pch = strtok (theLine," "); 
     while (pch != NULL) 
     { 
     if (0 == counter) 
     { 
      WordNode *toInsertPtr = (malloc(sizeof(struct WordNode))); 
      word = (malloc(100)); 
      strncpy (word, pch, strlen(pch)); 
      toInsertPtr->word = word; 
      toInsertPtr->next = NULL; 

      currIndex = JenkinsHash(word, MAX_HASH_SLOT); 
      if ((TheIndex->index[currIndex]) == NULL) 
      { 
       TheIndex->index[currIndex] = toInsertPtr; 
      } 
      else 
      { 
       TheIndex->index[currIndex]->next = toInsertPtr; 
      } 
     } 

     if (1 == counter) 
     { 
      numOfDocs = atoi(pch); 
     } 

     if (counter % 2 == 0 && counter != 0 && pch != NULL) 
     { 
      myDoc= (malloc(sizeof(struct DocumentNode))); 
      myDoc->next = NULL; 
      int doc_id = atoi(pch); 
      myDoc->documentID = doc_id;   
     } 

     if (counter % 2 != 0 && counter != 1 && pch != NULL) 
     { 
      myDoc->occurences = atoi(pch); 

      if (TheIndex->index[currIndex]->page == NULL) 
      { 
       TheIndex->index[currIndex]->page = myDoc; 
      } 
      else 
      { 
       TheIndex->index[currIndex]->page->next = myDoc; 
      } 
     } 
      pch = strtok (NULL, " "); 
      counter++; 
     } 
    } 

У меня есть GDBed, чтобы выяснить, что проблема здесь. Первый оператор if, проверяющий, есть ли узел индекса в индексе, всегда улавливается как нуль (даже если в этой точке индекса явно есть что-то), и он перезаписывает один слот снова и снова. Почему он всегда считает, что это NULL, когда это не так?

 if (TheIndex->index[currIndex]->page == NULL) 
     { 
      TheIndex->index[currIndex]->page = myDoc; 
     } 
     else 
     { 
      TheIndex->index[currIndex]->page->next = myDoc; 
     } 

Структуры данных заключаются в следующем:

typedef struct DocumentNode { 
    struct DocumentNode *next;  // pointer to next member of the list. 
    int documentID;     //doc identifier (filename, ie. 1, 2, etc.) 
    int occurences;     //num. occurances. 
} DocumentNode; 

typedef struct WordNode {     
    struct WordNode *next;   //pointer to the next word (for collisions) 
    char *word;      //the word itself. 
    DocumentNode *page;    // pointer to the first element of the page list. 
} WordNode; 

typedef struct InvertedIndex { 
    WordNode *index[MAX_HASH_SLOT]; 
} InvertedIndex; 
+1

Я думаю, что ваш вызов 'strncpy' неверен. Размер должен включать завершающий \ 0. Предложите использовать вместо этого функцию 'strdup', это комбинированные' malloc' и 'strcpy'. –

ответ

3

Ваш подход является слишком сложным: петля пытается поддерживать состояние, и имеет длинную цепь условий, чтобы решить, что делать с следующий токен.

Вместо того, чтобы делать свой strtok по одному, сделайте первый, чтобы получить слово, второе - чтобы получить счет, а затем сделать остальные из них попарно. Он должен действовать следующим образом:

while (fgets(theLine, sizeof(theLine), newPointer) != NULL) { 
    pch = strtok (theLine," "); 
    char *word = malloc(strlen(pch)+1); 
    strcpy(word, pch); 
    ... // Add the word 
    pch = strtok(NULL, " "); 
    int pairCount = atoi(pch); 
    for (int i = 0 ; i != pairCount ; i++) { 
     pch = strtok(NULL, " "); 
     int id = atoi(pch); 
     pch = strtok(NULL, " "); 
     int count = atoi(pch); 
     ... // Add the document 
    } 
} 

P.S. Если вы хорошо понимаете этот подход, вам, вероятно, понравится this tale от Edsger Dijkstra.

+0

Спасибо! Это было очень полезно. Быстрое сопровождение - я, кажется, не прикрепляю docNodes правильно. Вы можете обнаружить что-то не так с этой логикой? \t \t \t ', если ((TheIndex-> ​​Индекс [currIndex] -> страница) == NULL) \t \t \t { \t \t \t \t TheIndex-> ​​Индекс [currIndex] -> страница = myDoc; \t \t \t} \t \t \t еще \t \t \t { \t \t \t \t TheIndex-> ​​Индекс [currIndex] -> PAGE-> следующая = myDoc; \t \t \t} ' – themacexpert

+0

@themacexpert Проблема с этой логикой заключается в том, что она работает только для списков длины нуль или одна. Как только список получает второй элемент, эта логика продолжает писать над этим элементом вместо добавления в конец списка. Существует два подхода к решению этого вопроса: добавление цикла «while» (поиск «связанного списка в примере», в Интернете есть много учебников).Второй подход - сохранить указатель на указатель на «DocumentNode», в котором указывается, где положить новый «DocumentNode». Сначала установите его в индекс TheIndex-> ​​index [currIndex] -> page', а затем перейдите к его 'next', когда вы идете. – dasblinkenlight

+0

Спасибо, миллион! Я не буду повторять эту ошибку ха-ха. – themacexpert

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