Fundamentos da Programação Sequencial em C

  1. 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:

  1. As variáveis que recebem o retorno de getchar() devem ser do tipo char, int, ou ambos são aceitáveis?
  2. Como se pode exibir o valor numérico (ASCII) de um caractere? É possível usar putchar() ou apenas printf()?
  3. As variáveis do tipo int e char são sempre intercambiáveis? Por exemplo, char c1, c2; e int c1, c2; são equivalentes incondicionalmente?

Respostas e Considerações:

  • Para variáveis que recebem o resultado de getchar(), é recomendado o uso do tipo int. Isso ocorre porque getchar() pode retornar qualquer valor de caractere válido (0-255, dependendo da codificação) ou o valor especial EOF (End-Of-File), que geralmente é -1. Se uma variável char (que tipicamente é signed char, com faixa de -128 a 127) for usada, o valorr -1 de EOF pode 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ção putchar() é projetada para imprimir o caractere correspondente ao valor inteiro, não o valor numérico em si.
  • Os tipos int e char não são universalmente intercambiáveis. Embora um char possa ser implicitamente promovido a int e um int possa ser truncado para um char (com potencial perda de dados), o comportamento específico (como o caso de EOF ou overflow) torna o uso de int mais seguro para leitura de caracteres. Use char quando 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;
}

  1. 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;
}

  1. 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;
}

  1. 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=7 corresponde ao formato exato do primeiro scanf("a=%db=%d", ...).
  • 8.5 7.182e+1 fornece os valores para %f e %e. Note que 71.82 pode ser escrito como 7.182e+1.
  • Aa fornece os dois caracteres para scanf(" %c%c", ...). O espaço inicial no especificador %c ajuda a ignorar o caractere de nova linha que pode ter sido deixado pelo scanf anterior.
  1. 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:

  1. Qual será a saída quando o programa for executado? Por que?
  2. O que aconteceria se as linhas caractere_um = 97; e caractere_dois = 98; fossem alteradas para caractere_um = 197; e caractere_dois = 198;, mantendo o tipo char? Qual seria a saída e por quê?
  3. E se a declaração char caractere_um, caractere_dois; fosse alterada para int caractere_um, caractere_dois;, com os valores originais 97 e 98? Qual seria a saída e por quê?

Análise e Saída Esperada:

  • Cenário 1: Variáveis char inicializadas com 97 e 98

    Saída Esperada:

    Exibição como Caracteres: c1=a, c2=b
    Exibição como Inteiros: c1=97, c2=98
    
    

    Explicaçã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 char inicializadas com 197 e 198

    Saí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=-58
    
    

    Explicação: No C, o tipo char é frequentemente implementado como um signed char, que pode armazenar valores no intervalo de -128 a 127. Quando atribuímos 197 a um signed 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. Quando printf() usa %c com valores negativos (ou valores acima de 127 que foram truncados/overflow para um unsigned char), o comportamento é indefinido ou resulta em caracteres "estranhos" (não-ASCII padrão).

  • Cenário 3: Variáveis int inicializadas com 97 e 98

    Saída Esperada:

    Exibição como Caracteres: c1=a, c2=b
    Exibição como Inteiros: c1=97, c2=98
    
    

    Explicação: Ao declarar caractere_um e caractere_dois como int, os valores 97 e 98 são armazenados normalmente, pois estão dentro do intervalo de um int. A função printf(), ao receber um int e 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.

Tags: linguagem C I/O de Caracteres scanf printf putchar

Publicado em 7-5 06:18