Created
July 15, 2020 23:34
-
-
Save jj-marinho/be9fc30da78fb2bcd078a85a0332ccb8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdlib.h> | |
#include <stdio.h> | |
#include <string.h> | |
#include <regex.h> | |
#define BUFFER 512 | |
typedef struct Patterns { | |
char *regexFreq; // Regex usado na conta de frequencia | |
char *regexLongest; // Regex usado para achar a palavra mais longa | |
char *regexAll; // Regex usado na impressão de todos os matchs | |
char *closestWord; // Achar a palavra mais próxima desta no arquivo; | |
} Patterns; | |
// Funções usadas no projeto | |
// Documentação no "cabeçalho" de cada uma | |
int parseFile(char ***dictionary); | |
Patterns getPatterns(void); | |
void printWordFacts(char **dict, int dictSize); | |
void printPalindromeAmount(char ** dict, int dictSize); | |
void printFreqRegex(char *regex, char **dict, int dictSize); | |
void printLongestWordRegex(char *regex, char **dict, int dictSize); | |
void printAllMatchingWords(char *pattern, char **dict, int dictSize); | |
void printClosestWord(char *word, char **dict, int dictSize); | |
int compare(const void* a, const void* b); | |
int main(void) { | |
// Procedimento completo de abertura do arquivo | |
char **dictionary; | |
int dictSize = parseFile(&dictionary); | |
// Pegando os regexes e palavras de comparação | |
Patterns patterns = getPatterns(); | |
// Todas as funções de print modularizadas | |
// Fatos inicias | |
printWordFacts(dictionary, dictSize); | |
// Frequencias | |
printFreqRegex(patterns.regexFreq, dictionary, dictSize); | |
free(patterns.regexFreq); | |
// Palindromos | |
printPalindromeAmount(dictionary, dictSize); | |
// Palavra mais longa | |
printLongestWordRegex(patterns.regexLongest, dictionary, dictSize); | |
free(patterns.regexLongest); | |
// Todas as palavras relacionadas | |
printAllMatchingWords(patterns.regexAll, dictionary, dictSize); | |
free(patterns.regexAll); | |
// Palavra mais semelhante | |
printClosestWord(patterns.closestWord, dictionary, dictSize); | |
free(patterns.closestWord); | |
// Finalizando o programa | |
for (int j = 0; j < dictSize; j++) { | |
free(dictionary[j]); | |
} | |
free(dictionary); | |
return 0; | |
} | |
// Atravessa o arquivo, armazenando todas as palavras incluidas | |
// em uma matriz "dictionary". Retorna o tamanho da matriz | |
int parseFile(char ***dictionary) { | |
// Pegando o nome do arquivo e abrindo-o | |
char *fileName = malloc(32); | |
scanf("%[^\n]", fileName); | |
FILE * filePointer = fopen(fileName, "r"); | |
free(fileName); | |
int i = -1; | |
*dictionary = malloc(sizeof(char *)); | |
do { | |
// Realloc caso o buffer seja esgotado | |
if (++i % BUFFER == 0) { | |
*dictionary = realloc(*dictionary, sizeof(char *) * BUFFER * (1 + i / BUFFER)); | |
} | |
(*dictionary)[i] = calloc(32, 1); | |
// Pegando a palavra do arquivo e armazendo no dictionary, | |
// Depois disso eliminando o \n com o fgetc() | |
fscanf(filePointer, "%[^\n]", (*dictionary)[i]); | |
fgetc(filePointer); | |
} while (!feof(filePointer)); | |
free((*dictionary)[i]); | |
*dictionary = realloc(*dictionary, sizeof(char * ) * i); | |
fclose(filePointer); | |
return i; | |
} | |
// Pega os 4 padrões descritos na struct Patterns | |
// através do stdin. | |
// Retorna a struct contendo os padrões | |
Patterns getPatterns(void) { | |
Patterns patterns; | |
patterns.regexFreq = calloc(16, 1); | |
patterns.regexLongest = calloc(16, 1); | |
patterns.regexAll = calloc(16, 1); | |
patterns.closestWord = calloc(16, 1); | |
scanf("%s\n%s\n%s\n%s", | |
patterns.regexFreq, | |
patterns.regexLongest, | |
patterns.regexAll, | |
patterns.closestWord | |
); | |
return patterns; | |
} | |
// Imprime, em sequência: | |
// Número total de palavras, palavra mais curta, palavra mais longa | |
void printWordFacts(char **dict, int dictSize) { | |
// Posições da palavra mais longa e curta no dict | |
int longestIndex = 0, shortestIndex = 0; | |
// Tamanho de cada palavra, para evitar a necessidade de recalcular dentro da função | |
int longestLen = strlen(dict[0]), | |
shortestLen = longestLen, | |
currentLen = 0; | |
// Dentro de um loop, procura pela maior e menor palavra do dicionário | |
for (int i = 0; i < dictSize; i++) { | |
currentLen = strlen(dict[i]); | |
if (currentLen > longestLen) { | |
longestLen = currentLen; | |
longestIndex = i; | |
} else if (currentLen < shortestLen && currentLen != 0) { | |
shortestLen = currentLen; | |
shortestIndex = i; | |
} | |
} | |
printf("%d\n%s\n%s\n", dictSize, dict[shortestIndex], dict[longestIndex]); | |
} | |
// Checa a quantidade de palíndromos | |
void printPalindromeAmount(char ** dict, int dictSize) { | |
int numPalindromes = 0, | |
wordSize = 0, | |
isPalindrome = 1; | |
// Checa se a última letra e a primeira são iguais | |
// Faz isso para todas as letras. | |
// Se todas forem iguais, isPalindrome continua como 1 | |
// Ao somar, se isPalindrome for 1, aumenta o total de palindromos | |
for (int i = 0; i < dictSize; i++) { | |
wordSize = strlen(dict[i]) - 1; | |
isPalindrome = 1; | |
for (int j = 0; j < (wordSize - j) && isPalindrome; j++) { | |
if (dict[i][j] != dict[i][wordSize - j]) isPalindrome = 0; | |
} | |
numPalindromes += isPalindrome; | |
} | |
printf("%d\n", numPalindromes); | |
} | |
// Função que acha a frequência de matches do P1 em relação ao dicionário | |
void printFreqRegex(char *pattern, char **dict, int dictSize) { | |
int totalMatches = 0, result; | |
regex_t regex; | |
regcomp(®ex, pattern, REG_EXTENDED); | |
// Se houver match no regex, aumenta o número total de matches em 1 | |
for(int i = 0; i < dictSize; i++) { | |
result = regexec(®ex, dict[i], 0, NULL, 0); | |
if (result == 0) totalMatches++; | |
} | |
regfree(®ex); | |
printf("%d\n", totalMatches); | |
} | |
// Calcula qual a maior palavra do dicionário que obedece o pattern | |
// através de regex | |
void printLongestWordRegex(char *pattern, char **dict, int dictSize) { | |
int length = 0, index = 0, result; | |
regex_t regex; | |
regcomp(®ex, pattern, REG_EXTENDED); | |
// Se houver match, checa qual a maior palavra | |
for(int i = 0; i < dictSize; i++) { | |
result = regexec(®ex, dict[i], 0, NULL, 0); | |
if (result == 0) { | |
if (length < strlen(dict[i])) { | |
index = i; | |
length = strlen(dict[i]); | |
} | |
} | |
} | |
regfree(®ex); | |
printf("%s\n", dict[index]); | |
} | |
// Imprime todas as palavras no DICT que apresentam o padrão PATTERN | |
void printAllMatchingWords(char *pattern, char **dict, int dictSize) { | |
regex_t regex; | |
regcomp(®ex, pattern, REG_EXTENDED); | |
qsort(dict, dictSize, sizeof(char *), compare); | |
int result; | |
// Se houver match do regex, imprime o resultado | |
// Como já houve ordenação anteriormente, os resultados sairão ordenados | |
for(int i = 0; i < dictSize; i++) { | |
result = regexec(®ex, dict[i], 0, NULL, 0); | |
if (result == 0) { | |
printf("%s\n", dict[i]); | |
} | |
} | |
regfree(®ex); | |
} | |
// Usa um sistema de pontuação para determinar qual a palavra mais parecida | |
// com WORD. Calcula-se a pontuação baseada na "maior sequencia" de caracteres | |
// provenientes de WORD em cada palavra de DICT. | |
// Após isso, acha a maior pontuação e imprime o valor relacionado a ela | |
void printClosestWord(char *word, char **dict, int dictSize) { | |
int *points = calloc(dictSize, sizeof(int)); | |
int res = 0; | |
// Para cada palavra no dicionário | |
for (int i = 0; i < dictSize; i++) { | |
// Para cada letra da palavra | |
for (int j = 0; j < strlen(dict[i]); j++) { | |
// Para cada letra da substring/word | |
for (int k = 0; k < strlen(word); k++) { | |
// Checa se a letra de WORD é igual a letra da palavra sendo avaliada | |
// Se for igual, conta quantas letras em sequência pertencem as duas palavras | |
if (word[k] == dict[i][j]) { | |
res = 0; | |
for (int m = 0; m < strlen(word); m++) { | |
if (word[m] == dict[i][j + m]) { | |
res++; | |
} | |
} | |
// Checa se a pontuação atual é maior que a pontuação anterior | |
// Se for, a pontuação atual se torna a nova pontuação | |
points[i] = res > points[i] ? res : points[i]; | |
} | |
} | |
} | |
} | |
// Checa qual palavra teve a maior pontuação | |
res = 0; | |
for (int i = 0; i < dictSize; i++) { | |
if (points[i] > points[res]) | |
res = i; | |
// Em caso de empate, checa qual a menor palavra | |
else if (points[i] == points[res]) | |
res = strlen(dict[i]) > strlen(dict[res]) ? res : i; | |
} | |
// Imprime a menor palavra | |
printf("%s\n", dict[res]); | |
free(points); | |
} | |
// Função de comparação para o qsort | |
int compare(const void* a,const void* b) { | |
return strcmp(*(char**)a, *(char**)b); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment