Falando como o Cebolinha
O Cebolinha é um menino muito esperto, mas tem dificuldades de dicção. O seu problema é que toda vez que uma palavra tem um erre (R), ou dois erres (RR), ele o troca por um ele.
Queremos escrever um programa para saber como o Cebolinha falaria uma palavra.
Entrada
A entrada é uma única palavra que pode ou não conter erres e está escrita em caixa alta.
CHURRASQUEIRO
Saída
A palavra como Cebolinha falaria.
CHULASQUEILO
Implementando
Strings em C
O tratamento de strings em C é muito diferente do tratamento de strings em
Python. O motivo disso é que C é uma linguagem de nível mais baixo do que Python
e não tem um tipo primitivo de string. Em Python, existe um tipo str
e
todas as dificuldades de lidar com strings são escondidas pelo interpretador.
Antes de começarmos nossa tarefa, vamos fazer um exercício diferente: verificar
se uma palavra é igual ao seu inverso, isso é, se uma palavra é um palíndromo.
Em Python alguém poderia escrever
palavra = input() inverso = palavra[::-1] if palavra == inverso: print("É palíndromo") else: print("Não é palíndromo")
A expressão palavra[::-1]
parece meio mágica, mas é apenas uma conveniência de
Python: ela diz para copiar toda a string, mas andando -1
caractere por vez,
isso é, copie o último, depois o penúltimo, depois o antepenúltimo etc.
Poderíamos escrever nossa própria função que faz isso:
def copiar_inverso(palavra): inverso = "" i = len(palavra) - 1 # índice da última letra while i >= 0: inverso = inverso + palavra[i] # concatena a i-ésima letra de palavra i = i - 1 return inverso palavra = input() inverso = copiar_inverso(palavra) if palavra == inverso: print("É palíndromo") else: print("Não é palíndromo")
Se em C não há um tipo para strings, então como representá-las? A resposta é
usarmos um vetor de caracteres, isso é, um vetor de char
. Aqui descobrimos a
primeira diferença fundamental: como é o caso de todo vetor estático, em C uma
string deve ter um tamanho máximo permitido. Vamos começar lendo uma string e
escrevendo-a de volta.
#include <stdio.h> #define MAX_PALAVRA 10 int main() { char palavra[MAX_PALAVRA]; char inverso[MAX_PALAVRA]; scanf("%s", palavra); printf("Você escreveu %s\n", palavra); }
Para ler uma palavra do teclado, usamos scanf("%s", palavra)
; o trecho %s
indica para a função scanf
que ela deve ler uma palavra do teclado que não
contém espaços e guardá-la no vetor palavra
. Repare que nesse caso não usamos
o símbolo &
.
Descobrindo o tamanho da string
Se você se lembra da tarefa de vetores, deve recordar que guardávamos o número
n
de posições utilizadas juntamente com cada vetor. Esse não é o caso do
código acima, então como sabemos quantas letras realmente foram lidas e
guardadas no vetor palavra
por scanf
? Como saber qual é a última posição
utilizada do vetor palavra
?
A resposta é que scanf
copia um caractere especial '\0'
depois do último
caractere lido. Assim, se a palavra lida é CASA
, então o vetor terá a seguinte
forma
índice: [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] +---+---+---+---+---+---+---+---+---+---+ palavra: | C | A | S | A |\0 | ? | ? | ? | ? | ? | +---+---+---+---+---+---+---+---+---+---+
As posições marcadas com ?
não estão inicializadas, então elas podem conter
qualquer valor. Repare que, como gastamos uma posição com o '\0'
, a maior
palavra que cabe nesse vetor tem tamanho 9
caracteres.
Para descobrir o tamanho de uma string, podemos usar a função strlen
da
biblioteca padrão de funções em C. Para usar essa função precisamos incluir o
arquivo string.h
no topo do arquivo. Mas tudo o que essa função faz é contar
quantos caracteres há antes do '\0'
. Assim, se quisermos, podemos construir
nossa própria função que calcula o comprimento de uma string.
int comprimento_str(char string[]) { int comprimento = 0; while (string[comprimento] != '\0') { comprimento += 1; } return comprimento; }
Obtendo o inverso
Uma consequência de usar o caractere '\0'
para finalizar toda string é que, se
quisermos escrever funções que devolvem uma string, então nós também devemos
adicionar um '\0'
no final da string criada. Lembre-se de que como uma
string é um vetor, se quisermos criar ou alterar uma string por uma função,
então devemos passá-la por parâmetro. Na implmentação em C de nossa função
copiar_inverso
, iremos fazer as duas coisas.
void copiar_inverso(char palavra[], char inverso[]) { int i, j; i = comprimento_str(palavra) - 1; /* índice da última letra de palavra */ j = 0; /* índice da primeira posição de inverso */ while (i >= 0) { /* copia a i-ésima letra de palavra para a j-ésima posição de inverso */ inverso[j] = palavra[i]; i = i - 1; j = j + 1; } /* adicionamos o '\0' para indicar que a string inverso terminou */ inverso[j] = '\0'; }
Comparando duas strings
Agora que já sabemos ler uma palavra
e construir o inverso
, basta comparar
essas duas strings para saber se palavra
é um palíndromo. Embora seja tentador
escrever palavra == inverso
, como faríamos em Python, esse trecho não vai
funcionar em C! A razão é que uma string em C é um vetor e, portanto, está
restrita a todas as limitações de um vetor: não podemos comparar dois
vetores diretamente.
De novo, podemos escrever uma nova função que recebe duas strings, verifica se
elas têm o mesmo tamanho e, se tiver, compara cada uma das suas posições. Ao
invés de fazermos tudo isso, dessa vez vamos usar a função strcmp
da
biblioteca string.h
. Para usarmos essa função, fazemos uma chamada
strcmp(palavra1, palavra2)
que irá devolver um número inteiro
- menor que zero se
palavra1
vem antes depalavra2
no dicionário - igual a zero se ambas palavras forem iguais
- maior que zero se
palavra1
vem depois depalavra2
no dicionário
Juntando tudo, podemos escrever um programa.
#include <stdio.h> #include <string.h> #define MAX_PALAVRA 20 /* funções comprimento_str e copiar_inverso */ int main() { char palavra[MAX_PALAVRA]; char inverso[MAX_PALAVRA]; scanf("%s", palavra); copiar_inverso(palavra, inverso); if (strcmp(palavra, inverso) == 0) /* se as strings são iguais */ printf("É palíndromo\n"); else printf("Não é palíndromo\n"); }
Resolvendo o exercício
Finalmente podemos voltar ao nosso problema inicial: trocar os erres por eles. Devemos prestar atenção em uma sutileza: se uma palavra tiver dois erres (RR) colados, então queremos substituí-los por um único ele (L).
Em Python, poderíamos escrever:
def copiar_cebolinha(palavra): i = 0 # índice da letra em palavra ultima_eh_erre = False # indica se a última letra copiada foi R palavra_modificada = "" # string a ser devolvida for i in range(len(palavra)): letra = palavra[i] if letra == 'R': if not ultima_eh_erre: palavra_modificada += 'L' ultima_eh_erre = True else: palavra_modificada += letra ultima_eh_erre = False return palavra_modificada palavra = input() palavra_modificada = copiar_cebolinha(palavra) print(palavra_modificada)
Observe que a variável ultima_eh_erre
é do tipo bool
. Em C, não há um tipo
booleano. Para saber como representar um valor booleano em C, veja o exemplo
abaixo. Resolva agora a tarefa em C. Você pode começar modificando o código do
palíndromo disponível em Falando como o
Cebolinha.
Exemplos relacionados
Na linguagem C, ao invés de usarmos um tipo dedicado a valores booleanos,
utilizamos um inteiro como se fosse um valor booleano e adotamos a seguinte
convenção: uma variável declarada como int valor_booleano;
é interpretada
como:
- VERDADEIRA se
valor_booleano
for diferente de zero - FALSO se
valor_booleano
for igual a zero
O código a seguir verifica se um número é primo (muito lentamente).
#include <stdio.h> int eh_primo(int n) { int i; for (i = 2; i < n; i++) { if (n % i == 0) return 0; /* devolve falso */ } return 1; /* devolve verdadeiro */ } int main() { int n; scanf("%d", &n); if (eh_primo(n)) { printf("%d é primo\n", n); } else { printf("%d NÃO é primo\n", n); } }