- Manipulação de Caracteres com Funções de Entrada e Saída em C
Nesta seção, exploramos o comportamento das funções getchar() e putchar() para lidar com caracteres, comparando-as com o uso de printf().
Questões para Análise:
- As variáveis que recebem o retorno de
getchar()devem ser do tipochar,int, ou ambos são aceitáveis? - Como se pode exibir o valor numérico (ASCII) de um caractere? É possível usar
putchar()ou apenasprintf()? - As variáveis do tipo
intecharsão sempre intercambiáveis? Por exemplo,char c1, c2;eint c1, c2;são equivalentes incondicionalmente?
Respostas e Considerações:
- Para variáveis que recebem o resultado de
getchar(), é recomendado o uso do tipoint. Isso ocorre porquegetchar()pode retornar qualquer valor de caractere válido (0-255, dependendo da codificação) ou o valor especialEOF(End-Of-File), que geralmente é -1. Se uma variávelchar(que tipicamente ésigned char, com faixa de -128 a 127) for usada, o valorr -1 deEOFpode ser confundido com um caractere válido, ou um caractere válido pode ser interpretado incorretamente. - Para exibir o código ASCII de um caractere, deve-se usar
printf()com o especificador de formato%d(decimal). A funçãoputchar()é projetada para imprimir o caractere correspondente ao valor inteiro, não o valor numérico em si. - Os tipos
intecharnão são universalmente intercambiáveis. Embora umcharpossa ser implicitamente promovido ainte umintpossa ser truncado para umchar(com potencial perda de dados), o comportamento específico (como o caso deEOFou overflow) torna o uso deintmais seguro para leitura de caracteres. Usecharquando tiver certeza de que os valores estarão dentro do seu domínio e para otimização de memória.
#include <stdio.h>
int main() {
int primeiro_char, segundo_char; // Usamos 'int' para compatibilidade com EOF
printf("Por favor, insira o primeiro caractere: ");
primeiro_char = getchar(); // Lê o primeiro caractere
getchar(); // Consome o caractere de nova linha ('\n') deixado pelo Enter
printf("Agora, insira o segundo caractere: ");
segundo_char = getchar(); // Lê o segundo caractere
getchar(); // Consome o caractere de nova linha ('\n')
printf("\n--- Saída usando putchar() ---\n");
putchar(primeiro_char);
putchar('\n'); // Imprime uma nova linha
putchar(segundo_char);
putchar('\n');
printf("\n--- Saída usando printf() com '%%c' ---\n");
printf("Primeiro caractere lido: %c\n", primeiro_char);
printf("Segundo caractere lido: %c\n", segundo_char);
printf("\n--- Valores ASCII (Decimais) dos caracteres ---\n");
printf("ASCII do primeiro caractere: %d\n", primeiro_char);
printf("ASCII do segundo caractere: %d\n", segundo_char);
return 0;
}
- Cálculo de Propriedades Geométricas
Este programa calcula diversas propriedades geométricas de um círculo, esfera e cilindro, como perímetro, área e volume, com base em um raio e uma altura fornecidos pelo usuário. Os resultados são formatados para exibir duas casas decimais.
#include <stdio.h>
#include <math.h> // Necessário para a função pow() e, opcionalmente, M_PI
// Define PI se M_PI não estiver disponível em math.h
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
int main() {
double raio_base, altura_cilindro; // Variáveis para armazenar o raio e a altura
printf("Insira o raio da base e a altura do cilindro (separados por espaço): ");
// Lê os valores de entrada com verificação de sucesso
if (scanf("%lf %lf", &raio_base, &altura_cilindro) != 2) {
printf("Erro na leitura. Por favor, insira dois números válidos.\n");
return 1; // Retorna um código de erro
}
// Cálculos das propriedades
double perimetro_circulo = 2 * M_PI * raio_base;
double area_circulo = M_PI * raio_base * raio_base;
double area_esfera = 4 * M_PI * raio_base * raio_base;
double volume_esfera = (4.0 / 3.0) * M_PI * pow(raio_base, 3); // Usando pow para raio^3
double volume_cilindro = M_PI * raio_base * raio_base * altura_cilindro;
printf("\n--- Resultados dos Cálculos Geométricos ---\n");
printf("Perímetro do Círculo: %.2f\n", perimetro_circulo);
printf("Área do Círculo: %.2f\n", area_circulo);
printf("Área da Superfície da Esfera: %.2f\n", area_esfera);
printf("Volume da Esfera: %.2f\n", volume_esfera);
printf("Volume do Cilindro: %.2f\n", volume_cilindro);
return 0;
}
- Implementação de Cifra Simples (Cifra de César)
Este exemplo demonstra uma cifra de César simples, onde cada letra de uma palavra é substituída pela quarta letra seguinte no alfabeto. A palavra "China" será criptografada para "Glmre". O programa inicializa cinco variáveis char com as letras da palavra e aplica o deslocamento, exibindo o resultado com putchar() e printf().
#include <stdio.h>
int main() {
// Declaração e inicialização dos caracteres originais
char char1 = 'C';
char char2 = 'h';
char char3 = 'i';
char char4 = 'n';
char char5 = 'a';
const int deslocamento = 4; // Constante para o deslocamento da cifra
// Aplica o deslocamento a cada caractere
char1 += deslocamento;
char2 += deslocamento;
char3 += deslocamento;
char4 += deslocamento;
char5 += deslocamento;
printf("--- Saída Criptografada (via putchar()): ");
putchar(char1);
putchar(char2);
putchar(char3);
putchar(char4);
putchar(char5);
putchar('\n');
printf("--- Saída Criptografada (via printf()): %c%c%c%c%c\n",
char1, char2, char3, char4, char5);
return 0;
}
- Entrada de Dados Formatada com
scanf()
Dada a seguinte estrutura de chamadas scanf(), precisamos determinar a sequência exata de caracteres que o usuário deve digitar no teclado para que as variáveis recebam os valores desejados: a=3, b=7, x=8.5, y=71.82, c1='A', c2='a'.
#include <stdio.h>
int main() {
int var_a, var_b;
float var_x, var_y;
char char_primeiro, char_segundo;
// Primeiro scanf: espera um formato "a=NÚMEROb=NÚMERO"
scanf("a=%db=%d", &var_a, &var_b);
// Segundo scanf: espera dois números de ponto flutuante, o segundo em notação científica
scanf("%f%e", &var_x, &var_y);
// Terceiro scanf: espera dois caracteres
// Um espaço antes de %c ignora qualquer caractere de espaço em branco (incluindo quebras de linha anteriores)
scanf(" %c%c", &char_primeiro, &char_segundo);
// Opcional: imprimir para verificar os valores lidos
printf("\nValores lidos:\n");
printf("a = %d, b = %d\n", var_a, var_b);
printf("x = %.2f, y = %.2f\n", var_x, var_y);
printf("Primeiro Char = %c, Segundo Char = %c\n", char_primeiro, char_segundo);
return 0;
}
Entrada Requerida no Teclado:
Para obter os valores desejados (a=3, b=7, x=8.5, y=71.82, c1='A', c2='a'), a entrada no teclado deve ser a seguinte:
a=3b=7
8.5 7.182e+1
Aa
Explicação:
a=3b=7corresponde ao formato exato do primeiroscanf("a=%db=%d", ...).8.5 7.182e+1fornece os valores para%fe%e. Note que71.82pode ser escrito como7.182e+1.Aafornece os dois caracteres parascanf(" %c%c", ...). O espaço inicial no especificador%cajuda a ignorar o caractere de nova linha que pode ter sido deixado peloscanfanterior.
- Análise de Tipos e Comportamento de Overflow em C
Vamos analisar o comportamento de um programa C simples que atribui valores numéricos a variáveis char e int e as exibe de diferentes maneiras.
Cenário Base:
Considere o seguinte código:
#include <stdio.h>
int main() {
char caractere_um, caractere_dois; // Variáveis do tipo char
caractere_um = 97; // Atribui o valor numérico 97
caractere_dois = 98; // Atribui o valor numérico 98
printf("Exibição como Caracteres: c1=%c, c2=%c\n", caractere_um, caractere_dois);
printf("Exibição como Inteiros: c1=%d, c2=%d\n", caractere_um, caractere_dois);
return 0;
}
Questões para Reflexão:
- Qual será a saída quando o programa for executado? Por que?
- O que aconteceria se as linhas
caractere_um = 97;ecaractere_dois = 98;fossem alteradas paracaractere_um = 197;ecaractere_dois = 198;, mantendo o tipochar? Qual seria a saída e por quê? - E se a declaração
char caractere_um, caractere_dois;fosse alterada paraint caractere_um, caractere_dois;, com os valores originais97e98? Qual seria a saída e por quê?
Análise e Saída Esperada:
-
Cenário 1: Variáveis
charinicializadas com97e98Saída Esperada:
Exibição como Caracteres: c1=a, c2=b Exibição como Inteiros: c1=97, c2=98Explicação: Em ASCII, o valor 97 corresponde ao caractere 'a' e 98 ao 'b'. Quando
printf()usa%c, ele interpreta o valor numérico como um código de caractere. Com%d, ele exibe o valor numérico inteiro armazenado, que são 97 e 98. -
Cenário 2: Variáveis
charinicializadas com197e198Saída Esperada:
Exibição como Caracteres: c1=�, c2=� (O caractere pode variar, sendo geralmente um caractere estendido ou de erro) Exibição como Inteiros: c1=-59, c2=-58Explicação: No C, o tipo
charé frequentemente implementado como umsigned char, que pode armazenar valores no intervalo de -128 a 127. Quando atribuímos 197 a umsigned char, ocorre um overflow. O valor 197 é interpretado como 197 - 256 = -59 (em um sistema de 8 bits com complemento de dois). Similarmente, 198 torna-se -58. Quandoprintf()usa%ccom valores negativos (ou valores acima de 127 que foram truncados/overflow para umunsigned char), o comportamento é indefinido ou resulta em caracteres "estranhos" (não-ASCII padrão). -
Cenário 3: Variáveis
intinicializadas com97e98Saída Esperada:
Exibição como Caracteres: c1=a, c2=b Exibição como Inteiros: c1=97, c2=98Explicação: Ao declarar
caractere_umecaractere_doiscomoint, os valores 97 e 98 são armazenados normalmente, pois estão dentro do intervalo de umint. A funçãoprintf(), ao receber uminte usar%c, ainda imprimirá o caractere correspondente ao valor ASCII (os 8 bits menos significativos do inteiro). Ao usar%d, ela simplesmente imprime o valor inteiro como esperado.