CS50 pset1 Credit error in checksum calculation - c

This is my first post on here so please tell me if i made any mistakes. I tried to find an answer to my question on here but i couldn't find anything fitting.
so i have a problem in my code for the 'Credit' problem set of CS50x's week 1.
In the problemset the user has to enter a creditcard number that we have to verify as either VISA, MASTERCARD or AMEX. Otherwise the output should be INVALID.
The verification should work like this:
4 0 0 3 6 0 0 0 0 0 0 0 0 0 1 4
every second digit, starting from the second to last digit (the bold ones), is multiplied by 2 and added together.
If however the multiplied digit has 2 digits, those two digits are added seperatly like:
2 * 6 = 12 so twelve will be 1 + 2
after that you take the other half of the digits (without multiplying them) and add them together so in the end you have something like
8 + 0 + 1 + 2 + 0 + 0 + 0 + 0 + 2 = 13 (for the digits displayed in bold)
and
0 + 3 + 0 + 0 + 0 + 0 + 0 + 4 = 7 (for the other half of the digits)
You add both together to get 20 (which in the problem set is called the checksum. If the last digit of the calculated number is a 0 the card is valid and after that you just have to check some conditions to tell if its an AMEX, VISA or MASTERCARD.
Conditions for the different creditcards:
American Express = 15 Digits, starting with 34 or 37
VISA = 13 or 16 Digits, starting with 4
MasterCard = 16 Digits, starting with 51, 52, 53, 54 or 55
(Sorry for the long introduction)
I tried to make a formular for this calculation but for some reason it doesn't work for all of the numbers we get to test it. I tried a lot of things to change the calculation and the conditions at the end of my code but everytime i fix one problem, another one appears and right now it feels like i thought myself into a rabbit hole so maybe i'm just too blind to see the obvious.
We only use the libraries <stdio.h> - <cs50.h> - <math.h> so far.
long checkcredit = store;
int sum1 = 0;
int sum2;
for (int duo = 0; checkcredit > 0; duo++, checkcredit /= 10)
{
if (duo % 2 == 0)
{
sum1 += (checkcredit % 10);
}
else
{
sum2 = (checkcredit % 10) * 2;
if (sum2 >10)
{
sum2 = (checkcredit % 10) + 1;
}
}
}
sum1 +=sum2;
sum1 = sum1 % 10;
This is the part in which i think the problem is since i printed out the sum1 (the calculated verification number of the long digit) and it sometimes has the wrong output.
store is the original value of the creditcard number (for example 4003600000000014)
checkcredit is just a duplication of store to work with without changing the original store value
sum1 is for the number is displayed in bold (the once that get multiplied by 2 before adding)
sum2 is for the other half of the number
duo is a digit counter for the calculation to see if i the current digit is multiplied or not (thanks to a coworker of mine who gave the hint that i could try it that way, my old version was like 4 times longer
in the end i just add sum1 and sum2 together to get the "Checksum"
There is no compiler error whatsoever, just the Check50 output
Results for cs50/problems/2021/x/credit generated by check50 v3.2.2
:) credit.c exists
:) credit.c compiles
:( identifies 378282246310005 as AMEX
expected "AMEX\n", not "INVALID\n"
:( identifies 371449635398431 as AMEX
expected "AMEX\n", not "INVALID\n"
:( identifies 5555555555554444 as MASTERCARD
expected "MASTERCARD\n", not "INVALID\n"
:( identifies 5105105105105100 as MASTERCARD
expected "MASTERCARD\n", not "INVALID\n"
:( identifies 4111111111111111 as VISA
expected "VISA\n", not "INVALID\n"
:( identifies 4012888888881881 as VISA
expected "VISA\n", not "INVALID\n"
:) identifies 4222222222222 as VISA
:) identifies 1234567890 as INVALID
:) identifies 369421438430814 as INVALID
:) identifies 4062901840 as INVALID
:) identifies 5673598276138003 as INVALID
:) identifies 4111111111111113 as INVALID
:) identifies 4222222222223 as INVALID
like i said i think that the error i made is in this part of the code (i even think it has something to do with the condition in the for loop) but i can't figure out what is wrong there.
Just in case the whole code is here:
#include<cs50.h>
#include<stdio.h>
#include<math.h>
int main(void)
{
//Ask user for credit card number
long store;
do
{
store = get_long("Number: ");
}
while (store < 0);
//calculating the amount of digits
long cnumber = store;
int digits;
for (digits = 0 ; cnumber > 0 ; digits++)
{
cnumber/=10;
}
//calculating the checksum
long checkcredit = store;
int sum1 = 0;
int sum2;
for (int duo = 0; checkcredit > 0; duo++, checkcredit /= 10)
{
if (duo % 2 == 0)
{
sum1 += (checkcredit % 10);
}
else
{
sum2 = (checkcredit % 10) * 2;
if (sum2 >10)
{
sum2 = (checkcredit % 10) + 1;
}
//sum1 += sum2;
}
}
sum1 +=sum2;
//printf("%i ", sum1);
sum1 = sum1 % 10;
//conditions for varification of the card
if (sum1 == 0)
{
if (digits != 13 && digits != 15 && digits != 16)
{
printf("INVALID\n");
}
else if (digits == 16 || digits == 13)
{
if (digits == 16 && (store >= 51e14 && store <56e14))
{
printf("MASTERCARD\n");
}
else if ((digits == 13 || digits == 16) && ((store <= 4e13 && store < 5e13)||(store >= 4e15 && store < 5e15)))
{
printf("VISA\n");
}
else
{
printf("INVALID\n");
}
}
else if (digits == 15)
{
if((store >= 34e13 && store < 35e13)||(store >= 37e13 && store < 38e13))
{
printf("AMEX\n");
}
else
{
printf("INVALID\n");
}
}
}
else
{
printf("INVALID\n");
}
}
Please ignore the conditions part at the end, i just prototyped it together to check if it works (which it does if i ignore the checksum condition)
I'm sorry for the long post and i am really thankful for everyone who takes the time to look over this and help a beginner to learn from his mistakes.
-Wannabree

The handling of sum2 is wrong in that it does not sum up something, but overwrites sum2 each time. A possible remedy is to initialize int sum2 = 0; and change
{
sum2 = (checkcredit % 10) * 2;
if (sum2 >10)
{
sum2 = (checkcredit % 10) + 1;
}
}
to
sum2 += "\0\2\4\6\x8\1\3\5\7\x9"[checkcredit % 10];

Related

Attempting to run Luhn's Algorithm in C

So, I'm trying to make Luhn's algorithm in C, but it doesn't return the correct values when running it.
//Luhn's Algorithm
int tsum = 0;
if (count % 2 != 0)
{
for (int tempcount = count; tempcount > 0; tempcount--)
{
if (tempcount % 2 != 0)
{
tsum += (cardNum % 10);
}
else
{
tsum += (cardNum % 10)*2;
}
cardNum /= 10;
}
}
else
if (count % 2 == 0)
{
for (int tempcount = count; tempcount > 0; tempcount--)
{
if (tempcount % 2 == 0)
{
tsum += (cardNum % 10);
}
else
{
tsum += (cardNum % 10)*2;
}
cardNum /= 10;
}
}
tsum %= 10;
I have spent hours trying to troubleshoot and find the issue, count represents the number of digits in the card number, the rest define themselves.
I would appreciate somebody to tell me what I'm doing wrong, thank you.
EDIT: Apologies, cardNum is a long long. And I am expecitng a value of 0 for tsum when inputting any card number from Paypal's Standard Test Cards. I would also like to add, in my mind what this code should do is: using the checks for even and odd it will start from the rightmost digit and add it to tsum, every other digit will do the same. Then starting from the 2nd rightmost digit, the digit is multiplied by 2 then added to tsum, with every other digit doing the same. Then, the last line will check the rightmost digit of the current tsum and will tell me if the card is valid according to Luhn's Algorithm.
Here is what I usually do if I "try to implement" something I am not sure about: I use an interactive language, such as Common Lisp, tinker and test interactively until it works. Then, I usually have some good template I can use to write it in a less powerful language such as C.
(defun luhn-method (n)
(mod
(loop
for x = n then (floor x 10)
while (> x 0)
for double = nil then (not double)
for digit = (mod x 10)
for factor = (if double 2 1)
for y = (let ((a (* digit factor)))
(if (> a 9) (- a 9) a))
do (format t "~%~a" (list :x x :double double :digit digit :factor factor :y y))
summing y)
10))
I did this just from reading the wikipedia page about Luhn method (the german wiki page is easier to understand because it shows a simple exampple, while being less verbose than the english version).
From your Paypal site, the first number produces
(luhn-method 378282246310005)
(X 378282246310005 DOUBLE NIL DIGIT 5 FACTOR 1 Y 5)
(X 37828224631000 DOUBLE T DIGIT 0 FACTOR 2 Y 0)
(X 3782822463100 DOUBLE NIL DIGIT 0 FACTOR 1 Y 0)
(X 378282246310 DOUBLE T DIGIT 0 FACTOR 2 Y 0)
(X 37828224631 DOUBLE NIL DIGIT 1 FACTOR 1 Y 1)
(X 3782822463 DOUBLE T DIGIT 3 FACTOR 2 Y 6)
(X 378282246 DOUBLE NIL DIGIT 6 FACTOR 1 Y 6)
(X 37828224 DOUBLE T DIGIT 4 FACTOR 2 Y 8)
(X 3782822 DOUBLE NIL DIGIT 2 FACTOR 1 Y 2)
(X 378282 DOUBLE T DIGIT 2 FACTOR 2 Y 4)
(X 37828 DOUBLE NIL DIGIT 8 FACTOR 1 Y 8)
(X 3782 DOUBLE T DIGIT 2 FACTOR 2 Y 4)
(X 378 DOUBLE NIL DIGIT 8 FACTOR 1 Y 8)
(X 37 DOUBLE T DIGIT 7 FACTOR 2 Y 5)
(X 3 DOUBLE NIL DIGIT 3 FACTOR 1 Y 3)
0
making it easy to see every single step of the algorithm and convincing yourself it is correct.
To port this to C, first we need to explore, if C has an integer type wide enough for those credit card numbers (lisp has large integers by default - one thing less to worry about in our prototype). Lisp again:
(log 378282246310005 2)
48.426456
So, we need a 64 bit variable and should be good.
Since integers in C are implementation/platform/system specific, we should use some header file, giving us the correct type:
#include <stdint.h>
In there, the 64 bit unsigned integer is defined as uint64_t and if your compiler and your header files are correct for your system, using that makes sure, you do not get it wrong. The native "unsigned long long" etc. are just guesswork and not portable.
With that in place, we can simply port the code above to C:
uint64_t luhn(uint64_t n) {
uint64_t x = n;
uint64_t sum = 0;
uint64_t factor = 1;
while (x > 0) {
uint64_t y = (x % 10) * factor;
if (y > 9)
y = y - 9;
sum += y;
x = x / 10;
if (1 == factor) {
factor = 2;
} else {
factor = 1;
}
}
return sum % 10;
}
Summary:
A proper tool set helps getting stuff done. If you don't know yet, how to use a C debugger and step through code line by line while watching the content of variables, an interactive programming language is probably easier for you for prototyping.
Thank you for your help, I was able to solve this issue as it seems I had missed a step in Luhn's Algorithm.
//Luhn's Algorithm
int tsum = 0;
int luhn;
if (count % 2 != 0)
{
for (int tempcount = count; tempcount > 0; tempcount--)
{
if (tempcount % 2 != 0)
{
luhn = (cardNum % 10);
tsum += luhn;
}
else
{
luhn = (cardNum % 10) * 2;
if (luhn > 9)
{
tsum += (luhn - 9);
}
else
{
tsum += luhn;
}
}
cardNum /= 10;
}
}
else if (count % 2 == 0)
{
for (int tempcount = count; tempcount > 0; tempcount--)
{
if (tempcount % 2 == 0)
{
luhn = (cardNum % 10);
tsum += luhn;
}
else
{
luhn = (cardNum % 10) * 2;
if (luhn > 9)
{
tsum += (luhn - 9);
}
else
{
tsum += luhn;
}
}
cardNum /= 10;
}
}
tsum %= 10;
Here, I defined luhn as the next integer to be added to the tsum, in doing this I was able to fill in the missing step by subtracting 9 before adding to tsum if luhn exceeded 9.

CS50 pset 1 credit (long divided by a number)

I am currently trying my best to solve the question. However, I have encountered the following problem:
After checking the sum, I want to verify the first 2 digits from the card no.
so I use the following method:
int main(void)
{
long long ccn;
do
{
ccn = get_long_long("Credit Card No.:\n");
}
while (ccn < 0);
int ccn_len;
long long count = ccn;
long long bccn = ccn;
for (ccn_len = 0; count != 0; ccn_len++, count /= 10);
int sum = 0; //checksum
for (int i = 0; i < ccn_len; ccn /= 10, i++)
{
if (i % 2 == 0)
{
sum += ccn % 10;
}
else
{
int digit = (ccn % 10) * 2;
sum += digit / 10 + digit % 10;
}
}
if (sum % 10 != 0)
{
printf("INVALID");
}
else
{
int a = bccn / 1e13;
if ((bccn / 1e13 == 34 || bccn / 1e13 == 37) && ccn_len == 15)
{
printf("AMERICAN EXPRESS");
}
else if (bccn / 1e12 == 4 && ccn_len == 13)
{
printf("VISA");
}
else if (ccn_len == 16)
{
if (bccn / 1e15 == 4)
{
printf("VISA");
}
if (bccn / 1e14 > 50 || bccn / 1e14 < 56)
{
printf("MASTERCARD");
}
}
else
{
printf("INVALID");
}
}
}
}
Let's say it is a valid AE card: 378282246310005 with a length of 15 digits
In the above code, I use ccn / 1e13 to get the first two digits to check whether it is 34 or 37.
However, after satisfying the checksum, the output still shows INVALID.
I try to use another method,
I set a variable a
and a = ccn / 1e13
and then I put a in the if-statement:
if ((a == 34 || a == 37) || ccn_len == 15)
everything works fine this time.
Can anyone tell me what is going wrong with my code? Or how do I write better?
Your replies are very much appreciated.
1e13 is a floating-point constant with type double. In bccn / 1e13, bccn is converted to double, and then floating-point division is performed, yielding a number such as 37.82822463100050214279690408147871494293212890625. Then bccn / 1e13 == 37 evaluates as false because 37.82822463100050214279690408147871494293212890625 is not equal to 37.
Rewrite your code to use only integer arithmetic (do not use floating-point constants like 1e13) or to treat credit card “numbers” as strings of digits rather than as integers.

What is wrong with my code for CS50 credit problem?

Why is my code wrong?? I don't know why... This problem is to get a card number from the user and tell whether it is a valid card number or an invalid card number. It could either be an American Express card, MasterCard, or a Visa. American Express card has 15 digits and must either start with 34 or 36, while MasterCard has 16 digits and can start with 51, 52, 53, 54, 55. The Visa card must either have 13 or 16 digits, and must start with a 4. This problem also uses the Luhn's algorithm wherein to check if a card number is valid every other number starting from the tens place multiplied by two, then if added the digits no their product but their digits, so if you multiply 8 by 2 its 16 so you must add 1 + 6 and the other numbers. Then once you got the sum you must add them to the ones you didn't multiply by 2, then lastly if their sum is divisible by 10 then it is valid. I really don't know where I went wrong I've been looking at my code for almost 3 hours. Also noob programmer here..
#include<stdio.h>
int main(void)
{
//declare and initialize card number
long long number = 0;
//ask user for their credit card number
do
{
printf("Number: ");
scanf("%lli", &number);
}
while (number < 0);
//declare and initialize a counter for the number of the digits
int counter = 0;
long long temp = number;
//loop to count the number of digits
while (temp > 0)
{
temp /= 10;
counter++;
}
//statement for invalid digits
if (counter != 13 && counter != 15 && counter != 16)
{
printf("Invalid number of digits\n");
}
//array to store the digits individually
int digits[counter];
// loop to store the digits in the array
for (int i = 0; i < counter; i++)
{
digits[i] = number % 10;
number /= 10;
}
//loop to multiply every other digit by 2
for (int j = 1; j < counter; j += 2)
{
digits[j] *= 2;
}
// loop to separate then add digits that are greater than 10
for (int x = 1; x < counter; x += 2)
{
if (digits[x] > 10)
{
int s = digits[x] % 10;
digits[x] /= 10;
digits[x] = (digits[x] % 10) + s;
}
}
int sum = 0;
//loop to get the sum of all numbers
for (int y = 0; y < counter; y++)
{
sum += digits[y];
}
sum %= 10;
switch (sum)
{
case '0':
if (counter == 15 && (digits[14] == 3 && (digits[13] == 4 || digits[13] == 7)))
{
printf("American Express\n");
}
else if (counter == 16 && digits[15] == 5)
{
printf("Master Card\n");
}
else if (counter == 13 && digits [12] == 4)
{
printf("Visa\n");
}
else if (counter == 16 && digits[15] == 4)
{
printf("Visa\n");
}
break;
default:
printf("Invalid\n");
break;
}
}
There are three errors, and I'm ashamed that it took myself so long to spot especially the second one.
if (digits[x] > 10) is a kind of off-by-one error. Rather than greater than 10, the Description of the Luhn algorithm says: If the result of this doubling operation is greater than 9 …, so this has to be if (digits[x] > 9).
case '0': must rather be case 0:, since sum is an integer, not a character representation.
if (counter == 15 && (digits[14] == 3 && (digits[13] == 4 || digits[13] == 7))) fails because the digits have been modified by the algorithm in-place, so the 7 has become a 5. We could write if (counter == 15 && (digits[14] == 3 && (digits[13] == 4 || digits[13] == 7*2-9))) instead; same for else if (counter == 16 && digits[15] == 5).

Excecuting Luhn's Algorithm in C - buggy code

I'm currently working through CS50x's 2018 programme and I'm completing the 'credit' part of pset1. We're supposed to be executing Luhn's algorithm, but I can't get it to work.
Luhn's algorithm is an algorithm that uses checksum to determine whether or not a credit card is valid. The input should be a credit card number, or something that could be a credit card number. It then takes the number, multiplies every other digit by 2 (or every even digit as implied in my code), sums them, then takes the remaining digits (the odd ones) and sums them with the first sum. The algorithm then states that if the last digit of the summed value is 0 then the number is valid (or if it divides by ten perfectly). If the answer isn't 0 then it should print "INVALID" to the user. If it is 0 the code should then analyse whether or not the number could be a valid card. We are supposed to use American Express, Visa and MasterCard as our potential cards. If it's AMEX it will be 15 digits and start with 34 or 37, MASTERCARD is 16 digits and starts with 51, 52, 53, 54 or 55, and VISA is either 13 or 16 digits and starts with 4. The expected output is either one of the card companies or "INVALID" if the number doesn't fit that criteria.
Instead of this, my code simply runs until overflow after a number is submitted. I know my logic must be flawed somewhere, but I have no idea where I've gone wrong. My code is as follows:
//Checks credit card no. to see if valid
#include <cs50.h>
#include <stdio.h>
#include <math.h>
int main(void)
{
//Get card no. from user
long long n;
do
{
n = get_long_long("Card Number: ");
}
while (n < 0);
//Define variables for checksum process
int odd = 0;
int even = 0;
long long temp_n = n;
int sum_a = 0;
int sum_b = 0;
int counter = 0;
//Execute checksum until all of n assessed
while (temp_n >= 0)
{
//Take final digit, add up, then update temp no., increase digit counter by 1
odd = temp_n % 10;
sum_b = sum_b + odd;
temp_n = (temp_n - odd) / 10;
counter++;
//Take final digit (which is an even digit of n), multiply by 2 and add up, update temp no., increase counter by 1
even = temp_n % 10;
sum_a = sum_a + 2 * even;
temp_n = (temp_n - even) / 10;
counter++;
}
//Validate checksum
int test = (sum_a + sum_b) % 10;
//Return results
if (test == 0)
{
if (counter == 16 && odd == 5 && (even == 1 || even == 2 || even == 3 || even == 4 || even == 5))
{
printf("MASTERCARD\n");
}
else if ((counter == 16 || counter == 13) && odd == 4)
{
printf("VISA\n");
}
else if (counter == 15 && odd == 3 && (even == 4 || even == 7))
{
printf("AMEX\n");
}
else
{
printf("INVALID\n");
}
}
else
{
printf("INVALID\n");
}
}
I would appreciate any help I can get about where I've gone wrong. Thank you in advance.
while (temp_n >= 0)
{
//Take final digit, add up, then update temp no., increase digit counter by 1
odd = temp_n % 10;
sum_b = sum_b + odd;
temp_n = (temp_n - odd) / 10;
counter++;
//Take final digit (which is an even digit of n), multiply by 2 and add up, update temp no., increase counter by 1
even = temp_n % 10;
sum_a = sum_a + 2 * even;
temp_n = (temp_n - even) / 10;
counter++;
}
This assumes that input will always have even number of digits. Take a bool flag = true; and change it to:
while (temp_n >= 0)
{
//Take final digit, add up, then update temp no., increase digit counter by 1
if(flag){
odd = temp_n % 10;
sum_b = sum_b + odd;
temp_n = (temp_n - odd) / 10;
counter++;
flag = !flag;}
//Take final digit (which is an even digit of n), multiply by 2 and add up, update temp no., increase counter by 1
else{
even = temp_n % 10;
sum_a = sum_a + 2 * even;
temp_n = (temp_n - even) / 10;
counter++;
flag = !flag;}
}

Write a program in C to apply Luhn's algorithm for credit card validation

I need my program to prompt a user for an input and re-prompt in case the input doesn't follow a credit card format (ex: negative numbers or letters, etc.) and then apply the algorithm to see if the number is a valid credit card number and if yes, whether it's Visa, MasterCard or AmEx.
I know that this question has been answered with different codes on this website, I swear I read everything that I could possibly find (on this site and elsewhere on the net) but I'm having a really hard time understanding the C syntax and I wanted to try to come up with something myself instead of copying bits of codes I don't understand from other answers. If someone can help me out and look at what I've done so far and tell me what I'm doing wrong I would be really grateful. Also, any tips that could help me make sense of the C syntax logic better would be extremely appreciated.
My program is compiling but when I run it it's acting up in a very weird way: when I enter an input sometimes it will say that it is invalid (even if it's a valid number) and sometimes it will just not return anything after I press enter and won't stop running no matter how many times I press the return key.
Here is my code so far:
#include <stdio.h>
#include <cs50.h>
#include <math.h>
int main(void)
{
printf("Please give me your credit card number:\n") ;
long long card_num ;
do
{
card_num = GetLongLong() ;
}
while (card_num < 1 || card_num > 9999999999999999) ;
// Make a copy of the card number to be used and modified throughout the process.
long long temp_num = card_num ;
int digit = 0 ;
int count = 0 ;
int sum_a = 0 ;
int sum_b = 0 ;
// Isolate every digit from the credit card number using a loop and the variable 'digit'.
// Keep track of the amount and position of each digit using variable 'count'.
while (card_num >= 0)
{
digit = card_num % 10 ;
count++ ;
temp_num = (card_num - digit) / 10 ;
break ;
// Apply Luhn's algorithm using two different 'for' loops depending on the position of each digit.
for (count = 0 ; count % 2 == 0 ; count++)
{
sum_a = sum_a + ((card_num % 10) * 2) ;
while ((card_num % 10) * 2 >= 10)
{
sum_a = (sum_a % 10) + 1 ;
}
}
for (count = 0 ; count % 2 != 0 ; count++)
{
sum_b = sum_b + digit ;
}
return sum_a ;
return sum_b ;
return count ;
}
// Checking the validity of the number according to Luhn's algorithm
int total_sum = sum_a + sum_b ;
if (total_sum % 10 != 0)
{
printf("This is an invalid number.\n") ;
}
// If the number entered doesn't have the right amount of digits according
// to variable 'count', declare the number as invalid.
if (count != 13 || count != 15 || count != 16)
{
printf("This is an invalid number.\n") ;
}
// Reset value of variable 'temp_num' and apply calculations that will isolate the first two digits.
// Store the results in a variable 'company_id'.
temp_num = card_num ;
int company_id ;
while (temp_num > 100)
{
temp_num = card_num - (card_num % 10) ;
company_id = temp_num / 10 ;
}
return company_id ;
// Print the type of credit card depending on the company ID and amount of digits.
if (company_id > 50 && company_id < 56 && count == 16)
{
printf("MASTERCARD\n") ;
}
else if ((company_id == 4) && (count == 13 || count == 16))
{
printf("VISA\n") ;
}
else if ((company_id == 34 || company_id == 37) && (count == 15))
{
printf("AMEX\n") ;
}
else
{
printf("This is an invalid number.\n") ;
}
return 0 ;
}
Your answer is a out of order pastiche with sections that don't follow logically from the previous.
Specific issues:
This logic:
if (count != 13 || count != 15 || count != 16)
invalidates every card, the ors (||) should be ands (&&) for this to work.
This loop makes no sense:
while (card_num >= 0)
{
digit = card_num % 10 ;
count++ ;
temp_num = (card_num - digit) / 10 ;
break ;
...
}
The break is unconditional so it exits the loop and ignores the next twenty lines.
You appear to have spliced in subroutines from elsewhere as you call return five times, only the last of which is valid:
return sum_a ;
return sum_b ;
return count ;
return company_id ;
return 0 ;
In several places you use card_num when you should be using temp_num.
You fail to exit the program once you know the card is invalid -- instead you just keep on testing. You fail to acknowledge when a card is valid.
You count the number of digits in the card number but wait until after you run other checks before testing if that digit count was valid or not.
What follows is my rework of your code to address the above and some style issues:
#include <stdio.h>
#include <cs50.h>
#include <math.h>
int main(void)
{
printf("Please give me your credit card number: ") ;
long long card_num = 0LL;
while (card_num < 1LL || card_num > 9999999999999999LL)
{
card_num = GetLongLong();
}
// Make a copy of the card number to be used and modified throughout the process.
long long temp_num = card_num;
// Isolate every digit from the credit card number using a loop and the variable 'digit'.
// Keep track of the amount and position of each digit using variable 'count'.
int count = 0;
while (temp_num > 0LL)
{
temp_num = temp_num / 10LL;
count++;
}
// If the number entered doesn't have the right amount of digits according
// to variable 'count', declare the number as invalid.
if (count != 13 && count != 15 && count != 16)
{
printf("This is an invalid number (# of digits).\n");
return 1;
}
// Reset value of variable 'temp_num' and apply calculations that will isolate the first two digits.
// Store the results in a variable 'company_id'.
temp_num = card_num;
while (temp_num > 100LL)
{
temp_num = temp_num / 10LL;
}
int company_id = temp_num;
// Print the type of credit card depending on the company ID and amount of digits.
if (company_id > 50 && company_id < 56 && count == 16)
{
printf("MASTERCARD\n") ;
}
else if ((company_id == 34 || company_id == 37) && (count == 15))
{
printf("AMEX\n") ;
}
else if ((company_id / 10 == 4) && (count == 13 || count == 16 || count == 19))
{
printf("VISA\n") ;
}
else
{
printf("This card was issued by an unknown company.\n");
}
// Apply Luhn's algorithm.
int sum = 0;
temp_num = card_num;
for (int i = 1; i <= count; i++)
{
int digit = temp_num % 10LL;
if (i % 2 == 0)
{
digit *= 2;
if (digit > 9)
{
digit -= 9;
}
}
sum += digit;
temp_num /= 10LL;
}
// Checking the validity of the number according to Luhn's algorithm
if (sum % 10 != 0)
{
printf("This is an invalid number (Luhn's algorithm).\n");
return 1;
}
printf("This is a valid number.\n");
return 0;
}
This is not a finished program -- there's error checking and other details needed. Rather than summing the digits when a doubled card number is greater than 9, I used the simpler approach of subtracting 9.
Here my solution, this method received the var long credit card number, I hope to be helpful.
void check_card(long n)
{
long temp_n = n;
int count = 2;
while(temp_n > 100)
{
temp_n = temp_n / 10;
count ++;
}
long temp_n2 = n;
int sum = 0;
for (int i = 1; i <= count; i++)
{
int digit = temp_n2 % 10;
if (i%2 == 0)
{
if (digit * 2 > 9)
{
sum += (digit * 2) - 9;
}
else
{
sum += digit * 2;
}
}
else
{
sum += digit;
}
temp_n2 /= 10;
}
bool flag = (sum % 10 == 0) ? true : false;
if (count == 15 && (temp_n == 34 || temp_n == 37) && flag)
{
printf("AMEX\n");
}
else if(count == 16 && (temp_n > 50 && temp_n < 56) && flag)
{
printf("MASTERCARD\n");
}
else if((count == 13 || count == 16) && (temp_n / 10 ==4) && flag)
{
printf("VISA\n");
}
else
{
printf("INVALID\n");
}

Resources