I wrote this code in C as a problem set from CS50, problem needed to be solved was to write a programme that can check if a credit card is valid and then if the card is valid identify ether the card is VISA,AMERICAN EXPRESS OR MASTERCARD.
I wrote the algorithim to check if the card number is valid and is printing invalid if the card number is invialid. My problem is that my code doesn't wanna print out the name is card is
#include <cs50.h>
#include <stdio.h>
int main(void)
{
long card;
//prompt the user for card number
do
{
card = get_long("Card no: ");
}
while (card < 0); // card number must always be greater than zero
//count digit starting from second-last then multiply by two
int card1,card2,card3,card4,card5,card6,card7,card8;
card1 = ((card % 100)/10 * 2);
card2 = ((card % 10000)/1000 * 2);
card3 = ((card % 1000000)/100000 * 2);
card4 = ((card % 100000000)/10000000 * 2);
card5 = ((card % 10000000000)/1000000000 * 2);
card6 = ((card % 1000000000000)/100000000000 * 2);
card7 = ((card % 100000000000000)/10000000000000 * 2);
card8 = ((card % 10000000000000000)/1000000000000000 * 2);
card1 = (card1 % 100 / 10) + (card1 % 10);
card2 = (card2 % 100 / 10) + (card2 % 10);
card3 = (card3 % 100 / 10) + (card3 % 10);
card4 = (card4 % 100 / 10) + (card4 % 10);
card5 = (card5 % 100 / 10) + (card5 % 10);
card6 = (card6 % 100 / 10) + (card6 % 10);
card7 = (card7 % 100 / 10) + (card7 % 10);
card8 = (card8 % 100 / 10) + (card8 % 10);
int sum1 = card1 + card2 + card3 + card4 + card5 + card6 + card7 + card8;
//find digits that where not multiplyed by two
int card9,card10,card11,card12,card13,card14,card15,card16;
card9 = (card % 10);
card10 = ((card % 1000)/100);
card11 = ((card % 100000)/10000);
card12 = ((card % 10000000)/1000000);
card13 = ((card % 1000000000)/100000000);
card14 = ((card % 100000000000)/10000000000);
card15 = ((card % 10000000000000)/1000000000000);
card16 = ((card % 1000000000000000)/100000000000000);
int card9,card10,card11,card12,card13,card14,card15,card16;
card9 = (card % 10);
card10 = ((card % 1000)/100);
card11 = ((card % 100000)/10000);
card12 = ((card % 10000000)/1000000);
card13 = ((card % 1000000000)/100000000);
card14 = ((card % 100000000000)/10000000000);
card15 = ((card % 10000000000000)/1000000000000);
card16 = ((card % 1000000000000000)/100000000000000);
int sum2 = card9 + card10 + card11 + card12 + card13
c
18th Jan 2023, 12:39 PM
Khulyso Dev®
Khulyso Dev® - avatar
3 Answers
Sort by: Votes
Answer
0
you mean I should first write code on sololearn playground and then share a link, the one I posted above I wrote it using VS code
18th Jan 2023, 2:53 PM
Khulyso Dev®
Khulyso Dev® - avatar
0
int sum2 = card9 + card10 + card11 + card12 + card13 + card14 + card15 + card16;
int sum3 = sum1 + sum2;
int length = 0;
long visa = card;
long amex = card;
long master = card;
if((sum3 % 10)!= 0)
{
printf("INVALID\n");
return 0;
}
//Differetiate between visa,master and Amex
while (card >0)
{
card = card / 10;
length++;
}
//Identify if its VISA
while (visa >= 0)
{
visa /= 10;
}
if (visa == 4 && (length == 13 || length == 16))
{
printf("VISA\n");
return 0;
}
//identify if its Amex
while (amex >= 10000000000000)
{
amex /= 10000000000000;
}
if (length == 15 && (amex == 34 || amex == 37))
{
printf("AMEX\n");
return 0;
}
//identify if its mastercard
while (master >= 100000000000000)
{
master /= 100000000000000;
}
if (length == 16 && (master == 51 || master == 52 || master == 53 || master == 54 || master == 55))
{
printf("MASTERCARD\n");
return 0;
}
else
printf("INVALID\n");
return 0;
}
I tried to replace printf("%s\n", "VISA"); with printf("VISA\n") but is still not printing out the desired output
Time to use a debugger.
Or take a close look at this:
//Identify if its VISA
while (visa >= 0)
{
visa /= 10;
}
This loop ends only if visa becomes smaller than 0, which only happens if visa was initially negative.
But the following code is entered only if visa is 4 - which never happens.
if (visa == 4 && (length == 13 || length == 16))
{
printf("VISA\n");
return 0;
}
Related
When I use below code to insert into TDengine database ,sometimes it will lose connection.
you can compile it and run to reproduce issue ,anyone could help on this ?
I use the async taos_query_a API to test the response time .:
//
// Created by jia.wen on 8/15/22.
//
//#include <fmt/format.h>
#include <chrono>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <unistd.h>
#include <vector>
#include <taos.h>
static unsigned long long get_nanosecs_since_epoch()
{
using namespace std::chrono;
return static_cast<unsigned long long>(duration_cast<nanoseconds>(
system_clock::now().time_since_epoch()).count());
}
static std::string format_nanosecs_since_epoch(unsigned long long nanosecs_since_epoch)
{
std::time_t secs_since_epoch(nanosecs_since_epoch / 1000000000);
std::tm secs_since_epoch_tm;
localtime_r(&secs_since_epoch, &secs_since_epoch_tm);
unsigned long long remaining_nanosecs = nanosecs_since_epoch % 1000000000;
char buffer[30];
int year = secs_since_epoch_tm.tm_year + 1900;
buffer[0] = (year / 1000) + '0';
buffer[1] = (year % 1000) / 100 + '0';
buffer[2] = (year % 100) / 10 + '0';
buffer[3] = (year % 10) + '0';
buffer[4] = '-';
int month = secs_since_epoch_tm.tm_mon + 1;
buffer[5] = (month / 10) + '0';
buffer[6] = (month % 10) + '0';
buffer[7] = '-';
buffer[8] = (secs_since_epoch_tm.tm_mday / 10) + '0';
buffer[9] = (secs_since_epoch_tm.tm_mday % 10) + '0';
buffer[10] = ' ';
buffer[11] = (secs_since_epoch_tm.tm_hour / 10) + '0';
buffer[12] = (secs_since_epoch_tm.tm_hour % 10) + '0';
buffer[13] = ':';
buffer[14] = (secs_since_epoch_tm.tm_min / 10) + '0';
buffer[15] = (secs_since_epoch_tm.tm_min % 10) + '0';
buffer[16] = ':';
buffer[17] = (secs_since_epoch_tm.tm_sec / 10) + '0';
buffer[18] = (secs_since_epoch_tm.tm_sec % 10) + '0';
buffer[19] = '.';
buffer[20] = (remaining_nanosecs / 100000000) + '0';
buffer[21] = (remaining_nanosecs % 100000000) / 10000000 + '0';
buffer[22] = (remaining_nanosecs % 10000000) / 1000000 + '0';
buffer[23] = (remaining_nanosecs % 1000000) / 100000 + '0';
buffer[24] = (remaining_nanosecs % 100000) / 10000 + '0';
buffer[25] = (remaining_nanosecs % 10000) / 1000 + '0';
buffer[26] = (remaining_nanosecs % 1000) / 100 + '0';
buffer[27] = (remaining_nanosecs % 100) / 10 + '0';
buffer[28] = (remaining_nanosecs % 10) + '0';
buffer[29] = 0;
return std::string(buffer);
}
void taos_insert_call_back(void* param, TAOS_RES* tres, int code)
{
unsigned long long* insert_time = (unsigned long long *)param;
struct timeval systemTime;
char sql[128];
if (code < 0)
{
printf("Insert failed. code:%d, cause:%s\n", code, taos_errstr(tres));
}
else if (code == 0)
{
// printf("Not inserted.\n");
}
else
{
printf("Succeed.\n");
}
taos_free_result(tres);
}
int main()
{
const char *host = "localhost:6030";
const char *user = "root";
const char *passwd = "taosdata";
const char *db = "test_lts";
uint16_t port = 0; // 0 means use the default port
TAOS *taos = taos_connect(host, user, passwd, db, port);
if (taos == NULL)
{
int errno_n = taos_errno(NULL);
auto msg = taos_errstr(NULL);
printf("%d, %s\n", errno, msg);
}
else
{
printf("connected\n");
std::string ins_sql;
std::vector<int> test_cycles_;
TAOS_RES* exec_result = NULL;
int cycles = 60;
int insert_times = 2000;
for (auto i = 0; i < cycles; ++i)
{
for (auto j = 0; j < insert_times; ++j)
{
auto local_time = format_nanosecs_since_epoch(get_nanosecs_since_epoch());
ins_sql = "INSERT INTO tick_jw VALUES ('" + local_time + "'," + std::to_string(i + 1) + ", 20221018, " + std::to_string(j)
+ ", 'test', 1.2, 200, 1000, 0, 0, 0, "
"1.15, 1.14, 1.13, 1.12, 1.11, 5, 4, 3, 2, 1, 1.16, 1.17, 1.18, 1.19, 1.20, 5, 4, 3, 2, 1)";
taos_query_a(taos, ins_sql.c_str(), taos_insert_call_back, (void *)(0));
// usleep(60);
}
std::cout << "cycles = " << i + 1 << " finished." << std::endl;
// sleep(1);
}
std::cout << "insert_times = " << insert_times << " test async finished." << std::endl;
sleep(60);
taos_close(taos);
}
taos_cleanup();
}
the core part is just :taos_query_a(taos, ins_sql.c_str(), taos_insert_call_back, (void *)(0));
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");
}
}
#include <stdio.h>
#include <cs50.h>
#include <math.h>
int main(void) {
long int number;
int count = 0; // starting the count counter
do {
number = get_long("Please enter your 13-16 digit credit card number: \n"); //getting input from the user
} while (number <= 0);
int d1 = number % 10; //separating digit number 1
int d2 = ((number % 100) / 10); //separating digit number 2
int d3 = ((number % 1000) / 100); //separating digit number 3
int d4 = ((number % 10000) / 1000); //separating digit number 4
int d5 = ((number % 100000) / 10000); //separating digit number 5
int d6 = ((number % 1000000) / 100000); //separating digit number 6
int d7 = ((number % 10000000) / 1000000); //separating digit number 7
int d8 = ((number % 100000000) / 10000000); //separating digit number 8
int d9 = ((number % 1000000000) / 100000000); //separating digit number 9
int d10 = ((number % 10000000000) / 1000000000); //separating digit number 10
int d11 = ((number % 100000000000) / 10000000000); //separating digit number 11
int d12 = ((number % 1000000000000) / 100000000000); //separating digit number 12
int d13 = ((number % 10000000000000) / 1000000000000); //separating digit number 13
int d14 = ((number % 100000000000000) / 10000000000000); //separating digit number 14
int d15 = ((number % 1000000000000000) / 100000000000000); //separating digit number 15
int d16 = ((number % 10000000000000000) / 1000000000000000); //separating digit number 16
int last13 = number / 1000000000000; //finding the last one digit of 13 digit VISA
int last15 = number / 10000000000000; //finding the last two digit of 15 digit AMEX
int last16v = number / 1000000000000000; //finding the last one digit of 16 digit VISA
int last16m = number / 100000000000000; //finding the last two digit of 16 digit MASTERCARD
int a2 = (d2 * 2);
int a4 = (d4 * 2);
int a6 = (d6 * 2);
int a8 = (d8 * 2);
int a10 = (d10 * 2);
int a12 = (d12 * 2);
int a14 = (d14 * 2);
int a16 = (d16 * 2);
if (a2 >= 10) { // separating the digits of the multiple
int a11a = (a2 % 100) / 10;
int a12a = (a2 % 10);
a2 = a11a + a12a;
}
if (a4 >= 10) { // separating the digits of the multiple
int a31 = (a4 % 100) / 10;
int a32 = (a4 % 10);
a4 = a31 + a32;
}
if (a6 >= 10) { // separating the digits of the multiple
int a51 = (a6 % 100) / 10;
int a52 = (a6 % 10);
a6 = a51 + a52;
}
if (a8 >= 10) { // separating the digits of the multiple
int a71 = (a8 % 100) / 10;
int a72 = (a8 % 10);
a8 = a71 + a72;
}
if (a10 >= 10) { // separating the digits of the multiple
int a91 = (a10 % 100) / 10;
int a92 = (a10 % 10);
a10 = a91 + a92;
}
if (a12 >= 10) { // separating the digits of the multiple
int a111 = (a12 % 100) / 10;
int a112 = (a12 % 10);
a12 = a111 + a112;
}
if (a14 >= 10) { // separating the digits of the multiple
int a131 = (a14 % 100) / 10;
int a132 = (a14 % 10);
a14 = a131 + a132;
}
if (a16 >= 10) { // separating the digits of the multiple
int a151 = (a16 % 100) / 10;
int a152 = (a16 % 10);
a16 = a151 + a152;
}
int b = d1 + d3 + d5 + d7 + d9 + d11 + d13 + d15;
int c = a2 + a4 + a6 + a8 + a10 + a12 + a14 + a16;
int l = b + c;
int j = a2 + a4 + a6 + a8 + a10 + a12;
int k = d1 + d3 + d5 + d7 + d9 + d11 + d13;
int m = j + k;
int e = d1 + d3 + d5 + d7 + d9 + d11 + d13 + d15;
int x = a2 + a4 + a6 + a8 + a10 + a12 + a14;
int n = x + e;
printf("%i", n);
if (l % 10 == 0) { //checking if the checksum is valid
for (int i = number; number != 0; i++) { // counting the credit card number
number /= 10;
count++;
}
if (count == 16) {
if (last16m == 51) { // checking the last two digit of credit card
printf("MASTERCARD\n"); // printing the result based on last two digits
} else
if (last16m == 52) { // checking the last two digit of credit card
printf("MASTERCARD\n"); // printing the result based on last two digits
} else
if (last16m == 53) { // checking the last two digit of credit card
printf("MASTERCARD\n"); // printing the result based on last two digits
} else
if (last16m == 54) { // checking the last two digit of credit card
printf("MASTERCARD\n"); //// printing the result based on last two digits
} else
if (last16m == 55) { // checking the last two digit of credit card
printf("MASTERCARD\n"); // printing the result based on last two digits
} else
if (last16v == 4) { // checking the last two digit of credit card
printf("VISA\n"); // printing the result based on last two digits
} else {
printf("INVALID\n");
}
if (count != 16) {
printf("INVALID\n");
}
} else {
printf("INVALID\n");
}
}
if (m % 10 == 0) { //checking if the checksum is valid
for (int i = number; number != 0; i++) { // counting the credit card number
number /= 10;
count++;
}
if (count == 13) {
if (last13 == 4) { // checking the last one digit of credit card
printf("VISA\n"); // printing the result based on last one digit
} else {
printf("INVALID\n");
}
} else {
printf("INVALID\n");
}
}
if (n % 10 == 0) { //checking if the checksum is valid
for (int i = number; number != 0; i++) { // counting the credit card number
number /= 10;
count++;
}
if (count == 15) {
if (last15 == 34) { // checking the last two digit of credit card
printf("AMEX\n"); // printing the result based on last two digits
} else
if (last15 == 37) { // checking the last two digit of credit card
printf("AMEX\n"); // printing the result based on last two digits
} else {
printf("INVALID\n");
}
if (count != 15) {
printf("INVALID\n");
}
} else {
printf("INVALID\n");
}
}
}
I tried using 4003600000000014 and it gives the correct output. Taking 4222222222222, it returns INVALID. It also doesn't works for AMEX numbers (15 digits). It doesn't responds on giving 4111111111111113 as input (it should return 0). Please tell me what's wrong, I am a newbie to programming. This is the result it gives on checking it through check50 https://submit.cs50.io/check50/44370b403c33f9b47d462e3278458901599d16e1.
There are multiple problems in the code:
the type for number should be unsigned long long to ensure it is large enough to handle the 16 digits. unsigned long may be large enough on some platforms, such as 64-bit linux and OS/X, but not on others such as all versions of Windows.
the computations are lengthy and cumbersome, it would be much more readable to use an array of digit values.
it is unclear whether you compute the count of digits once or multiple times. The loop modifies number and does not initialize count explicitly (and the variable i is useless). If run multiple times, it works by coincidence as number will already be 0 from the first run. You should use a temporary variable with the proper type and compute count just once.
the tests for different card number lengths may have false positives: for example if m % 10 == 0 and the card number does not have 13 digits, you would print INVALID incorrectly. The test should be first on the number of digits, then on the checksum.
it is very confusing to refer to the initial digits as the last digits.
Here is a simpler version using an array:
#include <stdio.h>
#include <stdlib.h>
// emulate cs50 get_long_long()
static long long get_long_long(const char *prompt) {
for (;;) {
long long n;
int c;
printf("%s", prompt);
if (scanf("%llu", &n) == 1)
return n;
printf("Invalid input, try again\n");
// flush the rest of the input line
while ((c = getchar()) != EOF && c != '\n')
continue;
if (c == EOF)
exit(1);
}
}
int main(void) {
long long int number, num;
int digit[16] = { 0 };
int count;
for (;;) { //getting input from the user
number = get_long_long("Please enter your 13-16 digit credit card number: \n");
if (number > 0)
break;
}
// only accept numbers with 13 to 16 digits
if (number < 1000000000000 || number > 9999999999999999) {
printf("INVALID\n");
return 1;
}
for (count = 0, num = number; num != 0; count++) {
digit[count] = num % 10;
num = num / 10;
}
// compute checksum
int checksum = 0;
for (int i = 0; i < 16; i += 2) {
int a1 = digit[i];
int a2 = digit[i + 1] * 2;
if (a2 >= 10)
a2 -= 9;
checksum += a1 + a2;
}
//printf("checksum: %d, ", checksum);
int first = digit[count - 1];
int first2 = 10 * digit[count - 1] + digit[count - 2];
if (checksum % 10 == 0) {
if (count == 16) {
if (first2 >= 51 && first2 <= 55) {
printf("MASTERCARD\n");
return 0;
} else
if (first == 4) {
printf("VISA\n");
return 0;
}
} else
if (count == 13) {
if (first == 4) {
printf("VISA\n");
return 0;
}
} else
if (count == 15) {
if (first2 == 34 || first2 == 37) {
printf("AMEX\n");
return 0;
}
}
}
printf("INVALID\n");
return 1;
}
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");
}
}
I have nearly finished the Credit task of PSET1 (CS50) although I have run into a problem trying to get the program to not allow an entry that isn't a card number (E.g "Foo" or "t" or anything other than a number) and then loop.
I have attempted various while statements and goto statements although none of these attempts have been sucessful
Also any other suggestions would be appreciated.
#include <stdio.h>
#include <cs50.h>
int main(void)
{
//gets cardnumber & counts digits entered
long long cardnumber;
int count = 0;
{
//prompts user for a cardnumber
printf("Enter a cardnumber: ");
scanf("%lld", &cardnumber);
}
//Prints count of digits entered (will likely not need this part)
//else printf("Number of digits: %d", count); printf("\n");
//Finds first 8 digits for checksum)
int digit1 = (((cardnumber % 100) / 10) * 2);
int digit2 = (((cardnumber % 10000) / 1000) * 2);
int digit3 = (((cardnumber % 1000000) / 100000) * 2);
int digit4 = (((cardnumber % 100000000) / 10000000) * 2);
int digit5 = (((cardnumber % 10000000000) / 1000000000) * 2);
int digit6 = (((cardnumber % 1000000000000) / 100000000000) * 2);
int digit7 = (((cardnumber % 100000000000000) / 10000000000000) * 2);
int digit8 = (((cardnumber % 10000000000000000) / 1000000000000000) * 2);
//Sum first 8 digits of checksum
int check1 = ((digit1 % 10) + (digit1 / 10));
check1 = (check1 + (digit2 % 10)) + (digit2 / 10);
check1 = (check1 + (digit3 % 10)) + (digit3 / 10);
check1 = (check1 + (digit4 % 10)) + (digit4 / 10);
check1 = (check1 + (digit5 % 10)) + (digit5 / 10);
check1 = (check1 + (digit6 % 10)) + (digit6 / 10);
check1 = (check1 + (digit7 % 10)) + (digit7 / 10);
check1 = (check1 + (digit8 % 10)) + (digit8 / 10);
//Sum last 8 digits of checksum & Sum of first 8 (check1)
int digit9 = ((cardnumber % 10) / 1);
int digit10 = ((cardnumber % 1000) / 100);
int digit11 = ((cardnumber % 100000) / 10000);
int digit12 = ((cardnumber % 10000000) / 1000000);
int digit13 = ((cardnumber % 1000000000) / 100000000);
int digit14 = ((cardnumber % 100000000000) / 10000000000);
int digit15 = ((cardnumber % 10000000000000) / 1000000000000);
int digit16 = ((cardnumber % 1000000000000000) / 100000000000000);
//add to remaining digits to those that were multiplied by 2
int checksum = (check1 + digit9 + digit10 + digit11 + digit12 + digit13 + digit14 + digit15 + digit16);
// Check first 2 digits
if (cardnumber / 10000000000000 == 34 || cardnumber / 10000000000000 == 37 )
goto Amex;
if (cardnumber / 100000000000000 == 51 || cardnumber / 100000000000000 == 52 || cardnumber / 100000000000000 == 53 || cardnumber / 100000000000000 == 54 || cardnumber / 100000000000000 == 55 )
goto Master;
if (cardnumber / 1000000000000000 == 4 )
goto Visa;
else
{
printf("INVALID\n");
(I = 0);
}
goto End;
// Amex start with 34 or 37
Amex:;
char A;
if (cardnumber / 10000000000000 == 34 || cardnumber / 10000000000000 == 37 )
{
A = 1;
}
else
{
A = 0;
}
goto End;
// Mastercard start with 51, 52, 53, 54, 55
Master:;
char M;
if (cardnumber / 100000000000000 == 51 || cardnumber / 100000000000000 == 52 || cardnumber / 100000000000000 == 53 || cardnumber / 100000000000000 == 54 || cardnumber / 100000000000000 == 55 )
{
M = 1;
}
else
{
M = 0;
}
goto End;
//Visa start with 4
Visa:;
char V;
if (cardnumber / 1000000000000000 == 4 )
{
V = 1;
}
else
{
V = 0;
}
goto End;
End:;
while(cardnumber != 0)
{
// cardnumber = cardnumber/10
cardnumber /= 10;
++count;
}
// if cardnumber <13 or >16 digits error "invalid card" given
if (count > 16 || count < 13)
{
printf("INVALID\n");
(I = 0);
}
// Keep track of first 2 digits & validate checksum
char T;
if (checksum % 10 == 0)
{
T = 1;
}
else
{
T = 0;
}
if (T == 0) printf("INVALID\n");
{
(I = 0);
}
// - Amex (15 digits, start with 34 or 37)
if (count == 15 && T == 1 && A == 1)
{
printf("AMEX\n");
}
// - Mastercard (16 digits, start with 51, 52, 53, 54, 55)
if (count == 16 && T == 1 && M == 1)
{
printf("MASTERCARD\n");
}
// - Visa (13 & 16 digits, start with 4)
if ((count == 13 && T == 1 && V == 1) || (count == 16 && T == 1 && V == 1))
{
printf("VISA\n");
}
}
Prompt the user to type in the credit card number, use a do while loop so that if the number is less than 0, you will keep asking the user for a card number.
int main(void)
{
long long credit_card_number;
do
{
credit_card_number = get_long_long("Enter Valid Credit Card Number: ");
}
while (credit_card_number < 0);
#include <cs50.h>
#include <math.h>
#include <stdio.h>
int main(void)
{
long long cardnumber = 0;
do
{
cardnumber = get_long("Number: ");
}
while (cardnumber < 0);
int count = 0;
long long digits = cardnumber;
while (digits > 0)
{
digits = digits/10;
count++;
}
if ((count != 13) && (count != 15) && (count != 16))
{
printf("INVALID\n");
}
int number[count];
for (int i = 0; i < count; i++)
{
number[i] = cardnumber % 10;
cardnumber = cardnumber / 10;
}
int originalnumber[count];
for (int i = 1; i < count; i++)
{
originalnumber[i] = number[i];
}
for (int i = 1; i < count; i+=2)
{
number[i] = number[i] * 2;
}
int v = 0;
int temp;
if (count == 13)
{
for (int i = 0; i < count; i++)
{
temp = (number[i] % 10) + (number[i]/10 % 10);
v = v + temp;
}
if (originalnumber[12] == 4 && v % 10 == 0)
{
printf("VISA\n");
}
else
{
printf("INVALID\n");
}
}
if (count == 15)
{
for (int i = 0; i < count; i++)
{
temp = (number[i] % 10) + (number[i]/10 % 10);
v = v + temp;
}
if (originalnumber[14] == 3 && v % 10 == 0 && (originalnumber[13] == 4 || originalnumber[13] == 7))
{
printf("AMEX\n");
}
else
{
printf("INVALID\n");
}
}
if (count == 16)
{
for (int i = 0; i < count; i++)
{
temp = (number[i] % 10) + (number[i]/10 % 10);
v = v + temp;
}
if (originalnumber[15] == 4 && v % 10 == 0)
{
printf("VISA\n");
}
else if (originalnumber[15] == 5 && v % 10 == 0 && (originalnumber[14] == 1 || originalnumber[14] == 2 || originalnumber[14] == 3 || originalnumber[14] == 4 || originalnumber[14] == 5))
{
printf("MASTERCARD\n");
}
else
{
printf("INVALID\n");
}
}
}