Um CPF (Cadastro de Pessoa Física) é composto de 11 números ( \mathbf{n}_{\mathbf{1}} \mathbf{n}_{\mathbf{2}} \mathbf{n}_{\mathbf{3}} . \mathbf{n}_{\mathbf{4}} \mathbf{n}_{\mathbf{5}} \mathbf{n}_{\mathbf{6}} . \mathbf{n}_{\mathbf{7}} \mathbf{n}_{\mathbf{8}} \mathbf{n}_{\mathbf{9}}-\mathbf{n}_{\mathbf{1 0}} \mathbf{n}_{\mathbf{1 1}} ), sendo que os dois últimos números ( \mathrm{n}_{10} e \mathrm{n}_{11} ) são dígitos verificadores, isto é, é realizado um conjunto de operações com os números de \mathrm{n}_{1} a \mathrm{n}_{9} para se obter os número \mathrm{n}_{10} e \mathrm{n}_{11}. Este procedimento evita que um CPF seja digitado errado, pois toda vez que alguém o insere em um sistema/programa, os números de verificação são calculados e é feita a verificação dos valores calculados com os valores \mathrm{n}_{10} e \mathrm{n}_{11} digitados. Se pelo menos um dos números for digitado errado, o cálculo de \mathrm{n}_{10} e \mathrm{n}_{11} não serão iguais aos valores digitados, então o CPF pode ser considerado inválido.
Segue o procedimento para o cálculo de \mathrm{n}_{10} e \mathrm{n}_{11} e um caso particular de número de CPF inválido.

Cálculo de \mathbf{n}_{\mathbf{1 0}} :

v_{1}=\left(n_{1} \times 10\right)+\left(n_{2} \times 9\right)+\left(n_{3} \times 8\right)+\left(n_{4} \times 7\right)+\left(n_{5} \times 6\right)+\left(n_{6} \times 5\right)+\left(n_{7} \times 4\right)+\left(n_{8} \times 3\right)+\left(n_{9} \times 2\right)
r_{1}= resto da divisão inteira de v_{1} por 11
Se \mathbf{r}_{1}<2 então \mathbf{n}_{\mathbf{1 0}}=\mathbf{0}; caso contrário \mathbf{n}_{\mathbf{1 0}}=\mathbf{1 1}-\mathbf{r}_{\mathbf{1}}

Cálculo de \mathbf{n}_{\mathbf{1 1}} :

v_{2}=\left(n_{1} \times 11\right)+\left(n_{2} \times 10\right)+\left(n_{3} \times 9\right)+\left(n_{4} \times 8\right)+\left(n_{5} \times 7\right)+\left(n_{6} \times 6\right)+\left(n_{7} \times 5\right)+\left(n_{8} \times 4\right)+\left(n_{9} \times 3\right)+\left(n_{10} \times 2\right)
\mathrm{r}_{2}= resto da divisão inteira de \mathrm{v}_{2} por 11
Se \mathbf{r}_{\mathbf{2}}<2 então \mathbf{n}_{\mathbf{1 1}}=\mathbf{0}; caso contrário \mathbf{n}_{\mathbf{1 1}}=\mathbf{1 1}-\mathbf{r}_{\mathbf{2}}

Caso particular:

Se todos os números do CPF forem iguais (exemplos: 555.555.555, 222.222.222, etc.), o CPF não é válido.
Desenvolva um programa no qual o usuário entra com os nove primeiros números do CPF e o programa retorne os dois números de verificação de CPF, conforme o algoritmo apresentado. O usuário deverá digitar os números de três em três separado-os por ponto. 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”.

Passo 1

O enunciado pede que eu desenvolva um programa que:
  • Receba do usuário os nove primeiros dígitos de um CPF, digitados em grupos de três separados por ponto (formato exemplo: 123.456.789).
  • Calcule os dois dígitos verificadores n_{10} e n_{11} seguindo o algoritmo fornecido.
  • Use apenas um único comando scanf para ler os nove dígitos (a dica é usar a máscara "%1d%1d%1d.%1d%1d%1d.%1d%1d%1d").
  • Considere o caso particular: se todos os nove dígitos forem iguais (ex.: 555.555.555) o CPF é inválido.
Informações essenciais dadas:
  • Fórmula para v_{1}:
v_{1}=\left(n_{1} \times 10\right)+\left(n_{2} \times 9\right)+\left(n_{3} \times 8\right)+\left(n_{4} \times 7\right)+\left(n_{5} \times 6\right)+\left(n_{6} \times 5\right)+\left(n_{7} \times 4\right)+\left(n_{8} \times 3\right)+\left(n_{9} \times 2\right)
  • Resto r_{1} é o resto da divisão inteira de v_{1} por 11. Se r_{1}<2 então n_{10}=0; caso contrário n_{10}=11-r_{1}.
  • Fórmula para v_{2}:
v_{2}=\left(n_{1} \times 11\right)+\left(n_{2} \times 10\right)+\left(n_{3} \times 9\right)+\left(n_{4} \times 8\right)+\left(n_{5} \times 7\right)+\left(n_{6} \times 6\right)+\left(n_{7} \times 5\right)+\left(n_{8} \times 4\right)+\left(n_{9} \times 3\right)+\left(n_{10} \times 2\right)
  • Resto r_{2} é o resto da divisão inteira de v_{2} por 11. Se r_{2}<2 então n_{11}=0; caso contrário n_{11}=11-r_{2}.
  • Caso particular: se todos os dígitos n_1 a n_9 forem iguais, o CPF é inválido.
A partir daqui vou explicar passo a passo como implementar e como entender cada operação (sem pular etapas).

Passo 2

Entendendo os conceitos matemáticos usados (bem devagar e com calma):
  • O que é o “resto da divisão inteira por 11”? É a operação matemática que chamamos de “módulo 11”. Para dois inteiros a e b positivos, o resto de a dividido por b é o número r tal que existe um inteiro q com a = b\cdot q + r e 0\le r < b. Em C isso é feito com o operador %: r = a % b.
  • Por que multiplicar por pesos (10, 9, 8, …)? É o mecanismo de verificação: cada posição tem um peso diferente para dar mais sensibilidade a erros de transposição/erro de dígito. Não precisamos provar que é bom — apenas aplicar o algoritmo.
  • Como interpretar as condições r<2? São regras específicas do CPF: se o resto é 0 ou 1, o dígito verificador vira 0; caso contrário subtrai-se o resto de 11.
Vou mostrar exatamente como calcular cada parte e como isso vira código.

Passo 3

Algoritmo passo a passo (manual, para entender antes do código):
  1. Leitura: ler os nove dígitos n_1 a n_9 com um único scanf usando a máscara "%1d%1d%1d.%1d%1d%1d.%1d%1d%1d". Cada \%1d lê um dígito (um número de 0 a 9) e os pontos na máscara consomem os pontos digitados pelo usuário. Ex.: entrada 111.444.777 preencherá os nove inteiros.
  2. Calcular v_1 somando cada dígito pelo seu peso:
v_{1}=\sum_{i=1}^{9} n_{i}\times(11-i)
(Observe que quando i=1 o peso é 10 porque 11-1=10; quando i=9 o peso é 2 porque 11-9=2.)
3) Calcular r_{1}=v_{1}\bmod 11. Em C: r1 = v1 % 11;.
4) Determinar n_{10}:
  • Se r_{1}<2 então n_{10}=0.
  • Senão n_{10}=11-r_{1}.
  1. Calcular v_2 somando os nove primeiros dígitos com pesos deslocados (começando em 11) e incluindo n_{10} com peso 2:
v_{2}=\sum_{i=1}^{9} n_{i}\times(12-i) + n_{10}\times 2
(Quando i=1 o peso é 11 porque 12-1=11; quando i=9 o peso é 3 porque 12-9=3.)
6) Calcular r_{2}=v_{2}\bmod 11.
7) Determinar n_{11}:
  • Se r_{2}<2 então n_{11}=0.
  • Senão n_{11}=11-r_{2}.
  1. Caso particular: verificar se todos os n_1 a n_9 são iguais. Em código fazemos: todos_iguais = (n1==n2 && n2==n3 && ... && n8==n9). Se todos_iguais for verdadeiro, o CPF é inválido e devemos avisar isso em vez de apenas mostrar os dígitos verificadores.
Exemplo concreto (para fixar) com os dígitos: 111.444.777 (use isto na prova para checar passos):
  • Os nove dígitos são 1,1,1,4,4,4,7,7,7.
  • Calcular v_1:
v_1 = 1\cdot10 + 1\cdot9 + 1\cdot8 + 4\cdot7 + 4\cdot6 + 4\cdot5 + 7\cdot4 + 7\cdot3 + 7\cdot2 = 160
  • Resto r_1=160 \bmod 11 = 6. Como r_1\ge2, n_{10}=11-6=5.
  • Calcular v_2:
v_2 = 1\cdot11 + 1\cdot10 + 1\cdot9 + 4\cdot8 + 4\cdot7 + 4\cdot6 + 7\cdot5 + 7\cdot4 + 7\cdot3 + 5\cdot2 = 208
  • Resto r_2=208 \bmod 11 = 10. Como r_2\ge2, n_{11}=11-10=1.
  • Resultado: dígitos verificadores são 5 e 1, ou seja -51.
  • Verificação do caso particular: os dígitos não são todos iguais, então é um CPF válido nesse sentido.

Passo 4

Dicas de implementação e cuidados práticos:
  • Use um array int d[9]; para guardar os nove dígitos lidos. Isso facilita loops.
  • Use apenas um scanf com a máscara: scanf("%1d%1d%1d.%1d%1d%1d.%1d%1d%1d", &d[0], &d[1], ..., &d[8]);
  • Para somas ponderadas (peso multiplicador), use um loop que calcula o peso a partir do índice: para v_1 o peso do índice i (0-based) é 10 - i; para v_2 é 11 - i.
  • Sempre usar inteiros (int) para somas e restos; os números envolvidos são bem pequenos (não há overflow).
  • Depois de calcular n_{10} e n_{11}, verifique se todos os dígitos lidos eram iguais: se sim, imprima mensagem de CPF inválido; se não, imprima os dois dígitos verificadores.
  • Formatação da saída: o enunciado pede que o programa retorne os dois números de verificação. Podemos imprimir numa linha os dois dígitos separados (ex.: 5 1) ou juntos (51). Vou fornecer um código que imprime os dois dígitos lado a lado com hífen, mostrando também a mensagem de CPF inválido quando for o caso.

Resposta

#include <stdio.h>

int main(void) {
    int d[9];
    /* leitura dos nove dígitos com um único scanf usando a máscara sugerida */
    if (scanf("%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]) != 9) {
        printf("Erro na leitura\n");
        return 1;
    }

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

    /* cálculo de v1 e n10 */
    int v1 = 0;
    for (int i = 0; i < 9; ++i) {
        int peso = 10 - i; /* pesos: 10,9,8,...,2 */
        v1 += d[i] * peso;
    }
    int r1 = v1 % 11;
    int n10 = (r1 < 2) ? 0 : 11 - r1;

    /* cálculo de v2 e n11 */
    int v2 = 0;
    for (int i = 0; i < 9; ++i) {
        int peso = 11 - i; /* pesos: 11,10,9,...,3 */
        v2 += d[i] * peso;
    }
    v2 += n10 * 2; /* peso 2 para n10 */
    int r2 = v2 % 11;
    int n11 = (r2 < 2) ? 0 : 11 - r2;

    /* saída: os dois dígitos verificadores */
    printf("%d%d\n", n10, n11);

    return 0;
}

Exercícios relacionados