Credit
Problema a Resolver
Um cartão de crédito (ou débito), é claro, é um cartão de plástico com o qual você pode pagar bens e serviços. Impresso nesse cartão está um número que também está armazenado em um banco de dados em algum lugar, para que quando seu cartão for usado para comprar algo, o credor saiba de quem cobrar. Há muitas pessoas com cartões de crédito neste mundo, então esses números são bem longos: American Express usa números de 15 dígitos, MasterCard usa números de 16 dígitos e Visa usa números de 13 e 16 dígitos. E esses são números decimais (0 a 9), não binários, o que significa, por exemplo, que a American Express poderia imprimir até 10 ^ 15 = 1.000.000.000.000.000 de cartões exclusivos! (Isso é, hum, um quatrilhão.)
Na verdade, isso é um pouco exagerado, porque os números dos cartões de crédito têm alguma estrutura. Todos os números American Express começam com 34 ou 37; a maioria dos números MasterCard começa com 51, 52, 53, 54 ou 55 (eles também têm alguns outros números iniciais potenciais com os quais não nos preocuparemos para este problema); e todos os números Visa começam com 4. Mas os números de cartão de crédito também têm uma “soma de verificação” incorporada, uma relação matemática entre pelo menos um número e outros. Essa soma de verificação permite que computadores (ou humanos que gostam de matemática) detectem erros de digitação (por exemplo, transposições), se não números fraudulentos, sem a necessidade de consultar um banco de dados, o que pode ser lento. É claro que um matemático desonesto poderia certamente criar um número falso que, no entanto, respeitasse as restrições matemáticas, pelo que uma consulta à base de dados ainda é necessária para verificações mais rigorosas.
Em um arquivo chamado credit.c
em uma pasta chamada
credit
, implemente um programa em
C que verifica a validade de um número de cartão de crédito.
Começando
Passo a Passo
Eis aqui um passo a passo para a resolução do problema.
Cartões de crédito
Um cartão de crédito (ou débito), é claro, é um cartão de plástico com o qual você pode pagar por bens e serviços. Impresso nesse cartão está um número que também está armazenado em algum banco de dados, de forma que quando seu cartão é usado para comprar algo, o credor sabe a quem cobrar. Há muitas pessoas com cartões de crédito neste mundo, então esses números são bastante longos: a American Express usa números de 15 dígitos, a MasterCard usa números de 16 dígitos e a Visa usa números de 13 e 16 dígitos. E esses são números decimais (0 a 9), não binários, o que significa, por exemplo, que a American Express poderia imprimir até 10^15 = 1.000.000.000.000.000 cartões únicos! (Isso é, hm, um quadrilhão.)
Na verdade, isso é um pouco de exagero, porque os números de cartão de crédito têm alguma estrutura. Todos os números da American Express começam com 34 ou 37; a maioria dos números da MasterCard começa com 51, 52, 53, 54 ou 55 (eles também têm alguns outros números potenciais de início com os quais não nos preocuparemos neste problema); e todos os números da Visa começam com 4. Mas os números de cartão de crédito também possuem um "checksum", uma relação matemática entre pelo menos um número e outros. Esse checksum permite que computadores (ou pessoas que gostam de matemática) detectem erros de digitação (por exemplo, transposições), se não números fraudulentos, sem precisar consultar um banco de dados, o que pode ser lento. Claro, um matemático desonesto poderia criar um número falso que ainda respeite a restrição matemática, então uma consulta ao banco de dados ainda é necessária para verificações mais rigorosas.
Algoritmo de Luhn
Então, qual é a fórmula secreta? Bem, a maioria dos cartões usa um algoritmo inventado por Hans Peter Luhn, da IBM. De acordo com o algoritmo de Luhn, você pode determinar se um número de cartão de crédito é (sintaticamente) válido da seguinte forma:
- Multiplicar cada segundo dígito por 2, começando pelo penúltimo dígito do número, e depois adicionar os dígitos desses produtos juntos.
- Adicionar a soma à soma dos dígitos que não foram multiplicados por 2.
- Se o último dígito do total for 0 (ou, de forma mais formal, se o total módulo 10 for congruente a 0), o número é válido!
Isso é meio confuso, então vamos tentar um exemplo com o Visa do Aldo: 4003600000000014.
Detalhes de Implementação
-
Para fins de discussão, vamos primeiro sublinhar cada outro dígito, começando com o segundo dígito do número:
4003600000000014
Certo, vamos multiplicar cada um dos dígitos sublinhados por 2:
1•2 + 0•2 + 0•2 + 0•2 + 0•2 + 6•2 + 0•2 + 4•2
Isso nos dá:
2 + 0 + 0 + 0 + 0 + 12 + 0 + 8
Agora, vamos somar os dígitos desses produtos (ou seja, não os próprios produtos):
2 + 0 + 0 + 0 + 0 + 1 + 2 + 0 + 8 = 13
-
Agora vamos adicionar essa soma (13) à soma dos dígitos que não foram multiplicados por 2 (começando pelo final):
13 + 4 + 0 + 0 + 0 + 0 + 0 + 3 + 0 = 20
-
Sim, o último dígito dessa soma (20) é 0, então o cartão de David é válido!
Então, validar números de cartão de crédito não é difícil, mas pode ser um pouco tedioso manualmente. Vamos escrever um programa.
Detalhes de Implementação
No arquivo chamado credit.c
no diretório credit
, escreva um programa que solicite ao usuário um
número de cartão de crédito e, em seguida, informe (via printf
) se é um número de cartão American Express,
MasterCard ou Visa válido, conforme as definições de cada formato aqui. Para que possamos automatizar alguns
testes do seu código, pedimos que a última linha de saída do seu programa seja AMEX\n
ou MASTERCARD\n
ou VISA\n
ou INVALID\n
, nada mais, nada menos. Para simplicidade, você
pode assumir que a entrada do usuário será totalmente numérica (ou seja, sem hífens, como pode ser impresso em um
cartão real) e que não terá zeros à esquerda. Mas não assuma que a entrada do usuário se encaixará em um int
! É melhor usar o get_long
da biblioteca CS50 para obter a entrada dos
usuários. (Por quê?)
Considere o exemplo abaixo como um exemplo de como seu próprio programa deve se comportar quando receber um número de cartão de crédito válido (sem hífens).
$ ./credit
Number: 4003600000000014
VISA
Agora, o get_long
em si mesmo rejeitará hífens (e mais)
de qualquer maneira:
$ ./credit
Number: 4003-6000-0000-0014
Number: foo
Number: 4003600000000014
VISA
Mas cabe a você capturar as entradas que não são números de cartão de crédito (por exemplo, um número de telefone), mesmo que sejam numéricas:
$ ./credit
Número: 6176292929
INVALID
Teste seu programa com um monte de entradas, tanto válidas quanto inválidas. (Com certeza faremos isso!) Aqui estão alguns números de cartão que o PayPal recomenda para testes.
Se o seu programa se comportar incorretamente em algumas entradas (ou não compilar), é hora de fazer o debug!
Como Testar o Seu Código
Você também pode executar o seguinte comando para avaliar a correção do seu código usando check50
. Mas não se esqueça de compilar e testar seu código
também!
check50 cs50/problems/2024/x/credit
Execute o seguinte comando para avaliar o estilo do seu código usando style50
.
style50 credit.c
Como Enviar
No seu terminal, execute o seguinte comando para enviar o seu trabalho.
submit50 cs50/problems/2024/x/credit