2017-08-23 7 views
0

Salut tout le monde, c'est ma première fois dans Stackoverflow. J'ai une question concernant le comptage de l'occurrence des mots dans le fichier texte en utilisant C++. Ceci est mon code jusqu'à présent. Je dois créer un tableau struct d'index du mot et le compteur de chaque mot puis stocker tous dans un arbre AVL. Après avoir ouvert le fichier et lu un mot, je le cherche dans l'arbre avl ou trie. Si c'est le cas, utilisez l'index du noeud pour incrémenter le mot Cnt. Si ce n'est pas le cas, ajoutez-le au tableau array et placez sa position dans la structure suivante et placez la position structs dans l'arbre avl. J'ai aussi mis la structure Cnt à 1. Le problème que j'ai maintenant est qu'il semble que mon programme ne traite pas le comptage correctement donc il ne fait qu'imprimer 0. S'il vous plaît donnez-moi des recommandations sur la façon dont je peux corriger le bug. S'il vous plaît trouver mon code ci-dessous:Utilisation d'un tableau de struct comptant le nombre d'occurrences d'un mot dans un fichier texte C++

#include <iostream> 
#include <fstream> 
#include <string> 
#include <cstdlib> 
#include <cstring> 
#include <ctype.h> 
#include <stdio.h> 
#include <string> 
#include <cctype> 
#include <stdlib.h> 
#include <stdbool.h> 
using namespace std; 

struct Node* insert(struct Node* node, int key) ; 
void preOrder(struct Node *root) ; 
void removePunct(char str[]); 
int compareWord(char word1[], char word2[]); 

struct Stats { 
    int wordPos, wordCnt; 
}; 
Stats record[50000]; 
int indexRec = 0; 
char word[50000*10] ; 
int indexWord = 0; 

int main() { 
    ifstream fin; 
    string fname; 
    char line[200], wordArray[500000]; 

    cout << "Enter the text file name:" << endl; 
    cin >> fname; 
    fin.open(fname.c_str()); 
    if (!fin) { 
     cerr << "Unable to open file" << endl; 
     exit(1); 
    } 
    struct Node *root = NULL; 
    while (!fin.eof() && fin >> line) { //use getline 
     for(int n=0,m=0; m!=strlen(line); m+=n) { 
      sscanf(&line[m],"%s%n",word,&n); 
      removePunct(word); 
      //strcpy(&wordArray[indexWord],word); 
      int flag = compareWord(wordArray, word); 
      if(flag==-1) { 
       strcpy(&wordArray[indexWord],word); 
       record[indexRec].wordPos = indexWord; 
       record[indexRec].wordCnt = 1; 
       root = insert(root, record[indexRec].wordPos); 
       indexWord+=strlen(word)+1; 
       // indexes of the word array 
       indexRec++; 
       cout << wordArray[indexWord] << " "; 
      } else 
       record[flag].wordCnt++; 

      cout << record[indexRec].wordCnt; 
      cout << endl; 

     } 
     /*for(int x = 0; x <= i; x++) 
     { 
      cout << record[x].wordPos << record[x].wordCnt << endl; 
     }*/ 

    } 

    fin.close(); 
    return 0; 

} 

void removePunct(char str[]) { 
    char *p; 
    int bad = 0; 
    int cur = 0; 
    while (str[cur] != '\0') { 
     if (bad < cur && !ispunct(str[cur]) && !isspace(str[cur])) { 
      str[bad] = str[cur]; 
     } 
     if (ispunct(str[cur]) || isspace(str[cur])) { 
      cur++; 
     } else { 
      cur++; 
      bad++; 
     } 
    } 
    str[bad] = '\0'; 
    for (p= str; *p!= '\0'; ++p) { 
     *p= tolower(*p); 
    } 
    return; 
} 
int compareWord(char word1[], char word2[]) { 
    int x = strcmp(word1, word2); 
    if (x == 0) return x++; 
    if (x != 0) return -1; 
} 

struct Node { 
    int key; 
    struct Node *left; 
    struct Node *right; 
    int height; 
}; 

// A utility function to get maximum of two integers 
int max(int a, int b); 

// A utility function to get height of the tree 
int height(struct Node *N) { 
    if (N == NULL) 
     return 0; 
    return N->height; 
} 

// A utility function to get maximum of two integers 
int max(int a, int b) { 
    return (a > b)? a : b; 
} 

/* Helper function that allocates a new node with the given key and 
    NULL left and right pointers. */ 
struct Node* newNode(int key) { 
    struct Node* node = (struct Node*) 
         malloc(sizeof(struct Node)); 
    node->key = key; 
    node->left = NULL; 
    node->right = NULL; 
    node->height = 1; // new node is initially added at leaf 
    return(node); 
} 

// A utility function to right rotate subtree rooted with y 
// See the diagram given above. 
struct Node *rightRotate(struct Node *y) { 
    struct Node *x = y->left; 
    struct Node *T2 = x->right; 

    // Perform rotation 
    x->right = y; 
    y->left = T2; 

    // Update heights 
    y->height = max(height(y->left), height(y->right))+1; 
    x->height = max(height(x->left), height(x->right))+1; 

    // Return new root 
    return x; 
} 

// A utility function to left rotate subtree rooted with x 
// See the diagram given above. 
struct Node *leftRotate(struct Node *x) { 
    struct Node *y = x->right; 
    struct Node *T2 = y->left; 

    // Perform rotation 
    y->left = x; 
    x->right = T2; 

    // Update heights 
    x->height = max(height(x->left), height(x->right))+1; 
    y->height = max(height(y->left), height(y->right))+1; 

    // Return new root 
    return y; 
} 

// Get Balance factor of node N 
int getBalance(struct Node *N) { 
    if (N == NULL) 
     return 0; 
    return height(N->left) - height(N->right); 
} 

// Recursive function to insert key in subtree rooted 
// with node and returns new root of subtree. 
struct Node* insert(struct Node* node, int key) { 
    /* 1. Perform the normal BST insertion */ 
    if (node == NULL) 
     return(newNode(key)); 

    if (key < node->key) 
     node->left = insert(node->left, key); 
    else if (key > node->key) 
     node->right = insert(node->right, key); 
    else // Equal keys are not allowed in BST 
     return node; 

    /* 2. Update height of this ancestor node */ 
    node->height = 1 + max(height(node->left), 
          height(node->right)); 

    /* 3. Get the balance factor of this ancestor 
      node to check whether this node became 
      unbalanced */ 
    int balance = getBalance(node); 

    // If this node becomes unbalanced, then 
    // there are 4 cases 

    // Left Left Case 
    if (balance > 1 && key < node->left->key) 
     return rightRotate(node); 

    // Right Right Case 
    if (balance < -1 && key > node->right->key) 
     return leftRotate(node); 

    // Left Right Case 
    if (balance > 1 && key > node->left->key) { 
     node->left = leftRotate(node->left); 
     return rightRotate(node); 
    } 

    // Right Left Case 
    if (balance < -1 && key < node->right->key) { 
     node->right = rightRotate(node->right); 
     return leftRotate(node); 
    } 

    /* return the (unchanged) node pointer */ 
    return node; 
} 
void preOrder(struct Node *root) { 
    if(root != NULL) { 
     printf("%d ", root->key); 
     preOrder(root->left); 
     preOrder(root->right); 
    } 
} 
+3

Existe-t-il une raison spécifique pour ne pas simplement utiliser un 'std :: map '? – Frank

+1

On dirait que vous apprenez C et non C++. Des fonctions telles que 'removePunct' peuvent être écrites avec seulement 2 lignes de code C++. – PaulMcKenzie

+0

[Voici un exemple] (https://www.ideone.com/nNtPD2) – PaulMcKenzie

Répondre

0

Un problème (je ne vois pas si cela est le seul problème) est que vous avez du code comme celui-ci, la suppression de toutes les lignes intermédiaires:

record[indexRec].wordCnt = 1; 
if find word fails 
    indexRec++; 
cout << record[indexRec].wordCnt; 

Ainsi, lorsque vous avoir un nouveau mot (si je comprends bien le code!), vous imprimez l'enregistrement suivant. Une solution serait:

if (flag==-1) 
    cout << record[indexRec-1].wordCnt; 
else 
    cout << record[indexRec].wordCnt; 

Il y a beaucoup d'autres questions, comme compareWord() est très mal, vous devez décider si vous voulez vraiment utiliser C++ ou tout simplement C avec std::cout, le code de lecture du fichier est impair, vous incluez les versions C et C++ des en-têtes standard, etc., mais ce sont des problèmes pour une autre question!