해시 테이블을 구현하고 있지만 몇 가지 문제가 발생합니다. 단어가 추가 될 때 항상 업데이트 된 해시 테이블을 인쇄합니다. 문제는이 단어가 다시 나타날 때만 해당 빈도를 증가시켜야하지만 내 프로그램은 다음과 같습니다. 업데이트 된 빈도로 다시 인쇄 : 어떻게 한 번만 반복 된 단어를 인쇄 할 수 있습니까? 그리고 그들의 빈도를 보여주십시오.HashTable 반복 된 단어를 한 번만 인쇄하는 방법은 무엇입니까?
다른 문제는 print_freq 함수에 있습니다. 그것은 int freq를 받고이 주파수로 단어를 출력해야하지만 문제는 auxTable이 htable에서 단어를 저장하지 않는다는 것입니다. auxtable이 주파수를 정상적으로 저장하기 때문에 왜 작동하지 않는지 알 수 없습니다. 단어를 저장하려고하면 빈 문자 ""가 저장됩니다.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#define HTABLE_SIZE 1001
#define MAX_LINE_SIZ 1024
/* Hash Table */
typedef struct node* HASH_TABLE; /* estrutura de dados utilizadas para formar a hastable*/
struct node {
char *palavra; /*word*/
int freq;
};
/*Declaracao das funcoes*/
void inserirHashTable(char *s);
void print_ht();
void print_test();
HASH_TABLE htable[HTABLE_SIZE] = { NULL }; /* Hash table que armazenará as palavras lidas do arquivos */
unsigned int chaves[HTABLE_SIZE]; /* Vetor que armazenará as chaves das palavras da tabela*/
int tamanhoChaves=-1; /*Variavel responsavel por contar a quantidade de chaves do vetor de chaves*/
int size = 0; /* variavel responsavel por armazenar o numero de elementos da tabela*/
/*Função responsavel por processar o arquivo, a mesma recebe o arquivo como parametro,
* pega cada palavra presente no arquivo separa dos simbolos ?!+.-... e chama a função
* inserirHT para inserir a palavra separada na tabela hash*/
void processarArquivo(FILE *fp)
{
const char *seperators = " ?!'\";,.:+-*&%(){}[]<>\\\t\n"; // caractertes que deveram ser separados
char line[MAX_LINE_SIZ];
char *s;
while((fgets(line,MAX_LINE_SIZ, fp)) != NULL) //pegando a linha do arquivo
{
for (s=strtok(line,seperators); s; s=strtok(NULL,seperators)){ // separando a palavra
/*printf("Palavra a ser inserida %s \n",s); printf utilizado para mostrar
* a palavra que foi seperada e será inserida*/
inserirHashTable(s);//Chamando a função inserir
}
}
}
/* Função responsavel por criar a chave de cada palavra que vai para tabela,
recebe como parametro um ponteiro para string, logo em seguida pega cada
caractere da string e gera um unsigned int para ele, retorna por fim o
modulo desse unsigned int pelo tamanho da tabela*/
unsigned int hash(char *tok)
{
unsigned int hv = 0;
while (*tok)
hv = (hv << 4) | toupper(*tok++);
/*printf("conversao: %d \n",hv); Printf utilizado para mostrar o valor de hv antes de ser retorna como modulo*/
return hv % HTABLE_SIZE;
}
/* funcao responsavel por isenrir a palavra lida do arquivo na hash_table,
* a funçãp recebe como parametro um ponteiro para estra palavra*/
void inserirHashTable(char *palavra) {
/*printf("Inserindo a palavra %s \n",palavra); Printf utilzado para mostrar a palavra a ser inserida na tabela*/
tamanhoChaves++; /*Assim que uma palavra é inserida o numero de chaves é incrementado*/
chaves[tamanhoChaves] = hash(palavra);/*A palavra é convertida na função hash e sua armazenada no vetor de chaves*/
unsigned int hashval = chaves[tamanhoChaves]; /*Chave da apalvra*/
if (htable[hashval]==NULL){
/*printf("indice %u de %s \n",hashval,palavra);Printf utilizado para mostrar a chave e a palavra a ser inserida*/
htable[hashval] = malloc(sizeof(palavra)); /*Alocando memoria para palavrra*/
htable[hashval]->palavra = palavra ; /*Inserindo a palavra*/
htable[hashval]->freq = 1; /*Incrementado sua frequencia*/
size++;
}else {
/*If a words already exists in the table, i just incremente her frequency and the size. I guess the problem for repeated word is in here*/
htable[hashval]->freq++;
size++;
}
/*A tabela é impressa a cada instante que uma palavra é inserida*/
printf("\nAtualização da tabela\n");
print_ht();/*Impressao das palavras já recebidas, a cada instante, com a quantidade de ocorrências*/
}
/* Function responsible to print the words that were addedd to the hash table*/
void print_ht() {
int i=0;
/*Tabela auxiliar que servira para impressao das palavras e suas chaves*/
HASH_TABLE *auxTable = (HASH_TABLE*) malloc(sizeof(HASH_TABLE)*size);
unsigned int hashval; /* variavel utilizada para pegar a chave das palavras no vetor de chaves */
for(i; i < size; i++){
hashval = chaves[i]; /*Pegando a chave*/
/*printf("indice %u de %s \n",hashval,htable[hashval]->token);Printf utilizado para ver a chave e a palavra*/
auxTable[i] = htable[hashval]; /*Atribuindo a palavra e a freq para tabela auxiliar*/
}
/*qsort(auxTable,size,sizeof(link),compare);*/
/*Imprimindo a tabela*/
printf("Palavra | Frequencia\n");
for (i=0; i < size; i++)
printf("%s \t %d\n",auxTable[i]->palavra,auxTable[i]->freq);
free(auxTable);
}
/*Funcion responsible to print the words with the frequency received in the paramater*/
void print_freq(int freq){
printf("Palavras com a frequencia: %d\n", freq);
int i, j =0;
HASH_TABLE *auxTable = (HASH_TABLE*) malloc(sizeof(HASH_TABLE)*size);
unsigned int hashval;
for(i; i < size; i++){
hashval = chaves[i];
/*printf("indice %u de %s \n",hashval,htable[hashval]->palavra);*/
auxTable[i] = htable[hashval]; /*Problem is in here, when I do this, the auxTable[i]->palavra(word) = "", but the freq has been saved normally n*/
}
printf("Palavra | Frequencia\n");
for (i=0; i < size; i++) {
if(auxTable[i]->freq == freq) {
printf("%s \t %d\n",auxTable[i]->palavra,auxTable[i]->freq); /*When I print, only the frequency is showed*/
}
}
free(auxTable);
}
int main(int argc, char *argv[])
{
int i;
FILE *fp;
fp = fopen("input.txt","r");
if (NULL == fp)
{
fprintf(stderr,"Error ao abrir o arquivo: %s\n",fp);
}
printf("Imprimindo processo \n");
processarArquivo(fp); /* debuuga aqui pra tu entender o q rola*/
fclose(fp);
print_freq(3); //should print the word with freq equal to 3
//print_ht();
/*clear_ht();*/
return 0;
}
출력 :
; 'chaves []'배열을 스캔합니다.이 배열은 발생시킨 각 단어의 해쉬 값을 당신이 만난 순서대로 포함하고 있습니다. 보조 테이블도 필요 없습니다. htable [hashval] -> palavra, htable [hashval], htable [hashval]! = NULL) printf ("% s \ t % d \ n" -> 주파수);'충분해야합니다. –
아쉽게도 근본적인 버그가 있습니다. 두 단어가 같은 값으로 해시되면 동일한 단어로 취급합니다. 이를 * [hash collision] (https://en.wikipedia.org/wiki/Hash_table#Collision_resolution) *이라고하며이를 해결할 수있는 몇 가지 방법이 있습니다. 내가 가장 좋아하는 것은 노드를 단일 링크 목록으로 만드는 것이다. (그런데, 혼합 된 언어로 작성된 코드를 읽는 것은 매우 어렵습니다. 저는 영어 원어민이 아닙니다 .C 키워드는 이미 영어로되어 있으므로, 모든 코드와 주석이 영어로만.) –
도움을 주신 분께 고마워,이 속어 이야기에 대해 유감스럽게 생각합니다. 그때는 모두 포르투갈어로되어 있습니다. ', btw, 내 문제는 thats, 나는 해시 콜리 전 (hash colisions) 이 자료 나 코드가 있습니까? –