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);
}
}