Utilizando o algoritmo de verificação de CPF apresentado no exercício anterior, faça um programa no qual o usuário digita um CPF e o programa retorna ao usuário se o CPF digitado é válido. Utilize apenas um comando scanf para realizar a leitura do número do CPF. Dica: utilize a máscara de leitura “%1d%1d%1d.%1d%1d%1d.%1d%1d%1d-%1d%1d”.

Passo 1

O enunciado pede que você escreva um programa (em C) que leia um CPF digitado pelo usuário usando apenas um único comando scanf e informe se o CPF é válido ou não. O professor sugeriu a máscara de leitura "\%1d\%1d\%1d.\%1d\%1d\%1d.\%1d\%1d\%1d-\%1d\%1d" (ou, em C, "%1d%1d%1d.%1d%1d%1d.%1d%1d%1d-%1d%1d").
Informações relevantes dadas:
  • O CPF tem 11 dígitos no formato xxx.xxx.xxx-xx.
  • Deve-se usar apenas um scanf para ler os 11 dígitos (a máscara indicada faz isso).
  • O programa deve retornar se o CPF digitado é válido ou inválido.

Passo 2

Vamos entender a estrutura do CPF para saber o que checar. O CPF tem 11 dígitos:
  • Os primeiros 9 dígitos são a “base”.
  • Os últimos 2 dígitos são os dígitos verificadores (ou dígitos de controle).
Vou chamar cada dígito de \,d_1, d_2, \dots, d_{11}\,, onde:
  • \,d_1 é o primeiro dígito (centena de milhões),
  • \,d_9 é o nono dígito,
  • \,d_{10} é o primeiro dígito verificador,
  • \,d_{11} é o segundo dígito verificador.
Nosso objetivo: a partir de \,d_1\dots d_9 calcular os dois dígitos verificadores esperados e comparar com \,d_{10} e \,d_{11} fornecidos. Se baterem, o CPF é válido (exceto alguns casos especiais que tratamos a seguir).

Passo 3

Explicando o cálculo do primeiro dígito verificador de modo didático.
Regra (padrão do CPF):
  1. Calcule a soma ponderada dos 9 primeiros dígitos com pesos decrescentes de 10 a 2:
    S_1 = \sum_{i=1}^{9} d_i \times (11 - i)
    Observação: para i=1 o peso é 10 (pois 11-1=10); para i=9 o peso é 2 (pois 11-9=2).
  2. Calcule o resto da divisão de S_1 por 11: r = S_1 \bmod 11.
  3. A regra para o dígito é:
    • Se r < 2, então o dígito calculado é 0.
    • Caso contrário, o dígito calculado é 11 - r.
Em fórmula compacta:
d_{10}^{(calc)} = \begin{cases} 0, & \text{se } S_1 \bmod 11 < 2,\\[4pt] 11 - (S_1 \bmod 11), & \text{caso contrário.} \end{cases}á
Por que essa regra? É a implementação do esquema de módulo 11 usado para detectar erros comuns de digitação — não precisa decorar, basta aplicar os passos acima.]

Passo 4

Cálculo do segundo dígito verificador (seu passo é análogo, mas agora usa 10 primeiros dígitos — incluindo o dígito verificador recém-calculado).
Regra:
  1. Calcule a soma ponderada dos 10 primeiros dígitos ( d_1\) a \(d_{10}\)) com pesos decrescentes de 11 a 2: \[S_2 = \sum_{i=1}^{10} d_i \times (12 - i)
    Aqui para i=1 o peso é 11 (pois 12-1=11); para i=10 o peso é 2 (pois 12-10=2).
  2. Resto r = S_2 \bmod 11.
  3. Mesma regra:
d_{11}^{(calc)} = \begin{cases} 0, & \text{se } S_2 \bmod 11 < 2,\\[4pt] 11 - (S_2 \bmod 11), & \text{caso contrário.} \end{cases}á
Compare d_{10}^{(calc)}\] com o \(\,d_{10} lido e d_{11}^{(calc)} com o \,d_{11} lido.]

Passo 5

Verificações práticas e casos especiais que um bom programa trata:
  • Leitura: você deve usar apenas um scanf com a máscara sugerida. Se scanf não retornar 11 (número de inteiros lidos), o formato digitado está errado — trate como inválido.
  • CPFs com todos os dígitos iguais (como 000.000.000-00, 111.111.111-11, …, 999.999.999-99) são tradicionalmente considerados inválidos mesmo que o cálculo modular dê “válido”. Então detecte e rejeite quando todos os 11 dígitos forem iguais.
  • Valide os dígitos calculados conforme explicado nos passos anteriores.

Passo 6

Estratégia de implementação em C (detalhando parte a parte):
  • Declare um vetor int d[11]; para armazenar cada dígito.
  • Use uma única chamada:
    scanf("%1d%1d%1d.%1d%1d%1d.%1d%1d%1d-%1d%1d", &d[0], &d[1], …, &d[10]);
    Essa máscara lê exatamente 11 dígitos no formato xxx.xxx.xxx-xx. Os pontos e o hífen na máscara exigem que o usuário os escreva no input; se não escrever, scanf pode falhar e retornar menos que 11.
  • Teste se scanf retornou 11. Se não, informe entrada inválida.
  • Verifique se todos os dígitos são iguais — se sim, CPF inválido.
  • Calcule S_1 com um loop somando d[i] * (10 - i) para i = 0..8 (observe o deslocamento do índice em C).
  • Aplique a regra do resto para obter d10_calc.
  • Calcule S_2 somando d[i] * (11 - i) para i = 0..8 e adicionando d10_calc * 2 (ou faça o loop i = 0..9 usando d[9] = d10_calc).
  • Calcule d11_calc e compare com d[9] e d[10] (atenção: em C índices d[0] a d[10] correspondem a d_1 a d_{11}).
  • Mostre uma mensagem clara: “CPF válido” ou “CPF inválido”.

Passo 7

Exemplo numérico para internalizar o cálculo (pequena aula passo a passo):
Considere o CPF de exemplo (comum em testes): 111.444.777-35 (peguei este exemplo porque é frequentemente usado como exemplo de CPF válido).
Os dígitos d_1 a d_9 são: 1,1,1,4,4,4,7,7,7.
Calcule S_1:
\begin{aligned} S_1 &= 1\times 10 + 1\times 9 + 1\times 8 + 4\times 7 + 4\times 6 + 4\times 5 + 7\times 4 + 7\times 3 + 7\times 2 \\\ &= 10 + 9 + 8 + 28 + 24 + 20 + 28 + 21 + 14 = 162. \end{aligned}
Resto: 162 \bmod 11 = 8. Como 8 \ge 2, d_{10}^{(calc)} = 11 - 8 = 3 — bate com o dígito verificador 3 do exemplo.
Agora S_2 (usando os 10 primeiros dígitos, incluindo o 3 calculado):
\begin{aligned} S_2 &= 1\times 11 + 1\times 10 + 1\times 9 + 4\times 8 + 4\times 7 + 4\times 6 + 7\times 5 + 7\times 4 + 7\times 3 + 3\times 2 \\\ &= 11 + 10 + 9 + 32 + 28 + 24 + 35 + 28 + 21 + 6 = 204. \end{aligned}
Resto: 204 \bmod 11 = 6. Como 6 \ge 2, d_{11}^{(calc)} = 11 - 6 = 5 — bate com o 5 do exemplo. Logo 111.444.777-35 é válido.
Fazer esse tipo de conta é exatamente o que o programa fará automaticamente com loops.

Passo 8

Implementação completa (explicada): a seguir está um programa em C que:
  • usa somente um scanf com a máscara sugerida,
  • faz todas as verificações descritas,
  • imprime “CPF valido” ou “CPF invalido” (removi acento no output para evitar problemas com codificação; você pode trocar para “CPF válido”/“CPF inválido” se preferir).
Comentários no código explicam cada trecho para você entender e poder escrever parecido na prova.

Resposta

#include <stdio.h>

int main(void) {
    int d[11];
    int lidos;

    /* Leitura com apenas um scanf usando a máscara sugerida.
       O formato exige que o usuário digite exatamente xxx.xxx.xxx-xx */
    lidos = scanf("%1d%1d%1d.%1d%1d%1d.%1d%1d%1d-%1d%1d",
                  &d[0], &d[1], &d[2],
                  &d[3], &d[4], &d[5],
                  &d[6], &d[7], &d[8],
                  &d[9], &d[10]);

    if (lidos != 11) {
        printf("CPF invalido\n");
        return 0;
    }

    /* Verifica se todos os dígitos são iguais (caso especial inválido) */
    int todos_iguais = 1;
    for (int i = 1; i < 11; ++i) {
        if (d[i] != d[0]) { todos_iguais = 0; break; }
    }
    if (todos_iguais) {
        printf("CPF invalido\n");
        return 0;
    }

    /* Cálculo do primeiro dígito verificador */
    int S1 = 0;
    for (int i = 0; i < 9; ++i) {
        S1 += d[i] * (10 - i); /* pesos 10,9,...,2 */
    }
    int r1 = S1 % 11;
    int d10_calc = (r1 < 2) ? 0 : (11 - r1);

    /* Cálculo do segundo dígito verificador */
    int S2 = 0;
    for (int i = 0; i < 9; ++i) {
        S2 += d[i] * (11 - i); /* pesos 11,10,...,3 */
    }
    S2 += d10_calc * 2; /* peso 2 para o décimo dígito */
    int r2 = S2 % 11;
    int d11_calc = (r2 < 2) ? 0 : (11 - r2);

    /* Comparação com os dígitos fornecidos */
    if (d10_calc == d[9] && d11_calc == d[10]) {
        printf("CPF valido\n");
    } else {
        printf("CPF invalido\n");
    }

    return 0;
}

Exercícios relacionados