CS50: S2 | Readability e a Complexidade Textual
Matheus 🇧🇷
Posted on May 5, 2022
Introdução
Esse exercício visa utilizar o readability como medida de complexidade textual. Um exemplo de aplicativo do dia a dia que utiliza um sistema de readability para dizer se o seu texto está fácil de ser compreendido ou não, é o Hemingway Editor. Eles utilizam algum algoritmo que analisa quantos advérbios, se faz uso ou não da voz passiva e por aí vai.
Nesta atividade será algo bem mais simples, iremos analisar a quantidade de letras, palavras e sentenças, assim conseguiremos utilizar o index de Coleman-Liau projetado exatamente para a lingua inglesa, para descobrir a complexidade do texto.
A fórmula utilizada é: index = 0.0588 * L - 0.296 * S - 15.8
Sem mais delongas, vamos começar o exercicio.
Quebrando o código
- Headers utilizados
#include <cs50.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
- Prototipos declarados
int numberOfLetters(string text);
int numberOfWords(string text);
int numberOfSentences(string text);
float indexL(int letters, int words);
float indexS(int sentences, int words);
float colemanLiau(float L, float S);
void showGrade(float index);
- função Main
int main(void)
{
string text = get_string("Text: ");
int number_of_letters = numberOfLetters(text);
int number_of_words = numberOfWords(text);
int number_of_sentences = numberOfSentences(text);
float L = indexL(number_of_letters, number_of_words);
float S = indexS(number_of_sentences, number_of_words);
float indexGrade = colemanLiau(L, S);
showGrade(indexGrade);
}
Gostaria de aproveitar esse ponto para dizer que não existe uma só forma de resolver o problema, e provavelmente você pode ter feito algo completamente diferente do que eu fiz, e está tudo bem.
Contando letras
Na aula 2 vimos que as strings (textos) são arrays de caracteres
. E todo essa resolução ela gira em torno desse conceito muito importante!
int numberOfLetters(string text) {
int counter = 0;
for(int i = 0; i < strlen(text); i++) {
if(text[i] >= 'a' && text[i] <= 'z') {
counter++;
} else if(text[i] >= 'A' && text[i] <= 'Z') {
counter++;
}
}
return counter;
}
- Temos um contador que inicialmente tem valor 0.
Pois nenhuma letra foi contada até agora, durante a sua inicialização.
- Monta-se a estrutura do loop, mas dessa vez o nosso limitador é
strlen()
.
No Manual do CS50 temos na biblioteca string.h
a função strlen.
É por isso que incluimos o string.h
no nosso header. Para que possamos ter acesso a função strlen()
.
E o que ela faz? Ela retorna o tamanho dessa string(texto).
- Começam as condicionais
Como iremos de letra em letra, utilizando as bracket notations. Caso não se lembre, reveja a parte da aula que fala sobre Arrays.
E iremos comparar se a letra está entre a a z, minúscula, ou A a Z, maiúscula.
Caso estejam, adicionará um ao nosso contador e pulará para a próxima letra.
Ao final, retorna o valor desse contador.
int number_of_letters = numberOfLetters(text);
Com esse valor retornado, eu armazeno esse valor dentro de uma variável para ser usada mais tarde.
Contando palavras
O conceito é o mesmo de cima, a diferença agora é que farei uso da Tabela ASCII e só irei procurar pelo valor correspondente ao espaço.
int numberOfWords(string text) {
int counter = 1;
for(int i = 0; i < strlen(text); i++) {
if( (int) text[i] == 32) {
counter++;
}
}
return counter;
}
- Faço um type casting em relação a letra.
Type Casting é um processo em C onde a gente troca a variável que pertence a um tipo de dado para outro.
Neste caso, estou transformando um tipo de dado char -> int.
Então por exemplo:
- Char: A > Int: 65
- Char: 0 > Int: 48
- Char: ! > Int: 33
Char: [espaço] > Int: 32
O motivo do contador ser UM
Estou partindo do principio que sempre será escrito uma palavra, então sempre terá a primeira palavra colocada, onde eu não terei um marcador pra ser utilizado como referência (um espaço). Então para isso, já considerei que o contador começará com um.
- Ao final, retorna o valor desse contador.
int number_of_words = numberOfWords(text);
Contando sentenças
int numberOfSentences(string text) {
int counter = 0;
for(int i = 0; i < strlen(text); i++) {
if((int) text[i] == 33 || (int) text[i] == 46 || (int) text[i] == 63) {
counter++;
}
}
return counter;
}
Aqui, valendo-se da mesma regra das palavras
Desta vez, os maracadores são: o ponto final, o ponto de exclamação, e a interrogação.
Ao final, retorna o valor desse contador
int number_of_sentences = numberOfSentences(text);
E também, como nos dois primeiros, armazenando esses valores em variáveis para serem usados posteriormente.
Indices e o Index Coleman-Liau
index = 0.0588 * L - 0.296 * S - 15.8
As fórmulas utilizadas a seguir, elas seguem o dito pelo enunciado. Agora é aplicar valores.
Calculando L
float indexL(int letters, int words) {
return letters * 100.0 / words;
}
E utilizando as variáveis onde armazenamos os valores até agora, chamamos essa função assim.
float L = indexL(number_of_letters, number_of_words);
E agora, armazenando esse resultado em uma nova variável
Calculando S
float indexS(int sentences, int words) {
return sentences * 100.0 / words;
}
O processo é exatamente o mesmo.
float S = indexS(number_of_sentences, number_of_words);
Calculando o index Coleman-Liau
De posse dos valores de L e S, criamos uma nova função:
float colemanLiau(float L, float S) {
return (0.0588 * L) - (0.296 * S) - 15.8;
}
E aqui, vou armazenar o valor desse float em uma nova variável.
float indexGrade = colemanLiau(L, S);
Exibindo a nota em Tela
De posse dos valor do index, o problema nos pede:
- Caso o valor seja 1 ou menor, exibir: Before Grade 1
- Caso o valor seja 16 ou maior, exibir: Grade 16+
- Caso o valor esteja entre, ser arredondado para o seu inteiro mais próximo.
void showGrade(float index) {
if(index < 1) {
printf("Before Grade 1\n");
} else if (index > 16) {
printf("Grade 16+\n");
} else {
printf("Grade %i\n", (int) round(index));
}
}
E aqui, fiz o uso da função round()
. Essa função, também pode ser encontrada na Docs do cs50. Ela pertence a biblioteca math.h
, e também é por isso que adicionamos ao nosso header.
Resultados
E a função com headers, prototipos e a main juntas.
#include <cs50.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
int numberOfLetters(string text);
int numberOfWords(string text);
int numberOfSentences(string text);
float indexL(int letters, int words);
float indexS(int sentences, int words);
float colemanLiau(float L, float S);
void showGrade(float index);
int main(void)
{
string text = get_string("Text: ");
int number_of_letters = numberOfLetters(text);
int number_of_words = numberOfWords(text);
int number_of_sentences = numberOfSentences(text);
float L = indexL(number_of_letters, number_of_words);
float S = indexS(number_of_sentences, number_of_words);
float indexGrade = colemanLiau(L, S);
showGrade(indexGrade);
}
Obrigado por ler até aqui, espero que tenha te ajudado.
Estou cobrindo o CS50, semana a semana, e fazendo a resolução de alguns dos exercicios da semana para ajudar quem está começando.
Me siga aqui no dev.to para acompanhar, ou também me siga no twitter para acompanhar quando estou postando ou comentando sobre códigos que estou aprendendo e desenvolvendo.
Te vejo na próxima!
Posted on May 5, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.