veces una txt repite palabras palabra leer guardar datos cuantas contar buscar archivos archivo c algorithm nlp counting

una - leer palabras en c



Contando el número de ocurrencias de palabras en un archivo de texto (8)

Puede usar una tabla hash y tener cada entrada en el punto de la tabla hash a una estructura que contenga la palabra y la cantidad de veces que se ha encontrado hasta el momento.

¿Cómo podría hacer un seguimiento del número de veces que aparece una palabra en un archivo de texto? Me gustaría hacer esto por cada palabra.

Por ejemplo, si la entrada es algo así como:

"el hombre le dijo hola al niño".

Cada uno de "el hombre dijo hola al niño" tendría una ocurrencia de 1.

"the" tendría una ocurrencia de 2.

Estaba pensando en mantener un diccionario con pares de palabra / ocurrencia, pero no estoy seguro de cómo implementar esto en C. Un enlace a cualquier problema similar o relacionado con una solución sería genial.

EDITAR: Para evitar desplegar mi propia tabla hash, decidí aprender a usar glib. En el camino encontré un excelente tutorial que atraviesa un problema similar. http://bo.majewski.name/bluear/gnu/GLib/ch03s03.html

Estoy impresionado por la cantidad de enfoques diferentes y, en particular, por la simplicidad y elegancia de la implementación de Ruby.


Sí, un diccionario con pares de aparición de palabras funcionaría bien, y la forma habitual de implementar dicho diccionario sería utilizar una tabla hash (o, a veces, un árbol de búsqueda binario).

También podría usar un trie (o su versión comprimida, "Patricia trie" / Radix trie) cuya complejidad es asintóticamente óptima para este problema, aunque sospecho que en la práctica podría ser más lento que una (buena) implementación de la tabla hash.

[Realmente creo que si las tablas hash o los intentos son mejores depende de la distribución de las palabras en su entrada; por ejemplo, una tabla hash necesitará almacenar cada palabra en su cubo hash (para evitar colisiones), mientras que si tiene mucha palabras con prefijos comunes, en un trie esos prefijos comunes son compartidos y necesitan ser almacenados solo una vez cada uno, pero aún existe la sobrecarga de todos los indicadores ... si prueban ambos, tengo curiosidad por saber cómo ellos comparan]


¿Esto cuenta?

#include <stdio.h> #include <stdlib.h> int main(int argc, char **argv) { char buffer[2048]; if (argc != 2) { fprintf(stderr, "Usage: %s file/n", argv[0]); exit(EXIT_FAILURE); } snprintf(buffer, sizeof(buffer), "tr -cs ''[a-z][A-Z]'' ''[//n*]'' < %s |" " sort | uniq -c | sort -n", argv[1]); return(system(buffer)); }

Básicamente, encapsula la secuencia de comandos canónica que ilustra cómo contar palabras en Unix como un script de shell.

El comando '' tr '' traduce cualquier cosa que no sea un carácter alfabético en una nueva línea y exprime los duplicados. El primer '' sort '' agrupa todas las ocurrencias de cada palabra juntas. El '' uniq -c '' cuenta el número de apariciones consecutivas de cada palabra, imprimiendo la palabra y su conteo. El segundo '' sort '' los pone en orden de repeticiones crecientes. Es posible que necesite dinks con opciones para '' tr ''; no es el comando más estable de sistema a sistema, y ​​se las arregla rutinariamente para hacerme ataques manuales. En Solaris 10 utilizando / usr / bin / tr, el código anterior produce (en su propia fuente):

1 1 A 1 EXIT 1 FAILURE 1 Usage 1 Z 1 a 1 c 1 cs 1 exit 1 file 1 fprintf 1 if 1 main 1 return 1 sizeof 1 snprintf 1 stderr 1 stdio 1 stdlib 1 system 1 tr 1 uniq 1 z 2 argc 2 char 2 h 2 include 2 int 2 s 2 sort 3 argv 3 n 4 buffer


Para palabras individuales, no hay necesidad de escribir un programa a menos que esto sea parte de algo más grande:

sed -e ''s/[[:space:]]//n/g'' < file.txt | grep -c WORD


Solo para los curiosos, aquí hay una solución simple de Ruby del problema del conteo de palabras. Debería ser básicamente el mismo algoritmo en C, solo que con mucho más código.

h = Hash.new(0) File.read("filename.txt").split.each do |w| h[w] += 1 end p h


en Perl:

my %wordcount = (); while(<>){map {$wordcount{$_}++} (split //s+/)} print "$_ = $wordcount{$_}/n" foreach sort keys %wordcount;

y en Perl Golf (solo por diversión):

my%w; map{$w{$_}++}split//s+/while(<>); print"$_=$w{$_}/n"foreach keys%w;


#include <conio.h> #include <iostream.h> #include <fstream.h> #include <cstdlib> struct stdt { char name[20] ; int id ; }; //std int main() { stdt boy ; int a = 0 ; ofstream TextFile ; cout << "Begin File Creation /n" ; TextFile.open("F://C++ Book Chapter Program//Ch 7//File.txt" ); if ( !TextFile) { cerr <<"Erro 100 Openoing File.DAT" ; exit(100); }//end if while ( a < 3 ) { TextFile.write( (char*) &boy , sizeof (boy) ) ; cout << "/nEnter Name : " ; cin >> boy.name; cout << "/nEnter ID : " ; cin >> boy.id ; a++; }//end while TextFile.close(); cout << "/nEnd File Creation" ; ifstream TextFile1 ; TextFile1.open("F://C++ Book Chapter Program//Ch 7//File.txt" ); while ( TextFile1.read( (char*) &boy , sizeof (boy) ) ) { cout << "/nEnter Name : " << boy.name; cout << "/nEnter ID : " << boy.id ; }// end While getch(); return 0 ; }//end main


ADVERTENCIA código no probado:

#include <stdio.h> struct LLNode { LLNode* Next; char* Word; int Count; }; void PushWord(LLNode** list, const char* word) { LLNode* node = NULL; unsigned int len = 0; if (*list == NULL) { $list = new LLNode; $list = "/0"; } node = *list; while ((node = node->Next) != NULL) // yes we are skipping the first node { if (!strcmp(node->Word, word)) { node->Count++; break; } if (!node->Next) { LLNode* nnode = new LLNode; nnode->Count = 1; node->Next = nnode; len = strlen(word); node->Word = new char[len + 1]; strcpy(node->Word, word); break; } } } void GetCounts(LLNode* list) { if (!list) return; LLNode* node = list; while ((node = node->Next) != NULL) // yes we are skipping the first node { printf("Word: %s, Count: %i", node->Word, node->Count); } } void PushWords(LLNode** list, const char* words) { char ch = ''/0''; unsigned int len = strlen(words); char buff[len]; // to be sure we have no buffer ovverunes. May consume too much memery for your application though. int index = 0; for (unsigned int i = 0; i < len; i++) { ch = words[i]; if (index > 0 && ch == '' '') { ch[index + 1] = ''/0''; PushWords(list, buff); index = 0; } else if (ch != '' '') { ch[index++] = ch; } } if (index > 0 && ch == '' '') { ch[index + 1] = ''/0''; PushWords(list, buff); index = 0; } } int main() { LLNode* list = NULL; PushWords(&list, "Hello world this is a hello world test bla"); GetCount(list); // release out memery here }

Escribí eso hace un momento, así que probablemente no funcione, pero esa es la idea general.

Otro borrador en esta ocasión en C ++ (nota: std :: map tiene tiempos de búsqueda bastante buenos):

#include <iostream> #include <string> #include <map> using namespace std; typedef map<string, int> CountMap; void PushWords(CountMap& list, const char* words) { char ch = ''/0''; unsigned int len = strlen(words); string str; int index = 0; for (unsigned int i = 0; i < len; i++) { ch = words[i]; if (index > 0 && ch == '' '') { list[str] = list[str] + 1; index = 0; } else if (ch != '' '') { str += ch; index++; } } if (index > 0 && ch == '' '') { list[str] = list[str] + 1; } } void PrintCount(CountMap& list) { CountMap::iterator iter = list.begin(), end = list.end(); for (; iter != end; ++iter) { cout << (*iter).first << " : " << (*iter).second; } } int main() { CountMap map; PushWords(map, "Hello world this is a hello world test bla"); PrintCount(map); }