Escrever um programa em C que leia uma cadeia de caracteres e imprima todas as palavras que contenham três ou mais vogais.
Passo 1
O enunciado pede: ler uma cadeia de caracteres e imprimir todas as palavras que contenham três ou mais vogais.
Informações relevantes que o enunciado fornece (ou que vou assumir, de forma explícita, para poder implementar sem ambiguidade):
Informações relevantes que o enunciado fornece (ou que vou assumir, de forma explícita, para poder implementar sem ambiguidade):
- A entrada é uma única cadeia de caracteres (uma linha de texto).
- Precisamos identificar “palavras” e testar, para cada palavra, se ela tem pelo menos três vogais.
- Vou considerar como vogais as letras:
tanto em maiúsculas quanto em minúsculas (caso-insensível). - Vou definir “palavra” como uma sequência de caracteres alfabéticos (ou seja, letras). Caracteres que não são letras (espaço, pontuação, números, etc.) separam as palavras.
- Não vou tratar letras acentuadas (
etc.) como vogais especiais — isso exigiria tratamento de acordo com codificação/locale; aqui trataremos apenas as vogais ASCII mencionadas. - Saída: cada palavra que tiver três ou mais vogais será impressa (uma por linha, para ficar claro).
Passo 2
Escolha do método (o porquê):
Existem várias formas de fazer isso em C (por exemplo, usar para separar por delimitadores, usar expressões regulares com bibliotecas extras, etc.). Vou usar um método bem básico e confiável: percorrer a string caractere a caractere, construir a palavra atual enquanto os caracteres forem letras, e ao encontrar um separador (ou o fim da cadeia) eu avalio a palavra construída. Motivos:
Existem várias formas de fazer isso em C (por exemplo, usar
- É um método que usa apenas biblioteca padrão de C (<stdio.h>, <ctype.h>, <string.h>), comum em provas.
- Permite controlar exatamente o que é considerado letra e o que é delimitador.
- É fácil de explicar e implementar sem funções avançadas.
Passo 3
Funções e conceitos da biblioteca que vamos usar (a mini-aula):
-
: lê uma linha de entrada segura (não ultrapassa o tamanho do buffer). Retorna em caso de erro/fim de arquivo. -
: obtem o comprimento (número de caracteres) da string . -
(em <ctype.h>): retorna verdadeiro se for uma letra (A–Z ou a–z). Atenção: o argumento deve ser convertido para por segurança quando for possivelmente negativo. -
(em <ctype.h>): converte para minúscula (se for letra). Também passe . - Lógica básica de buffers: vamos manter um buffer para a string inteira e outro para construir a palavra atual; quando o separador aparece, finalizamos a palavra, avaliamos e limpamos o buffer da palavra.
- Contagem de vogais: para cada letra adicionada à palavra incrementamos um contador se for vogal.
Exemplo rápido de uso:
- Se a entrada for: “Programação em C é legal”, considerando apenas vogais ASCII sem acentos, as palavras seriam “Programacao”, “em”, “C”, “e”, “legal” (mas lembre que acentos seriam ignorados ou considerados não-letras dependendo do locale).
Passo 4
Pseudocódigo / lógica passo a passo (já bem mastigado, prepare para codificar):
- Ler a linha com
para um buffer grande o suficiente. - Remover o caractere de nova linha final (se existir).
- Inicializar: índice do buffer da palavra
, contador de vogais . - Para cada caractere
cda string (incluindo processar o'\0'ao final):- Se
for verdadeiro: - acrescentar
cao buffer da palavra (se ainda houver espaço). - se
estiver entre a,e,i,o,uentão incrementarvcount.
- acrescentar
- Senão (ou seja,
cé separador ou final):- se
wlen > 0(temos uma palavra pronta):- terminar a palavra com
'\0'. - se
vcount >= 3então imprimir a palavra. - resetar
wlen = 0evcount = 0.
- terminar a palavra com
- se
c == '\0'então sair do laço (fim).
- se
- Se
- Encerrar.
Observação importante: devemos lembrar de processar a última palavra após o fim da string — no pseudocódigo acima isso é tratado porque iteramos até incluir o
'\0' e, ao vê-lo, o ramo “senão” trata a palavra final.Passo 5
Implementação de como detectar vogal (mini-aula e cuidado prático):
- Vamos criar uma função auxiliar simples:
- Recebe um caractere
c(tipochar). - Converte para minúscula com
. - Verifica se é igual a
, , , ou . - Retorna 1 se for vogal, 0 caso contrário.
- Recebe um caractere
- Por que converter para minúscula? Para tratar
Aeado mesmo jeito sem duplicar verificações. - Por que usar
ao passar para tolower/isalpha? Para evitar comportamento indefinido quandocharfor negativo (em algumas implementações), é a prática segura.
Passo 6
Tratamento de limites, buffer overflow e saída:
- Definir constantes:
para o tamanho da linha lida (por ex. 10000) e para o tamanho máximo da palavra que guardaremos (por ex. 1000). Em provas, esses tamanhos são suficientes; mencionar que, em código de produção, considerar dinamicidade ou limites reais do problema. - Se uma palavra for maior que
vamos ignorar os caracteres excedentes para não estourar o buffer, mas continuar contando vogais (para não perder a condição) — implementamos essa estratégia simples no código. - Impressão: imprimo cada palavra que satisfaz a condição em uma linha separada com
.
Passo 7
Complexidade e dicas para a prova (curta e motivadora):
- Complexidade de tempo: O(n), onde
é o comprimento da cadeia de entrada, porque processamos cada caractere uma vez. - Complexidade de espaço: O(1) extra (além do buffer de entrada), pois só guardamos a palavra atual e contadores.
- Dica para a prova: explique o algoritmo em poucas frases e diga que você percorre caractere a caractere e verifica letras/vogais; isso costuma ser suficiente para ganhar créditos antes de mostrar o código — depois entregue o código limpo.
- Força aí! Respira, faz com calma, segue o passo a passo — você consegue.
Passo 8
Agora vem a implementação final. Ela segue tudo que expliquei: usa
, percorre caractere a caractere, constrói palavras com letras apenas, conta vogais (caso-insensível) e imprime as palavras que tiverem três ou mais vogais. Teste mental rápido: para entrada “Universidade de São Paulo”, como não tratamos acentos, “Universidade” (tem 6 vogais ASCII: u,i,e,i,a,e -> várias) será detectada e impressa; “de” não; “São” tem 1 vogal ASCII (o acento não contado), então não.
Resposta
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <ctype.h>
#include <string.h>
#define MAX_LEN 10000
#define MAX_WORD 1000
#define MAX_WORD 1000
int is_vowel(char c) {
c = tolower((unsigned char)c);
return (c == ‘a’ || c == ‘e’ || c == ‘i’ || c == ‘o’ || c == ‘u’);
}
c = tolower((unsigned char)c);
return (c == ‘a’ || c == ‘e’ || c == ‘i’ || c == ‘o’ || c == ‘u’);
}
int main(void) {
char s[MAX_LEN];
if (!fgets(s, sizeof s, stdin)) return 0;
char s[MAX_LEN];
if (!fgets(s, sizeof s, stdin)) return 0;
size_t n = strlen(s);
if (n > 0 && s[n - 1] == '\n') s[n - 1] = '\0';
char word[MAX_WORD];
int wlen = 0;
int vcount = 0;
for (size_t i = 0; ; ++i) {
char c = s[i];
if (c != '\0' && isalpha((unsigned char)c)) {
if (wlen < MAX_WORD - 1) {
word[wlen++] = c;
}
if (is_vowel\text{(c)}) vcount++;
} else {
if (wlen > 0) {
word[wlen] = '\0';
if (vcount >= 3) {
printf("%s\n", word);
}
wlen = 0;
vcount = 0;
}
if (c == '\0') break;
}
}
return 0;
}