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
scanfpara 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
, onde:
-
é o primeiro dígito (centena de milhões), -
é o nono dígito, -
é o primeiro dígito verificador, -
é o segundo dígito verificador.
Nosso objetivo: a partir de
calcular os dois dígitos verificadores esperados e comparar com
e
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):
-
Calcule a soma ponderada dos 9 primeiros dígitos com pesos decrescentes de 10 a 2:Observação: para
o peso é (pois ); para o peso é (pois ). -
Calcule o resto da divisão de
por : . -
A regra para o dígito é:
- Se
, então o dígito calculado é . - Caso contrário, o dígito calculado é
.
- Se
Em fórmula compacta:
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:
-
Calcule a soma ponderada dos 10 primeiros dígitos (Aqui para
o peso é (pois ); para o peso é (pois ). -
Resto
. -
Mesma regra:
Compare
lido e
com o
lido.]
Passo 5
Verificações práticas e casos especiais que um bom programa trata:
- Leitura: você deve usar apenas um
scanfcom a máscara sugerida. Sescanfnã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 formatoxxx.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,scanfpode falhar e retornar menos que 11. - Teste se
scanfretornou 11. Se não, informe entrada inválida. - Verifique se todos os dígitos são iguais — se sim, CPF inválido.
- Calcule
com um loop somando d[i] * (10 - i)parai = 0..8(observe o deslocamento do índice em C). - Aplique a regra do resto para obter
d10_calc. - Calcule
somando d[i] * (11 - i)parai = 0..8e adicionandod10_calc * 2(ou faça o loopi = 0..9usandod[9] = d10_calc). - Calcule
d11_calce compare comd[9]ed[10](atenção: em C índicesd[0]ad[10]correspondem aa ). - 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):
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
a
são:
.
Calcule
:
Resto:
. Como
,
— bate com o dígito verificador
3 do exemplo.Agora
(usando os 10 primeiros dígitos, incluindo o
3 calculado):Resto:
. Como
,
— 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
scanfcom 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;
}