/**************************************************
* new_credit.c *
* *
* CS50 *
* *
* Prompts the user for a credit card number, *
* *
* determines the type of the card *
* *
* (Visa, American Express, Mastercard) *
* *
* and tests its validity. *
*************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <math.h>
#define BUFFER_SIZE 256
char* get_input(void);
bool is_number(char *alleged_number);
long long int* string_to_long_long(char *string);
int count_digits(long long int number);
void credit_card_type(long long int credit_card_number, int credit_card_number_length);
bool is_credit_card_valid(long long int credit_card_number, int credit_card_number_length);
int
main(void)
{
long long int *credit_card_number = string_to_long_long(get_input());
int credit_card_number_length = count_digits(*credit_card_number);
credit_card_type(*credit_card_number, credit_card_number_length);
return 0;
}
/*
* Gets a credit card number from the user.
*/
char*
get_input(void)
{
char temp_credit_card_number[BUFFER_SIZE];
// prompt the user for a credit card number
printf("Enter a credit card number: "); // copy from standard input to temp_credit_card_number[]
while (fgets(temp_credit_card_number
, BUFFER_SIZE
, stdin
) != NULL
) { // add the trailling '\0' at the end of the string
for (int i = 0; i < BUFFER_SIZE; i++) {
if (temp_credit_card_number[i] == '\n') {
temp_credit_card_number[i] = '\0';
break;
}
}
// check user input
if ( !(is_number(temp_credit_card_number)) ) {
} else {
break;
}
}
// get_input() returns a pointer
char *value = temp_credit_card_number;
return value;
}
/*
* Checks that the user input is a number.
*/
bool
is_number(char *alleged_number)
{
long long int number;
char *invalid;
number = strtoll(alleged_number, &invalid, 10);
if (*invalid != '\0') {
return false;
}
return true;
}
/*
* Converts a string to a long long integer.
*/
long long int*
string_to_long_long(char *string)
{
char *invalid;
long long int number = strtoll(string, &invalid, 10);
long long int *value = &number;
return value;
}
/*
* Counts the number of digits of a number.
*/
int
count_digits(long long int number)
{
int i;
for (i = 0; number != 0 ; i++) {
number /= 10;
}
return i;
}
/*
* Determines the type of a credit card,
* (Visa, American Express, Mastercard)
*/
void
credit_card_type(long long int credit_card_number, int credit_card_number_length)
{
// these variables store the first or two first digits of a credit card number.
int visa_first_digit_13
= (credit_card_number
/ pow(10, 12)); int visa_first_digit_16
= (credit_card_number
/ pow(10, 15)); int amex_two_first_digits
= (credit_card_number
/ pow(10, 13)); int mastercard_two_first_digits
= (credit_card_number
/ pow(10, 14));
// determines the possible type of a card then test its validity
switch (credit_card_number_length) {
case 13:
// VISA ?
if (visa_first_digit_13 == 4) {
if (is_credit_card_valid(credit_card_number, credit_card_number_length))
} else {
}
break;
case 15:
// AMEX ?
if ((amex_two_first_digits == 34) || (amex_two_first_digits == 37)) {
if (is_credit_card_valid(credit_card_number, credit_card_number_length))
} else {
}
break;
case 16:
// VISA ?
if (visa_first_digit_16 == 4) {
if (is_credit_card_valid(credit_card_number, credit_card_number_length))
// MASTERCARD ?
} else if ((mastercard_two_first_digits == 51) ||
(mastercard_two_first_digits == 52) ||
(mastercard_two_first_digits == 53) ||
(mastercard_two_first_digits == 54) ||
(mastercard_two_first_digits == 55)
) {
if (is_credit_card_valid(credit_card_number, credit_card_number_length))
} else {
}
break;
default:
}
return;
}
/*
* Tets the syntactic validity of a credit card number,
* (Peter Luhn's algoritm).
*/
bool
is_credit_card_valid(long long int credit_card_number, int credit_card_number_length)
{
long long int every_other_digit;
int sum_products_digits = 0;
/* isolate every other digits starting with the number's second-to-last digit,
multiply it by 2, and then add those products' digits together */
for (int i = credit_card_number_length - 2; i > -1; i -= 2 ) {
every_other_digit
= ((long long int) (credit_card_number
/ pow(10, i
))) % 10; sum_products_digits += ((every_other_digit * 2) / 10) + ((every_other_digit * 2) % 10);
}
long long int left_out_digit;
int sum_left_out_digits = 0;
// isolate the digits which weren't multiplied by 2, and then add these digits together
for (int i = credit_card_number_length - 1; i > -1; i -= 2) {
left_out_digit
= ((long long int) (credit_card_number
/ pow(10, i
))) % 10; sum_left_out_digits += left_out_digit;
}
int final_sum = sum_products_digits + sum_left_out_digits;
// test weather the last digit of "final_sum" is 0 or not
if (final_sum % 10 == 0) {
return true;
} else {
return false;
}
}