Several weeks ago, I started to do the CS50 course on EdX to learn a little bit about Computer Science then I started to code in C, so if the program that follows is not really well made, that’s normal.
So basically, when I try to run my program, I get the error message : Floating point exception (core dumped). By looking on the Internet, I understood that it means that there is some expression dividing value by zero in my program, but I cannot figure out where the error comes from. So, please help. And thank you very much in advance for your response.
#include <cs50.h>
#include <stdio.h>
int main(void)
{
//Prompt for input
long cardNum = get_long("Enter your card number : ");
//Calculate the checksum
int totalneedx2 = 0;
int total;
int needx2;
for (int n = 100; n < cardNum; n = n * 100)
{
needx2 = cardNum % n / n * 10;
if (needx2 >= 5)
{
int unit;
needx2 = needx2 * 2;
unit = needx2 % 10;
needx2 = needx2 / 10;
total = needx2 + unit;
}
else if (needx2 < 5)
{
needx2 = needx2 * 2;
total = needx2;
}
totalneedx2 = total + totalneedx2;
needx2 = 0;
}
int nox2;
int totalnox2 = 0;
for (int n = 10; n < cardNum; n = n * 100)
{
nox2 = cardNum % n / n * 10;
totalnox2 = totalnox2 + nox2;
nox2 = 0;
}
int totalChecksum = totalnox2 + totalneedx2;
if (totalChecksum % 10 == 0)
{
if (cardNum >= 1000000000000)
{
if (cardNum / 1000000000000 == 4)
{
printf("VISA\n");
}
else
{
printf("INVALID\n");
}
}
else if (cardNum >= 100000000000000)
{
if (cardNum / 10000000000000 == 34 || cardNum / 10000000000000 == 37)
{
printf("AMEX/n");
}
else
{
printf("INVALID\n");
}
}
else if (cardNum >= 1000000000000000)
{
if (cardNum / 100000000000000 == 51 || cardNum / 100000000000000 == 52 || cardNum / 100000000000000 == 53 || cardNum / 100000000000000 == 54 || cardNum / 100000000000000 == 55)
{
printf ("MASTERCARD\n");
}
else if (cardNum / 1000000000000000 == 4)
{
printf ("VISA\n");
}
else
{
printf("INVALID\n");
}
}
}
else
{
printf("INVALID\n");
}
}
Task: the user enters the card number and needs to determine whether the card is valid and, if so, determine the type of card (Visa, MasterCard, American Express). We have [https://cs50.harvard.edu/college/2021/spring/psets/1/credit/#luhns-algorithm][Luhn's Algorithm] to determine the validation of card number.
Problem: sometimes programm identifies invalid card as Visa(for example: 4111111111111113, 4222222222223). I really don't know how to solve this problem( I've already seen other solutions of this CS50 Credit task, but since I'm a beginner, I want to know what's wrong exactly with this code. I would be grateful for any hints on this problem and the code as a whole. Appreciate your help!
#include <cs50.h>
#include <stdio.h>
#include <math.h>
int main(void)
{
long credit;
do
{
credit = get_long("Number of card:\n");
}
while (credit < 0);
long number = credit;
int digits;
for (digits = 0; number > 0; digits++)
{
number /= 10;
}
int checksum = 0;
int i;
for (i = 0; number > 0; i++, number /= 10)
{
if (i % 2 == 0)
{
checksum += (number % 10);
}
else
{
int n = (number % 10) * 2;
if (n > 9)
{
n = (n / 10) + (n % 10);
}
checksum += n;
}
}
checksum = checksum % 10;
if ((checksum == 0) && ((credit >= 34e13 && credit < 35e13) || (credit >= 37e13 && credit < 38e13)))
{
printf("AMEX\n");
}
else if ((checksum == 0) && (credit >= 51e14 && credit < 56e14))
{
printf("MASTERCARD\n");
}
else if ((checksum == 0) && ((credit >= 4e12 && credit < 5e12) || (credit >= 4e15 && credit < 5e15)))
{
printf("VISA\n");
}
else
{
printf("INVALID\n");
}
}
Code changes number
for (digits = 0; number > 0; digits++) {
number /= 10;
}
int checksum = 0;
int i;
Consider the value of number after the above loop. Certainly 0. Next loop does not iterate.
for (i = 0; number > 0; i++, number /= 10)
Code needs to preserve number.
I am really stuck here. The programm gives right answer to invald credit card numbers but never say if its VISA, AMEX or MASTERCARD.
I need to post the complete code because I do not have so much experience wit the C language.
The checksum part in the end could also have been "bool" but I always got error messages with that.
#include <cs50.h>
#include <stdio.h>
int main(void)
{
long long card;
int checksum = 0;
do
{
card = get_long_long("Number: ");
}while (card <= 0);
int count = 0;
while (card != 0) {
card /= 10; // n = n/10
++count;
}
if(count != 16 && count != 13 && count != 15){
printf("INVALID\n");
}
else if(checksum != 0){
printf("INVALID\n");
}
else if(card >= 34e13 || card >= 37e13){
printf("AMEX\n");
}
else if(card >= 51e14 || card >= 52e14 || card >= 53e14 || card >= 54e14 || card >= 55e15) {
printf("MASTERCARD\n");
}
else if(card >= 4e15 || card >=4e12) {
printf("VISA\n");
}
else {
printf("INVALID\n");
}
}
int checksum(long long card_nr)
{
int sum = 0;
for (int i=0;card_nr !=0; i++, card_nr/=10 )
{
if(i % 2 == 0)
sum += card_nr % 10;
else
{
int digit = 2 * (card_nr % 10);
sum += digit / 10 + digit % 10;
}
}
return (sum % 10) == 0;
}
There may be major issue or only some parenthesis, the programm is compiling. Thanks for any help.
There are many errors with the logic:
#include <cs50.h>
#include <stdio.h>
int main(void)
{
long long card;
int checksum = 0;
do
{
card = get_long_long("Number: ");
}while (card <= 0);
int count = 0;
// ** In here you destroy card, so later card whill allways be 0
while (card != 0) {
card /= 10; // n = n/10
++count;
}
if(count != 16 && count != 13 && count != 15){
printf("INVALID\n");
}
else if(checksum != 0){
printf("INVALID\n");
}
//** here it is the same as if(card >= 34e13)
else if(card >= 34e13 || card >= 37e13){
printf("AMEX\n");
}
//** here it is the same as if(card >= 51e14)
//** also these values are already covered by last check
else if(card >= 51e14 || card >= 52e14 || card >= 53e14 || card >= 54e14 || card >= 55e15) {
printf("MASTERCARD\n");
}
//** here it is the same as if(card >= 4e15)
//** also these values are already covered by previous check
else if(card >= 4e15 || card >=4e12) {
printf("VISA\n");
}
else {
printf("INVALID\n");
}
}
int checksum(long long card_nr)
{
int sum = 0;
for (int i=0;card_nr !=0; i++, card_nr/=10 )
{
if(i % 2 == 0)
sum += card_nr % 10;
else
{
int digit = 2 * (card_nr % 10);
sum += digit / 10 + digit % 10;
}
}
return (sum % 10) == 0;
}```
After loop:
while (card != 0) {
card /= 10; // n = n/10
++count;
}
card = 0 and original card number is lost.
You can save original card number to another variable and then compare it.
Also it is better to use integer constants like 54LL << 14 instead of float 54e14
When I enter a credit card number that should work it outputs "INVALID" when it should output the credit card brand. I believe something is going wrong in the validity function but i can't seem to figure out what. I've spent a couple hours trying to fix the problem but nothing has worked. It would be great if I could get some help, thanks so much!
This is my code:
#include <stdio.h>
#include <cs50.h>
bool validity(long long creditNum);
int find_length(long long n);
bool checksum(long long ccn);
void credit_card_num(long long ccn);
int main(void)
{
long long creditNum;
do
{
creditNum = get_long_long("Enter Card Number: ");
}
while(creditNum < 0);
if (validity(creditNum) == true)
credit_card_num(creditNum);
else
printf("INVALID\n");
}
bool validity(long long creditNum)
{
int length = find_length(creditNum);
if ((length == 13 || length == 15 || length == 16) && checksum(creditNum))
return true;
else
return false;
}
int find_length(long long n)
{
int length;
for (length = 0; n != 0; n/= 10)
length++;
return length;
}
bool checksum(long long ccn)
{
int sum = 0;
int digit;
for (int i = 0; ccn != 0; i++, ccn /= 10)
{
if (i % 2 == 0)
sum += ccn % 10;
else
digit = 2 * (ccn % 10);
sum += digit / 10 + digit % 10;
}
if ((sum % 10) == 0)
return true;
else
return false;
}
void credit_card_num(long long ccn)
{
if ((ccn >= 34e13 && ccn < 35e13) || (ccn >= 37e13 && ccn < 38e13))
printf("AMEX\n");
else if (ccn >= 51e14 && ccn < 56e14)
printf("MASTERCARD\n");
else if ((ccn >= 4e12 && ccn < 5e12) || (ccn >= 4e15 && ccn < 5e15))
printf("VISA\n");
else
printf("INVALID\n");
}
It looks like your error is in your checksum function; specifically, the for loop.
for (int i = 0; ccn != 0; i++, ccn /= 10)
{
if (i % 2 == 0)
sum += ccn % 10;
else
digit = 2 * (ccn % 10);
sum += digit / 10 + digit % 10;
}
should be
for (int i = 0; ccn != 0; i++, ccn /= 10)
{
if (i % 2 == 0){
sum += ccn % 10;
} else {
digit = 2 * (ccn % 10);
sum += digit / 10 + digit % 10;
}
}
There was incorrect nesting around your if-else statement. I tested with a couple numbers and they printed the correct output.
First of all, it would be great if you included the "get_long_long" function, so we could see how the input is taken.
Secondly, the digit variable inside the checksum function wasn't initialized, which caused some problems.
Lastly, from a brief look here, you kinda implemented the algorithm in a wrong way, I fixed it, please check that the result is working for you:
bool checksum(long long ccn)
{
int sum = 0;
int digit;
for (int i = 0; ccn != 0; i++, ccn /= 10)
{
digit = ccn % 10;
if (i % 2 != 0) {
digit *= 2;
if (digit > 9)
digit -= 9;
}
sum += digit;
}
if ((sum % 10) == 0)
return true;
else
return false;
}
I'm new to C and I'm doing CS50. I can't get my code to work. I'm almost positive the for statement is correct. The sum given by the for statement is correct.
I think it's something to do with the (floor(ccNumber / pow(10,13) == 34) in the if statements.
Explanation of Luhn's Algorithm: https://cs50.harvard.edu/x/2020/psets/1/credit/
Sample credit card numbers for testing: https://www.freeformatter.com/credit-card-number-generator-validator.html
#include <stdio.h>
#include <cs50.h>
#include <math.h>
void credit(long ccNumber);
int main(void)
{
long ccNumber = 0;
credit(ccNumber);
}
void credit(long ccNumber)
{
do
{
ccNumber = get_long("Enter a credit card number: ");
}
while (ccNumber < 0);
{
int sum = 0;
long ccNumberFormat = ccNumber;
int nDigits = floor(log10(ccNumberFormat)) + 1;
int parity = nDigits % 2; // if parity % 2 == 0 then even number of digits, otherwise odd number of digits
for (int i = nDigits; i >= 0; i--) {
int digit = ccNumberFormat % 10;
if (i % 2 != parity) { // even number credit card digits will be multiplied by 2 every even number (starting from 0)
digit = digit * 2;
// printf("%d\n", sum);
}
if (digit > 9) {
digit = digit - 9;
}
sum = sum + digit;
ccNumberFormat /= 10;
printf("%d\n", sum);
}
if (sum % 10 == 0 && nDigits == 15 && (floor(ccNumber / pow(10,13) == 34) || (floor(ccNumber / pow(10,13) == 37))))
{
printf("%s\n", "AMEX");
}
else if (sum % 10 == 0 && (nDigits == 13 || nDigits == 16) && (floor(ccNumber / pow(10,12) == 4) || floor(ccNumber / pow(10,15) == 4)))
{
printf("%s\n", "VISA");
}
else if (sum % 10 == 0 && nDigits == 16 && ((floor(ccNumber / pow(10,14) >= 51) || (floor(ccNumber / pow(10,14) <= 55)))))
{
printf("%s\n", "MASTERCARD");
}
}
}
Pseudocode I more or less followed on Wikipedia::
function checkLuhn(string purportedCC) {
int sum := integer(purportedCC[length(purportedCC)-1])
int nDigits := length(purportedCC)
int parity := nDigits modulus 2
for i from 0 to nDigits - 2 {
int digit := integer(purportedCC[i])
if i modulus 2 = parity
digit := digit × 2
if digit > 9
digit := digit - 9
sum := sum + digit
}
return (sum modulus 10) = 0
}
A credit card number is a big number, are you sure long is enough and you do not need long long
Out of that in your expressions like floor(ccNumber / pow(10,13) == 34) the ')' is wrongly placed and you wanted floor(ccNumber / pow(10,13)) == 34 and of course the same for others :
if (sum % 10 == 0 && nDigits == 15 && ((floor(ccNumber / pow(10,13)) == 34) || (floor(ccNumber / pow(10,13)) == 37)))
{
printf("%s\n", "AMEX");
}
else if (sum % 10 == 0 && (nDigits == 13 || nDigits == 16) &&((floor(ccNumber / pow(10,12)) == 4) || (floor(ccNumber / pow(10,15)) == 4)))
{
printf("%s\n", "VISA");
}
else if (sum % 10 == 0 && nDigits == 16 && ((floor(ccNumber / pow(10,14)) >= 51) || (floor(ccNumber / pow(10,14)) <= 55)))
{
printf("%s\n", "MASTERCARD");
}
but in
else if (sum % 10 == 0 && (nDigits == 13 || nDigits == 16) &&((floor(ccNumber / pow(10,12)) == 4) || (floor(ccNumber / pow(10,15)) == 4)))
you take the risk to have a bad result, you need to check (floor(ccNumber / pow(10,12)) == 4) only if nDigits == 13 and (floor(ccNumber / pow(10,15)) == 4) only if nDigits == 16 and you can simplify to have :
else if (sum % 10 == 0 && (nDigits == 13 || nDigits == 16) &&(floor(ccNumber / pow(10,nDigits-1)) == 4))
So finally :
#include <stdio.h>
#include <math.h>
void credit(long long ccNumber);
int main(void)
{
long long cc[] = { 4532057997187363ll, // visa
4485661945778178ll, // visa
2720995573736457ll, // MasterCard
2720998284576493ll, // MasterCard
375137447049450ll, // amex
378572901284556ll, // amex
};
for (int i = 0; i != sizeof(cc)/sizeof(*cc); ++i)
credit(cc[i]);
return 0;
}
void credit(long long ccNumber)
{
int sum = 0;
long long ccNumberFormat = ccNumber;
int nDigits = floor(log10(ccNumberFormat)) + 1;
int parity = nDigits % 2; // if parity % 2 == 0 then even number of digits, otherwise odd number of digits
for (int i = nDigits; i >= 0; i--) {
int digit = ccNumberFormat % 10;
if (i % 2 != parity) { // even number credit card digits will be multiplied by 2 every even number (starting from 0)
digit = digit * 2;
// printf("%d\n", sum);
}
if (digit > 9) {
digit = digit - 9;
}
sum = sum + digit;
ccNumberFormat /= 10;
//printf("%d\n", sum);
}
if (sum % 10 == 0 && nDigits == 15 && ((floor(ccNumber / pow(10,13)) == 34) || (floor(ccNumber / pow(10,13)) == 37))) {
printf("%lld %s\n", ccNumber, "AMEX");
}
else if (sum % 10 == 0 && (nDigits == 13 || nDigits == 16) &&(floor(ccNumber / pow(10,nDigits-1)) == 4)) {
printf("%lld %s\n", ccNumber, "VISA");
}
else if (sum % 10 == 0 && nDigits == 16 && ((floor(ccNumber / pow(10,14)) >= 51) || (floor(ccNumber / pow(10,14)) <= 55))) {
printf("%lld %s\n", ccNumber, "MASTERCARD");
}
}
Compilation and execution:
pi#raspberrypi:/tmp $ gcc -Wall f.c -lm
pi#raspberrypi:/tmp $ ./a.out
4532057997187363 VISA
4485661945778178 VISA
2720995573736457 MASTERCARD
2720998284576493 MASTERCARD
375137447049450 AMEX
378572901284556 AMEX
pi#raspberrypi:/tmp $
note also to do floating point computation is a risk, you can do all only using long long
regarding:
int main(void)
{
long ccNumber = 0;
credit(ccNumber);
}
void credit(long ccNumber)
{
do
{
ccNumber = get_long("Enter a credit card number: ");
}
The call to credit() is passing the contents of the variable: ccnumber rather than a pointer to ccnumber. So the called function: credit() can never change that value in main().
Suggest:
int main(void)
{
long ccNumber = 0;
credit( &ccNumber );
}
void credit(long * ccNumber)
{
do
{
*ccNumber = get_long("Enter a credit card number: ");
}
In general, should never compare a floating point value with an integer value for equality, So the following kind of expression is very unreliable:
(floor(ccNumber / pow(10,13) == 34)
also, such an expression is actually just comparing two digits of the ccnumber to 34. MUCH better to have read the credit card number as a string then comparing the two digits to ccnumber[ first digit position ] == 3 && ccnumber[ second digit position ] == 4. Similar considerations exist for all the other expressions that are using pow()
Therefore, suggest getting the credit card number via:
string ccnumber = get_string( "enter credit card number" );
the result will be a pointer to the string containing the credit card number. each of the 'interesting' digits can then be accessed as an index (starting with 0) into the credit card number
however, if you really do not want to use a char array, you could replace expressions like;
(floor(ccNumber / pow(10,13) == 34)
with:
(ccNumber / 10000000000000 == 34)
#include <stdio.h>
#include <cs50.h>
// Luhn's Algorithm
int main(void)
{
long cardNumber = get_long("Please, enter your card number: ");
int sum1 = 0, num = 0, remainder = 0, sum2 = 0;
long temp = cardNumber;
while (temp > 0)
{
num = ((temp / 10) % 10) * 2; // Multiplying every other digit by 2, starting with the number’s second-to-last digit
while (num > 0)
{
remainder = num % 10;
sum1 += remainder; // Adding those products’ digits together
num /= 10;
}
temp /= 100;
}
// So as to restore the initial values of remainder and temp for the use in next loop
remainder = 0;
temp = cardNumber;
while (temp > 0)
{
remainder = temp % 10;
sum2 += remainder; // Sum of the digits that weren’t multiplied by 2
temp /= 100;
}
((sum1 + sum2) % 10) == 0 ? printf("Valid\n") : printf("Invalid\n");
return 0;
}
Solution based on concepts explained in week 1
#include <cs50.h>
#include <stdio.h>
int main(void)
{
long long cardNum;
do
{
cardNum = get_long_long("Enter Card number: ");
}
while (cardNum < 1);
long long tempCC;
int remNum, sum = 0, sum1 = 0, counter = 1, currentNum, total;
tempCC = cardNum;
do
{
currentNum = tempCC % 10;
if (counter % 2 == 0)
{
currentNum = currentNum * 2;
if (currentNum > 9)
{
currentNum = currentNum - 9;
}
sum += currentNum;
}
else
{
sum1 += currentNum;
}
counter++;
tempCC = tempCC / 10;
}
while (tempCC > 0);
total = sum + sum1;
if (total % 10 == 0)
{
tempCC = cardNum;
do
{
tempCC = tempCC / 10;
}
while (tempCC < 10 || tempCC > 100);
if (((counter - 1) == 15) && (tempCC == 34 || tempCC == 37))
{
printf("AMEX\n");
}
else if (((counter - 1) == 16) && (tempCC >= 51 && tempCC <= 55))
{
printf("MASTERCARD\n");
}
else if ((((counter - 1) == 13) || ((counter - 1) == 16)) && (tempCC / 10 == 4))
{
printf("VISA\n");
}
else
{
printf("INVALID\n");
}
}
else
{
printf("INVALID\n");
}
}