2016-07-12 17 views
4

Ich versuche, die Anzahl der Vorkommen jedes Wortes in der Funktion countWords zu zählen Ich glaube, ich begann die for-Schleife in der Funktion richtig, aber wie vergleiche ich die Wörter in den Arrays zusammen und sie zählen und dann die Duplikate löschen? Ist es nicht wie eine Fibonacci-Serie oder irre ich mich? Auch int n hat den Wert 756, weil so viele Wörter im Array sind und wordsArray die Elemente im Array sind.Zählen Sie die Anzahl der Vorkommen jedes Wortes

#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

'während { numworte ++; fscanf (Textdatei, "% s", Puffer); } ist falsch. Verwenden Sie den Rückgabewert von 'fscanf()', um zu bestimmen, wann die Schleife beendet werden soll. – chux

Antwort

1

Angenommen, Sie den Rückgabewert von countWords wollen ein Array von ganzen Zahlen mit Wort zählt für jedes einzelne Wort zu sein, müssen Sie eine doppelte Schleife haben. Eine Schleife geht über das gesamte Array, die zweite Schleife durchläuft den Rest des Arrays (nach dem aktuellen Wort) und sucht nach Duplikaten.

Man könnte so etwas wie dieser Pseudo-Code tun:

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

Ich werde hier Ihr ein bisschen Kurve Ball werfen.

Anstatt Ihren Code zu reparieren, der leicht repariert werden kann, da er alleine ziemlich gut ist, aber unvollständig ist, habe ich beschlossen, ein Beispiel von Grund auf neu zu schreiben.

Es ist nicht nötig, die Datei zweimal zu lesen [das erste Mal, um die maximale Anzahl zu erhalten]. Dies könnte durch ein dynamisches Array und realloc gehandhabt werden.

Der wichtigste Punkt, denke ich, ist, dass es viel einfacher ist, dass Wortliste hat keine Duplikate zu gewährleisten, während es zu schaffen, anstatt Duplikate am Ende zu entfernen.

Ich entschied mich für ein paar Dinge.

Ich habe eine "Word Control" -Struktur erstellt. Sie haben mehrere separate Arrays, die auf die gleiche Weise indiziert werden. Das "schreit" nach einer Struktur. Das heißt, anstatt 5 separate Arrays zu haben, haben Sie ein einzelnes Array einer Struktur mit 5 Elementen.

Die Wortliste ist eine verkettete Liste dieser Strukturen. Es könnte ein dynamisches Array auf dem Heap sein, das realloc Ed stattdessen erhält, aber die verknüpfte Liste ist eigentlich einfacher für diese bestimmte Verwendung zu pflegen.

Jede Struktur hat den [bereinigten] Worttext und eine Zählung der Vorkommen (vs. Ihre separaten wordArray und countArray).

Beim Hinzufügen eines Wortes wird die Liste nach einer vorhandenen Übereinstimmung durchsucht. Wenn eine gefunden wird, wird die Zählung inkrementiert, anstatt ein neues Wortlistenelement zu erzeugen. Das ist der Schlüssel zum Eliminieren von Duplikaten [d.h. Erstelle sie nicht an erster Stelle].

Wie auch immer, hier ist es: (! Feof (Text-Datei))

#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; 
} 
Verwandte Themen