2016-07-12 2 views
4

Я пытаюсь подсчитать количество вхождений каждого слова в функцию countWords Я верю, что я начал цикл for в функции правильно, но как сравнить слова в массивах вместе и подсчитать их, а затем удалить дубликаты? Разве это не серия фибоначчи, или я ошибаюсь? Также int n имеет значение 756, потому что это количество слов в массиве и wordsArray - это элементы в массиве.Подсчитайте количество вхождений каждого слова

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

int *countWords(char **words, int n); 
int main(int argc, char *argv[]) 
{ 
    char buffer[100]; //Maximum word size is 100 letters 
    FILE *textFile; 
    int numWords=0; 
    int nextWord; 
    int i, j, len, lastChar; 
    char *wordPtr; 
    char **wordArray; 
    int *countArray; 
    int *alphaCountArray; 
    char **alphaWordArray; 
    int *freqCountArray; 
    char **freqWordArray; 
    int choice=0; 

    //Check to see if command line argument (file name) 
    //was properly supplied. If not, terminate program 
    if(argc == 1) 
    { 
    printf ("Must supply a file name as command line argument\n"); 
    return (0); 
    } 

    //Open the input file. Terminate program if open fails 
    textFile=fopen(argv[1], "r"); 
    if(textFile == NULL) 
    { 
    printf("Error opening file. Program terminated.\n"); 
    return (0); 
    } 

    //Read file to count the number of words 
    fscanf(textFile, "%s", buffer); 
    while(!feof(textFile)) 
    { 
    numWords++; 
    fscanf(textFile, "%s", buffer); 
    } 

    printf("The total number of words is: %d\n", numWords); 
    //Create array to hold pointers to words 
    wordArray = (char **) malloc(numWords*sizeof(char *)); 
    if (wordArray == NULL) 
    { 
    printf("malloc of word Array failed. Terminating program.\n"); 
    return (0); 
    } 
    //Rewind file pointer and read file again to create 
    //wordArray 
    rewind(textFile); 
    for(nextWord=0; nextWord < numWords; nextWord++) 
    { 
    //read next word from file into buffer. 
    fscanf(textFile, "%s", buffer); 

    //Remove any punctuation at beginning of word 
    i=0; 
    while(!isalpha(buffer[i])) 
    { 
     i++; 
    } 
    if(i>0) 
    { 
     len = strlen(buffer); 
     for(j=i; j<=len; j++) 
     { 
     buffer[j-i] = buffer[j]; 
     } 
    } 

    //Remove any punctuation at end of word 
    len = strlen(buffer); 
    lastChar = len -1; 
    while(!isalpha(buffer[lastChar])) 
    { 
     lastChar--; 
    } 
    buffer[lastChar+1] = '\0'; 

    //make sure all characters are lower case 
    for(i=0; i < strlen(buffer); i++) 
    { 
     buffer[i] = tolower(buffer[i]); 
    } 

    //Now add the word to the wordArray. 
    //Need to malloc an array of chars to hold the word. 
    //Then copy the word from buffer into this array. 
    //Place pointer to array holding the word into next 
    //position of wordArray 
    wordPtr = (char *) malloc((strlen(buffer)+1)*sizeof(char)); 
    if(wordPtr == NULL) 
    { 
     printf("malloc failure. Terminating program\n"); 
     return (0); 
    } 
    strcpy(wordPtr, buffer); 
    wordArray[nextWord] = wordPtr; 
    } 

    //Call countWords() to create countArray and replace 
    //duplicate words in wordArray with NULL 
    countArray = countWords(wordArray, numWords); 
    if(countArray == NULL) 
    { 
    printf("countWords() function returned NULL; Terminating program\n"); 
    return (0); 
    } 

    //Now call compress to remove NULL entries from wordArray 
    compress(&wordArray, &countArray, &numWords); 
    if(wordArray == NULL) 
    { 
    printf("compress() function failed; Terminating program.\n"); 
    return(0); 
    } 
    printf("Number of words in wordArray after eliminating duplicates and compressing is: %d\n", numWords); 

    //Create copy of compressed countArray and wordArray and then sort them alphabetically 
    alphaCountArray = copyCountArray(countArray, numWords); 
    freqCountArray = copyCountArray(alphaCountArray, numWords); 
int *countWords(char **wordArray, int n) 
{ 
    return NULL; 
    int i=0; 
    int n=0; 

    for(i=0;i<n;i++) 
    { 
     for(n=0;n<wordArray[i];n++) 
     { 

     } 
    } 

} 
+0

'в то время как { numWords ++; fscanf (textFile, "% s", буфер); } 'неправильно. Используйте возвращаемое значение 'fscanf()', чтобы определить, когда выйти из цикла. – chux

ответ

1

Предполагая, что вы хотите, возвращаемое значение countWords быть массивом целых чисел с числом слов для каждого уникального слова, вы должны иметь двойную петлю. Один цикл проходит по всему массиву, второй цикл проходит через остальную часть массива (после текущего слова), ища дубликаты.

Вы могли бы сделать что-то вроде этого псевдокода:

Allocate the return array countArray (n integers) 
Loop over all words (as you currently do in your `for i` loop) 
    If the word at `i` is not null // Check we haven't already deleted this word 
     // Found a new word 
     Set countArray[i] to 1 
     Loop through the rest of the words e.g. for (j = i + 1; j < n; j++) 
     If the word at j is not NULL and matches the word at i (using strcmp) 
      // Found a duplicate word 
      Increment countArray[i] (the original word's count) 
      // We don't want wordArray[j] anymore, so 
      Free wordArray[j] 
      Set wordArray[j] to NULL 
    Else 
     // A null indicates this was a duplicate, set the count to 0 for consistency. 
     Set countArray[i] to 0 
Return wordArray 
0

Я собираюсь бросить вам немного кривой мяч здесь.

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

Не нужно читать файл дважды [первый раз, чтобы получить максимальный счет]. Это может обрабатываться динамическим массивом и realloc.

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

Я выбрал несколько вещей.

Я создал структуру управления словами. У вас есть несколько отдельных массивов, которые индексируются одинаково. Это, вроде, «кричит» для структуры. То есть, а не [сказать] 5 отдельных массивов, имеют один массив структуры, в которой есть 5 элементов.

Список слов - это связанный список этих структур. Это может быть быть динамическим массивом на куче, который вместо этого получает realloc ed, но связанный список на самом деле проще поддерживать для этого конкретного использования.

Каждая структура имеет текст [очищенного] слова и количество вхождений (по сравнению с вашими отдельными wordArray и countArray).

При добавлении слова список проверяется на наличие существующих совпадений. Если он найден, счетчик увеличивается, а не создает новый элемент списка слов. Это ключ к устранению дубликатов (т. не создавайте их в первую очередь].

Во всяком случае, вот это: (! Feof (Textfile))

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

#define sysfault(_fmt...) \ 
    do { \ 
     printf(_fmt); \ 
     exit(1); \ 
    } while (0) 

// word control 
typedef struct word { 
    struct word *next;    // linked list pointer 
    char *str;      // pointer to word string 
    int count;      // word frequency count 
} word_t; 

word_t wordlist;     // list of words 

// cleanword -- strip chaff and clean up word 
void 
cleanword(char *dst,const char *src) 
{ 
    int chr; 

    // NOTE: using _two_ buffers in much easier than trying to clean one 
    // buffer in-place 
    for (chr = *src++; chr != 0; chr = *src++) { 
     if (! isalpha(chr)) 
      continue; 
     chr = tolower(chr); 
     *dst++ = chr; 
    } 

    *dst = 0; 
} 

// addword -- add unique word to list and keep count of number of words 
void 
addword(const char *str) 
{ 
    word_t *cur; 
    word_t *prev; 
    char word[1000]; 

    // get the cleaned up word 
    cleanword(word,str); 

    // find a match to a previous word [if it exists] 
    prev = NULL; 
    for (cur = wordlist.next; cur != NULL; cur = cur->next) { 
     if (strcmp(cur->str,word) == 0) 
      break; 
     prev = cur; 
    } 

    // found a match -- just increment the count (i.e. do _not_ create a 
    // duplicate that has to be removed later) 
    if (cur != NULL) { 
     cur->count += 1; 
     return; 
    } 

    // new unique word 
    cur = malloc(sizeof(word_t)); 
    if (cur == NULL) 
     sysfault("addword: malloc failure -- %s\n",strerror(errno)); 

    cur->count = 1; 
    cur->next = NULL; 

    // save off the word string 
    cur->str = strdup(word); 
    if (cur->str == NULL) 
     sysfault("addword: strdup failure -- %s\n",strerror(errno)); 

    // add the new word to the end of the list 
    if (prev != NULL) 
     prev->next = cur; 

    // add the first word 
    else 
     wordlist.next = cur; 
} 

int 
main(int argc,char **argv) 
{ 
    FILE *xf; 
    char buf[1000]; 
    char *cp; 
    char *bp; 
    word_t *cur; 

    --argc; 
    ++argv; 

    xf = fopen(*argv,"r"); 
    if (xf == NULL) 
     sysfault("main: unable to open '%s' -- %s\n",*argv,strerror(errno)); 

    while (1) { 
     // get next line 
     cp = fgets(buf,sizeof(buf),xf); 
     if (cp == NULL) 
      break; 

     // loop through all words on a line 
     bp = buf; 
     while (1) { 
      cp = strtok(bp," \t\n"); 
      bp = NULL; 

      if (cp == NULL) 
       break; 

      // add this word to the list [avoiding duplicates] 
      addword(cp); 
     } 
    } 

    fclose(xf); 

    // print the words and their counts 
    for (cur = wordlist.next; cur != NULL; cur = cur->next) 
     printf("%s %d\n",cur->str,cur->count); 

    return 0; 
} 
Смежные вопросы