Nesta aula, vamos explorar as funções fundamentais de entrada e saída (E/S) em C, que permitem a comunicação entre o programa e o usuário ou outros dispositivos. Dominar printf e scanf é essencial para qualquer programador C, pois são as ferramentas mais comuns para exibir dados e ler entradas. Além disso, veremos funções mais simples como putchar e getchar, e entenderemos o papel do buffer no comportamento dessas funções.

Ao final, você será capaz de formatar saídas, ler entradas com segurança e compreender como os dados fluem entre o programa e o terminal.

printf e especificadores

A função printf é usada para exibir dados formatados na saída padrão (geralmente o terminal). Ela pertence à biblioteca padrão <stdio.h>. Sua sintaxe básica é: printf("string de formato", argumentos);. A string de formato contém texto literal e especificadores de formato (como %d para inteiros) que são substituídos pelos valores dos argumentos.

Os especificadores mais comuns incluem: %d (int), %f (float/double), %c (char), %s (string), %p (ponteiro), %x (hexadecimal). Você pode modificar a formatação com flags, largura e precisão, por exemplo: %5d (largura mínima 5), %.2f (duas casas decimais).

#include <stdio.h>

int main() {
    int idade = 25;
    float altura = 1.75;
    char inicial = 'A';
    char nome[] = "Ana";

    printf("Idade: %d\n", idade);
    printf("Altura: %.2f\n", altura);
    printf("Inicial: %c\n", inicial);
    printf("Nome: %s\n", nome);
    printf("Idade: %5d\n", idade); // largura 5
    return 0;
}

scanf e cuidados

A função scanf lê dados formatados da entrada padrão (teclado). Sua sintaxe é scanf("string de formato", &variaveis);. É crucial usar o operador & antes das variáveis (exceto para strings, que já são ponteiros). Os especificadores são similares aos do printf, mas com algumas diferenças: %f lê float, %lf lê double.

Principais cuidados: (1) Verifique o retorno de scanf (número de itens lidos) para detectar erros. (2) Ao ler strings, %s não lê espaços e pode causar estouro de buffer; prefira fgets para strings. (3) O caractere de nova linha (\n deixado no buffer) pode interferir em leituras subsequentes; use um espaço antes de %c para consumir whitespace.

#include <stdio.h>

int main() {
    int numero;
    float decimal;
    char letra;
    char palavra[50];

    printf("Digite um inteiro: ");
    scanf("%d", &numero);
    printf("Digite um float: ");
    scanf("%f", &decimal);
    printf("Digite um caractere: ");
    scanf(" %c", &letra); // espaço antes de %c consome o \n
    printf("Digite uma palavra: ");
    scanf("%s", palavra); // sem & para string

    printf("Você digitou: %d, %.2f, %c, %s\n", numero, decimal, letra, palavra);
    return 0;
}

putchar/getchar

putchar exibe um único caractere na saída padrão, enquanto getchar lê um caractere da entrada padrão. São funções mais simples que printf/scanf e úteis para processamento caractere a caractere. Ambas retornam um int (EOF em caso de erro ou fim de arquivo).

#include <stdio.h>

int main() {
    char c;
    printf("Digite um caractere: ");
    c = getchar();
    printf("Você digitou: ");
    putchar(c);
    putchar('\n');
    return 0;
}

Quando usamos getchar após scanf, o caractere de nova linha pode ser capturado. Por isso, muitas vezes é necessário limpar o buffer.

Buffer

O buffer é uma área de memória usada para armazenar temporariamente dados de E/S. Em C, a entrada padrão é geralmente buffered, ou seja, os caracteres são armazenados até que uma nova linha seja lida (buffer de linha). Isso afeta funções como getchar e scanf: elas só processam a entrada após o usuário pressionar Enter.

Por exemplo, se você usa scanf("%d") e depois getchar(), o getchar pode ler o \n deixado no buffer. Para evitar isso, você pode consumir o \n com um getchar extra ou usar scanf(" %c") (espaço antes de %c). Outra técnica é usar while(getchar() != '\n'); para limpar o buffer até a nova linha.

#include <stdio.h>

int main() {
    int num;
    char ch;

    printf("Digite um número: ");
    scanf("%d", &num);
    // Limpa o buffer até a nova linha
    while(getchar() != '\n');

    printf("Digite um caractere: ");
    ch = getchar();
    printf("Número: %d, Caractere: %c\n", num, ch);
    return 0;
}

Boas práticas

Sempre verifique o retorno de scanf e getchar para tratar entradas inválidas. Prefira fgets para ler strings e depois converta com sscanf para maior segurança. Evite usar gets (obsoleto). Lembre-se de incluir <stdio.h> e usar \n para quebras de linha.

Exercícios

  1. Escreva um programa que leia um número inteiro e exiba seu quadrado usando printf.
  2. ✓ Resposta:
    #include <stdio.h>
    int main() {
        int num;
        printf("Digite um inteiro: ");
        scanf("%d", &num);
        printf("Quadrado: %d\n", num * num);
        return 0;
    }
  3. Leia dois números float e exiba a soma com duas casas decimais.
  4. ✓ Resposta:
    #include <stdio.h>
    int main() {
        float a, b;
        printf("Digite dois floats: ");
        scanf("%f %f", &a, &b);
        printf("Soma: %.2f\n", a + b);
        return 0;
    }
  5. Use getchar para ler uma string de até 10 caracteres (sem scanf) e exiba com putchar.
  6. ✓ Resposta:
    #include <stdio.h>
    int main() {
        char str[11];
        int i = 0;
        char c;
        printf("Digite até 10 caracteres: ");
        while ((c = getchar()) != '\n' && i < 10) {
            str[i++] = c;
        }
        str[i] = '\0';
        printf("Você digitou: ");
        for (int j = 0; str[j] != '\0'; j++) {
            putchar(str[j]);
        }
        putchar('\n');
        return 0;
    }
  7. Escreva um programa que leia um caractere e informe seu código ASCII usando %d.
  8. ✓ Resposta:
    #include <stdio.h>
    int main() {
        char ch;
        printf("Digite um caractere: ");
        scanf(" %c", &ch);
        printf("O caractere '%c' tem código ASCII %d\n", ch, ch);
        return 0;
    }
  9. Demonstre o problema do buffer lendo um inteiro e depois um caractere sem limpar o buffer, e depois corrija.
  10. ✓ Resposta:
    // Versão com problema:
    #include <stdio.h>
    int main() {
        int num;
        char ch;
        printf("Digite um número: ");
        scanf("%d", &num);
        printf("Digite um caractere: ");
        scanf("%c", &ch); // lê o \n
        printf("Número: %d, Caractere: %d\n", num, ch);
        return 0;
    }
    
    // Correção:
    #include <stdio.h>
    int main() {
        int num;
        char ch;
        printf("Digite um número: ");
        scanf("%d", &num);
        while(getchar() != '\n'); // limpa buffer
        printf("Digite um caractere: ");
        scanf("%c", &ch);
        printf("Número: %d, Caractere: %c\n", num, ch);
        return 0;
    }

Referências