I need to extract the odd number out and give the output, but when I execute the code, it gives me in reverse order (e.g. expected output is1234 = 13 but my code gave me 31).
int digit, num;
while (num > 0)
{
digit = num % 10;
if(digit % 2 != 0)
{
printf("%d" , digit);
}
num /= 10;
}
That is because you are first printing the remainder from the division operation in the following statement:
digit = num % 10;
You have to store it in an array and after all the divisions are complete only print it.
you're printing the units first. So you need either to store the data, or to use a recursive approach so last numbers are printed first:
#include <stdio.h>
void podd(int num)
{
if (num > 0)
{
int digit = num % 10;
if (digit % 2)
{
printf("%d" , digit);
}
podd(num / 10);
}
}
int main()
{
podd(1234);
printf("\n");
return 0;
}
(variation of the classic int to string conversion problem described here: Convert integer to string without access to libraries)
Obviously, It will output 31.
Coz,
1st iteration in while loop =>
num is 1234
digit = num % 10; digit = 1234 % 10 ( It's 4)
if(digit % 2 != 0)
{
printf("%d" , digit);
}
4 will not print coz 4 % 2 != 0 will return false.
num /= 10; num = 1234 / 10 ( num is now 123)
2nd iteration in while loop =>
num is 123
digit = num % 10; digit = 123 % 10 ( It's 3)
if(digit % 2 != 0)
{
printf("%d" , digit);
}
3 will be printed coz 4 % 2 != 0 will return true.
num /= 10; num = 123 / 10 ( num is now 12)
So ... we got our first number 3.
So, if you continue this process (it's called debugging ) for the next while loop iterations you will find the final output ... that's 31.
The direct answer as follows:
int num = 1234, digit = 0;
do {
digit = num % 10; // Assigns the extracted digit to a variable named digit (ex: 4).
if (digit % 2 != 0) // Applies the formula to get the odd number.
printf("%d\n", digit); // Prints the odd number.
num /= 10; // Extracts one digit each time (ex: 1234 / 10 = 123).
} while (num > 0); // Has reached the end of the number 'num'.
The Result:
3
1
Related
I want to multiply every other digit by 2, starting with the number’s second-to-last digit, and then add those products’ digits together, but the first printed values seem completely nonsensical.
#include <stdio.h>
#include <math.h>
int len(long li);
int main(void)
{
// Get credit card number
long credit_card = 378282246310005;
// Adding every second digit's double's digits, starting with the second to last
int sum = 0;
int digit_doubled;
for (int i = 0; i < len(credit_card); i++)
{
if (i % 2 == 0)
{
continue;
}
digit_doubled = (int) (credit_card / pow(10, i)) % 10 * 2;
printf("Digit doubled %i: %i\n", i, digit_doubled);
for (int j = 0; j < len(digit_doubled); j++)
{
sum += (int) (digit_doubled / pow(10, j)) % 10;
}
}
}
int len(long li)
{
if (li == 0)
{
return 1;
}
return floor(log10(li)) + 1;
}
I have tried modifying the expression to see what results I'd get. When I deleted the
% 10 * 2 from the end of digit_doubled = (int) (credit_card / pow(10, i)) % 10 * 2;, I got results that indicate some kind of integer overflow, but I have absolutely no idea where it could be coming from since my program isn't really producing any high values anywhere.
Having suggested using a LUT to deliver the single digit value required by the OP's question, here is a snippet of code to do just that:
unsigned long long copy = longValue; // perhaps correct on OP's compiler??
copy /= 10; // dispose of the checksum digit (rightmost)
// The following line depends on the OP's problem statement
// Is this digit odd (checksum digit being digit zero)
// or is this digit even? (checksum digit being disregarded.)
// Incl-/excl- next line to suit problem statement.
copy /= 10; // dispose of the rightmost "odd" digit
while( copy ) {
int digit = copy % 10; // get "even" digit from the right end.
// Crafted LUT to return correctly "doubled & folded" value of this digit.
sum += "0246813579"[digit] - '0';
copy /= 100; // "shift" value down by 100 (ie: 2 digits of value)
}
I leave it as an exercise for the OP to determine what characterises "even" and "odd" in the sequence of digits of a credit card "number". Does one count the checksum digit as '1' or not? For the OP to work out...
For fun, here's the loop after compaction.
for( /**/; copy; copy /= 100 )
sum += "0246813579"[ copy % 10 ] - '0';
And, a more advanced version would simply calculate the desired value from the supplied value:
for( /**/; copy; copy /= 100 )
sum += copy%5 * 2 + copy%10/5;
For those who (reasonably) question the validity of the formula above:
#include <stdio.h>
int main( void ) {
for( int i = 0; i < 10; i++ ) {
int j = 2 * i;
printf( "Digit Value: %d ", i );
printf( " x2 = %02d ", j );
printf( "==> %d + %d ", j/10, j%10 );
printf( "==> %d ", j/10 + j%10 );
printf( "==== %d\n", i%5 * 2 + i%10/5 ); // <== Formula version
}
return 0;
}
Digit Value: 0 x2 = 00 ==> 0 + 0 ==> 0 ==== 0
Digit Value: 1 x2 = 02 ==> 0 + 2 ==> 2 ==== 2
Digit Value: 2 x2 = 04 ==> 0 + 4 ==> 4 ==== 4
Digit Value: 3 x2 = 06 ==> 0 + 6 ==> 6 ==== 6
Digit Value: 4 x2 = 08 ==> 0 + 8 ==> 8 ==== 8
Digit Value: 5 x2 = 10 ==> 1 + 0 ==> 1 ==== 1
Digit Value: 6 x2 = 12 ==> 1 + 2 ==> 3 ==== 3
Digit Value: 7 x2 = 14 ==> 1 + 4 ==> 5 ==== 5
Digit Value: 8 x2 = 16 ==> 1 + 6 ==> 7 ==== 7
Digit Value: 9 x2 = 18 ==> 1 + 8 ==> 9 ==== 9
In the first loop when i=1 you cast a value greater than the maximum value that can be stored in an integer (2147483647) which cause it to be truncated and on my system go negative:
digit_doubled = (int) (credit_card / pow(10, i)) % 10 * 2; // =>
digit_doubled = (int) 37828224631000 % 10 * 2; / =>
digit_doubled = -1847312168 % 10 * 2; // =>
digit_doubled = -16;
I suggest you include stdint.h and use uint64_t instead of silently assume that a long is 64 bit. Alternatively, consider using a string as a credit number is an identifier not a number (even though it is written as one).
Mixing functions that operate on double for integer type values will open you up to floating point rounding errors. You could use uint64_t versions of these functions instead of double. Below I implemented a len() and my_pow10() functions for you. As the value of digit_doubled is at most 18 you can just inline that calculation instead of using a loop.
#include <stdio.h>
#include <stdint.h>
uint64_t my_pow10(uint64_t x) {
if(x == 0) return 1;
size_t v = 10;
for(size_t i = 1; i < x; i++, v *= 10);
return v;
}
size_t len(uint64_t v) {
size_t i = 0;
for(; v; i++, v /= 10);
return i;
}
int main(void) {
const uint64_t credit_card = 378282246310005;
const uint8_t credit_card_len = len(credit_card);
uint8_t sum = 0;
for (uint8_t i = 1; i < credit_card_len; i += 2) {
uint8_t digit_doubled = credit_card / my_pow10(i) % 10 * 2;
printf("Digit doubled %hhu: %hhu\n", i, digit_doubled);
sum += digit_doubled / 10 + digit_doubled % 10;
}
printf("sum = %u\n", sum);
}
You don't need floating-point arithmetic at all here, or logs or pows. You can use % 10 to extract the next digit, and / 10 to discard it. Like this:
#include <stdint.h>
#include <stdio.h>
int main(void)
{
uint64_t credit_card = 378282246310005ULL;
int sum = 0;
while (credit_card != 0)
{
credit_card /= 10; // Discard rightmost digit
int double_digit = 2 * (credit_card % 10);
credit_card /= 10;
sum += double_digit % 10;
double_digit /= 10;
sum += double_digit % 10;
}
printf ("%d\n", sum);
}
Iam trying to implement Luhn's algorithm in the C language to check credit card validity, for those who don't know... this is it:
Multiply every other digit by 2, starting with the number’s
second-to-last digit, and then add those products’ digits together.
Add the sum to the sum of the digits that weren’t multiplied by 2.
If the total’s last digit is 0 (or, put more formally, if the total
modulo 10 is congruent to 0), the number is valid!
and to implement that, I looped through the whole number and if the number place I was in had a modulo 2 equal to 0 then I would multiply by two and add to a variable called totalEven.
if that wasn't the case I would add the number I was in to totalOdd without multiplication.
I would then increment the place by one and check the other numbers until I reach 16 (the max digits for a card).
I would later add both variables and check if the total modulo ten was equal to 0. If it means the credit card number is correct, else it is false.
here is the code:
#include <stdio.h>
#include <cs50.h>
//list of variables
//is the card valid
bool isValid = true;
// the creditcard number
long input;
//mod stands for modules, and is used to single out each number as seen later
int mod = 10;
//the location at which number I am checking
int place = 1;
//num is the number I am checking that has been singled out
int num = 0;
//total of numbers * 2 located at locations numbered with even numbers
int totalEven = 0;
//total of numbers located at locations numbered with odd numbers
int totalOdd = 0;
//gets input and stores it in well.. input
input = get_long("Number: ");
// a formula to single out a number, starting with the ones and then as you can see, mod is muliplied by 10 to go over the second number.
num = ((input % mod) - (input % (mod /10))) / (mod/10);
//loops 16 times
for(int i = 0; i < 16; i++)
{
// if the place is even execute below
if(place % 2 == 0)
{
totalEven = totalEven + num * 2;
}
//else do this
else if (place % 2 != 0)
{
totalOdd = totalOdd + num;
}
//moves to the next number
mod = mod * 10;
place++;
}
//fufils the last step of the algorithm
if((totalEven + totalOdd) % 10 == 0 )
{
isValid = true;
}
else
{
isValid = false;
}
problem is that this block of code gives me invalid or !isValid even though the credit card number is supposed to be correct and I checked my "formula" and it works just fine...
I have absolutely no idea what to do... I am a humble hobbyist so plz don't roast me for the monstrosity above.
here is a complete version of the code
#include <stdio.h>
#include <cs50.h>
long power();
int main(void)
{
//AMERX 15 STRT 34 OR 37
//MC 16 STRT 51, 52, 53, 54, 55
//VZA 13 OR 16 STRT 4
long input;
bool isValid = true;
string type;
int mod = 10;
int place = 1;
int num = 0;
int totalEven = 0;
int totalOdd = 0;
do
{
input = get_long("Number: ");
}
while(input < 0);
for(int i = 0; i < 16; i++)
{
num = ((input % mod) - (input % (mod /10))) / (mod/10);
if(place % 2 == 0)
{
totalEven = totalEven + num * 2;
}
else
{
totalOdd = totalOdd + num;
}
mod = mod * 10;
place++;
}
if((totalEven + totalOdd) % 10 == 0 )
{
isValid = true;
}
else
{
isValid = false;
printf("%i , %i", totalEven, totalOdd);
}
if (isValid == true){
if((input < (38 * power(10, 13)) && input >=(37 * power(10, 13))) || (input < (35 * power(10,13)) && input >= (34 * power(10, 13))))
{
type = "AMEX\n";
}
else if(input >= (51 * power(10, 14)) && input < (56 * power(10, 14)))
{
type = "MASTERCARD\n";
}
else if((input < (5 * power(10, 12)) && input >= (4 * power(10, 12))) || (input < (5 * power(10, 15)) && input >= (4 * power(10, 15))))
{
type = "VISA\n";
}
else{
type = "error\n";
}
}
else
{
type = "INVALID\n";
}
if((totalEven + totalOdd) % 10 == 0 )
{
isValid = true;
}
else
{
isValid = false;
}
printf("%s", type);
}
long power(int n, int p)
{
long result = 1;
for(int i = 0; i<p; i++)
{
result = result * n;
}
return result;
I'm not an expert in Luhn algorithm but when I read https://en.wikipedia.org/wiki/Luhn_algorithm it seems to me that you are doing it wrong.
Quote from https://en.wikipedia.org/wiki/Luhn_algorithm :
From the rightmost digit (excluding the check digit) and moving left, double the value of every second digit. The check digit is neither doubled nor included in this calculation; the first digit doubled is the digit located immediately left of the check digit. If the result of this doubling operation is greater than 9 (e.g., 8 × 2 = 16), then add the digits of the result (e.g., 16: 1 + 6 = 7, 18: 1 + 8 = 9) or, alternatively, the same final result can be found by subtracting 9 from that result (e.g., 16: 16 − 9 = 7, 18: 18 − 9 = 9).
I don't see anywhere in your code where you handle that bolded part.
Instead of
totalEven = totalEven + num * 2;
I think you need
int tmp = num * 2;
if (tmp > 9) tmp = tmp - 9;
totalEven = totalEven + tmp;
That said - I think you are making the implementation much more complex than needed by storing the input as a number. Instead of a number you could use an array of digits.
That is - instead of
long input = 1122334455667788
use
int digits[] = {8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1};
// Notice that index zero is the rightmost digit
In this way the algorithm is much more simple:
// Double every second element and check for overflow
for (idx = 1; idx < 16; idx += 2)
{
digits[idx] = 2 * digits[idx];
if (digits[idx] > 9) digits[idx] = digits[idx] - 9;
}
// Calculate the sum
sum = 0;
for (idx = 0; idx < 16; ++idx)
{
sum = sum + digits[idx];
}
If you must receive the input as a number, start by calling a function that converts the number to an array of digits. You can find many, many examples of how that conversion is done here on SO. Here Converting integer into array of digits is just one of many examples.
As I was looking at your code, there some mistakes I want to point out.
You forgot: #include <string.h> as you did declare string type in the code.
input = get_long("Number: "); should have its own do-while loop in case user inputs letters or incorrect numbers.
if(place % 2 == 0){
totalEven = totalEven + num * 2;
}
else if (place % 2 != 0){
totalEven = totalEven + num;
} should totalOdd = totalOdd + num for the second part
totalEven = totalEven + num * 2 is right and wrong at the same time. It only works if the number multiplied by 2 is less than 10. If the num * 2 >= 10, lets say num = 6, then 6 * 2 is 12 which would then be 1 + 2 + totalEven.
num = ((input % mod) - (input % (mod /10))) / (mod/10); This should be in the first for loop.
In #include <math.h>, there is a power function called pow which does exactly as your power() function.
Caution: I have made use of CS50X Library as the question seems to be the one from the same.
#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;
}
#include <stdio.h>
#include <cs50.h>
int main(void)
{
long cc = get_long("Credit Card: "); // gets input
long len = 0; //intialized length
long x = cc; // set 2nd variable = to cc to prevent manipulation of cc
while (x != 0) // length count loop while x is divisable loop will continue will be stored as len
{
x = x / 10;
len++;
}
if ((len != 16) && (len != 15) && (len != 13)) //Checking for length to see if number matchs possible postive outcomes
{
printf("INVALID\n");
return 0;
}
//pull 2nd to last and then every other digit
long cc_num1 = ((cc % 100) / 10);
long cc_num2 = ((cc % 10000) / 1000);
long cc_num3 = ((cc % 1000000) / (100000));
long cc_num4 = ((cc % 100000000) / (10000000));
long cc_num5 = ((cc % 10000000000) / (1000000000));
long cc_num6 = ((cc % 1000000000000) / (100000000000));
long cc_num7 = ((cc % 100000000000000) / (10000000000000));
long cc_num8 = ((cc % 10000000000000000) / (1000000000000000));
cc_num1 = (cc_num1 * 2); //Multiply digits pulled above by 2
cc_num2 = (cc_num2 * 2);
cc_num3 = (cc_num3 * 2);
cc_num4 = (cc_num4 * 2);
cc_num5 = (cc_num5 * 2);
cc_num6 = (cc_num6 * 2);
cc_num7 = (cc_num7 * 2);
cc_num8 = (cc_num8 * 2);
cc_num1 = ((cc_num1 / 10) + (cc_num1 % 10)); //split double digits and add to signles
cc_num2 = ((cc_num2 / 10) + (cc_num2 % 10));
cc_num3 = ((cc_num3 / 10) + (cc_num3 % 10));
cc_num4 = ((cc_num4 / 10) + (cc_num4 % 10));
cc_num5 = ((cc_num5 / 10) + (cc_num5 % 10));
cc_num6 = ((cc_num6 / 10) + (cc_num6 % 10));
cc_num7 = ((cc_num7 / 10) + (cc_num7 % 10));
cc_num8 = ((cc_num8 / 10) + (cc_num8 % 10));
long cc_sum = cc_num1 + cc_num2 + cc_num3 + cc_num4 + cc_num5 + cc_num6 + cc_num7 + cc_num8; // add sum of number above
long cc_num1x = ((cc % 10) / 1); //pulls last digit from card then everyother digit
long cc_num2x = ((cc % 1000) / 100);
long cc_num3x = ((cc % 100000) / 10000);
long cc_num4x = ((cc % 10000000) / 1000000);
long cc_num5x = ((cc % 1000000000) / 100000000);
long cc_num6x = ((cc % 100000000000) / 10000000000);
long cc_num7x = ((cc % 10000000000000) / 1000000000000);
long cc_num8x = ((cc % 1000000000000000) / 100000000000000);
long cc_sumx = cc_num1x + cc_num2x + cc_num3x + cc_num4x + cc_num5x + cc_num6x + cc_num7x +
cc_num8x; //adds last and everyother digit together
long sumofsums = cc_sum + cc_sumx; // adds sums of both sums created
if ((sumofsums % 10) != 0) // Luhn’s Algorithm results will close if not met
{
printf("INVALID\n");
return 0;
}
{
if (len == 15) // checks for AMEX by using length then first 2 digits
{
long ax = cc / 10000000000000;
if ((ax == 34 || ax == 37))
{
printf("AMEX\n");
}
else
{
printf("INVALID\n");
return 0;
}
}
}
long mc = cc / 100000000000000;
long v = cc / 1000000000000000;
long v2 = cc / 1000000000000;
if (len == 16) // Checks for MC and Via (16 digits) by length then first 2 digits MC or 1 visa
{
if ((mc == 51 || mc == 52 || mc == 53 || mc == 54 || mc == 55))
{
printf("MASTERCARD\n");
}
else if (v == 4)
{
printf("VISA\n");
}
else
{
printf("INVALID\n");
return 0;
}
}
if (len == 13) //Checks 2nd Visa length 13 digits then 1st digit
{
if (v2 == 4)
{
printf("VISA\n");
}
else
{
printf("INVALID\n");
return 0;
}
}
}
There has to be a better way then the way I am planning to do this. The Length count loop is fine until 10 digits but then pulls random numbers.
The every other digit formula seems like it can be done through recursion but I am blanking on that. Since the number is limited to 16 at most the formula I am using seems to work.
Determine if card is 15 || 16 || 13 digits if not mark In valid in IF Else loop
Use CC check sum formula If else loop (In valid if it doesn't meet Criteria)
Look at 2 Starting numbers to determine AX, MC or Visa
#include <stdio.h>
#include <cs50.h>
#include <string.h>
int main(void)
{
long cc = get_long("Credit Card: " ); // gets input
int len = 0; //intialized length
int x = cc; // set 2nd variable = to cc to prevent manipulation of cc
while(x != 0) // length count loop while x is divisable loop will continue will be stored as len
{
x = x/10;
len++;
}
printf("%i\n", len); // REMOVE !!!!!!!!!!! BUG TEST
//pull 2nd to last and then every other digit
int cc_num1 = ((cc % 100)/10);
int cc_num2 = ((cc % 10000)/1000);
int cc_num3 = ((cc % 1000000)/(100000));
int cc_num4 = ((cc % 100000000)/(10000000));
int cc_num5 = ((cc % 10000000000)/(1000000000));
int cc_num6 = ((cc % 1000000000000)/(100000000000));
int cc_num7 = ((cc % 100000000000000)/(10000000000000));
int cc_num8 = ((cc % 10000000000000000)/(1000000000000000));
printf("%i %i %i %i %i %i %i %i", cc_num1, cc_num2, cc_num3, cc_num4 , cc_num5, cc_num6 , cc_num7 , cc_num8 );
}
Let's acknowledge the elephant in the room first.
long cc = get_long("Credit Card: " );
...
int x = cc;
The C standard specifies long to be at least 32 bits, whereas int must be at least 16 bits. The actual values are dependent on your system and your library implementation of course. But more often than not, long will be capable of storing more bits than an int. As is the case here. This means "numbers with more than 10 digits", essentially numbers that are too large to be stored into an int, will cause undefined behavior. To know exactly which number is the upper limit for int in your system/environment, you may print the value of INT_MAX, defined in limits.h.
The solution is, of course, to store the long variable in another long variable, not an int. Or, simply pass the value to a function that does the necessary work. Putting everything in main isn't being very organized now is it.
How about we make a function that basically prints all the details about a card given the card's number?
The signature will look like-
void print_card_details(long num)
Now we need a function to put the card through luhn's algorithm. We can also make a function for that-
int is_valid(long num)
{
int curr_digit, add_digit, prod_sum = 0, sum = 0;
for (int digit_count = 0; num != 0; num /= 10, digit_count++)
{
// Strip each digit from number, starting from the end
curr_digit = num % 10;
if (digit_count % 2 != 0)
{
// Every 2nd digit from the right goes through this
// The current digit gets doubled
// The digits of that result are added to the sum
add_digit = curr_digit * 2;
prod_sum += add_digit % 10 + add_digit / 10;
}
else
{
// The remaining digits go through this
// They are all summed up
sum += curr_digit;
}
}
if ((prod_sum + sum) % 10 != 0)
{
// If the sum of prod_sum + sum doesn't end in 0
// It is invalid
return 0;
}
else
{
// The card is valid
return 1;
}
}
The conventional way to iterate through the digits of a number is not to bruteforcefully divide arbitrary powers of 10 manually, but to iterate through it and divide and modulus by 10. For example, this snippet-
while (x != 0)
{
printf("Current digit: %d\n", x % 10);
x /= 10;
}
Will print all digits of the number stored in x. This is essentially what we've used in the luhn's algorithm loop. Except we also keep a count of the total digits, because we only want every second digit starting from the end. How do we know the current digit qualifies this criteria? We check if the current digit_count is even (by dividing by 2 and checking the leftover is 0).
The formula that follows-
add_digit = curr_digit * 2;
prod_sum += add_digit % 10 + add_digit / 10;
is basically the implementation of this-
Multiply every other digit by 2, starting with the number’s second-to-last digit, and then add those products’ digits together.
Make sure only the digits of the resulting add_digit is added. So if add_digit ended up being 12. We need to add 1 + 2. That's exactly what add_digit % 10 + add_digit / 10 does. 12 % 10 is, of course, 2. And 12 / 10 is 1.
This function returns 1 if the card is valid, 0 if it's not. You can fit this up in your main function and check the return value to know whether the card is valid.
If it is valid, move on to the next step of checking the number of digits the card has, as well as what it begins with.
We can make a loop to count the number of digits, as well as store the very first and second digit of the number.
int len = 0;
int curr_digit = 0, prev_digit = 0;
while(num != 0)
{
prev_digit = curr_digit;
curr_digit = num % 10;
num /= 10;
len++;
}
This will give you the length of the card number. Notice, in the last iteration, the value of prev_digit is the second digit and the curr_digit is the first. So curr_digit * 10 + prev_digit will yield the first 2 numbers (together) that the credit card number begins with.
Finally, you just need a bunch of simple if/else clauses to verify which card it is. You're only asked to check for a very small subset as well. So here it is-
// Construct the 2 digit number that this card num begins with
int begins_with = curr_digit * 10 + prev_digit;
if (len == 13 && begins_with / 10 == 4)
{
// We know only VISA uses 13 digits
// And it begins with 4 (second digit does not matter)
printf("VISA\n");
}
else if (len == 15 && begins_with == 34 ||)
{
// We know only AMEX uses 15 digits
printf("AMEX\n");
}
else if (len == 16)
{
// Both VISA and MASTERCARD use 16 digits
if (curr_digit == 4)
{
// But VISA card number begins with 4
printf("VISA\n");
}
else if (curr_digit == 5)
{
// MASTERCARD number begins with 5
printf("MASTERCARD\n");
}
else
{
// Out of context for this problem
printf("INVALID\n");
}
}
else
{
// Out of context for this problem
printf("INVALID\n");
}
Put that all together, and you should hopefully get
void print_card_details(long num)
{
if (!is_valid(num))
{
// Card did not pass luhn's algo
printf("INVALID\n");
return;
}
int len = 0;
int curr_digit = 0, prev_digit = 0;
while(num != 0)
{
prev_digit = curr_digit;
curr_digit = num % 10;
num /= 10;
len++;
}
// Construct the 2 digit number that this card num begins with
int begins_with = curr_digit * 10 + prev_digit;
if (len == 13 && curr_digit == 4)
{
// We know only VISA uses 13 digits
// And it begins with 4 (second digit does not matter)
printf("VISA\n");
}
else if (len == 15 && (begins_with == 34 || begins_with == 37))
{
// We know only AMEX uses 15 digits
printf("AMEX\n");
}
else if (len == 16)
{
// Both VISA and MASTERCARD use 16 digits
if (curr_digit == 4)
{
// But VISA card number begins with 4
printf("VISA\n");
}
else if (begins_with >= 51 && begins_with <= 55)
{
// MASTERCARD number begins with 51, 52, 53, 54, or 55
printf("MASTERCARD\n");
}
else
{
// Out of context for this problem
printf("INVALID\n");
}
}
else
{
// Out of context for this problem
printf("INVALID\n");
}
return;
}
I have a remainder function that finds that modulo of a number then a divider function to divide that number. My program isn't working the way I need it to. For example if I put in 2502 as my number, I should get the output of : 2 5 0 2.
I need to be able to store the value through each iteration, so for example:
number: 123
123 % 10 = 3 //last digit
Number: 123 / 10 = 12
12 % 10 = 2 //second digit
Number: 12 / 10 = 1
1 % 10 = 1 //first digit
int Rem(int num);
int Div(int num);
int main() {
int num;
printf("Enter an integer between 1 and 32767: ");
scanf("%d", &num);
Rem(num);
Div(num);
printf("%d","The digits in the number are: ");
}
int Rem(int num) {
while(num != 0){
int rem = num % 10;
return rem;
}
}
int Div(int num){
while(num != 0){
int div = num / 10;
return div;
}
}
The idea here is pretty simple, but there are some subtleties. Here's some pseudo code. You'll need to convert to C.
num = 9934; // or get it from input
do {
rem = num % 10; // this gives you the lowest digit
num = num / 10; // divide by 10 to get rid of that lowest digit
print rem;
} while (num != 0);
I use a do ... while loop so the output will be correct if the user enters 0.
If you code this up and run it, you'll notice that it prints the digits in reverse order: 4 3 9 9. So you'll need some way to reverse the digits before you output them. Three possible ways are:
Store the digits in an array, and then reverse the array before outputting.
Push each digit onto a stack. When you're done, pop each digit off the stack and output it.
Write a recursive function. That would eliminate the need for an explicit stack or array.
Also you could convert it to a string and then convert back the elements of that string, but keep '\0' in mind
You can simply use this function , it return the number of digits passing by argument
size_t ft_cnbr(int n)
{
size_t count;
count = 1;
if (n < 0)
{
count++;
n = -n;
}
while (n > 9)
{
n = n / 10;
count++;
}
return (count);
}
Without using an array.. How can I manage to turn a flag from 1 to 0 if there is the same digit twice or more in a number?
take it as if they are all integers, the temp & temp2 are the same number which is a 4 digit number
for(i = 0; i < 4; i++) //if a digits shows twice
{
n = temp % 10;
for(k = 0; k <= 6; k++)
{
if(n == temp2 % 10)
{
counter++;
}
temp2 /= 10;
}
temp /= 10;
if(counter > 1)
{
flag = 0;
}
counter = 0;
}
The result is that just it doesn't work.. something is not working
You take the least significant digit and check if it is present in the rest of the number. If it is found, you're done. If it is not found, you divide the number by 10 and repeat the process. Example:
n = 123456789;
step 1: Is 9 present in 12345678
step 2: Is 8 present in 1234567
step 3: Is 7 present in 123456
.. and so on ..
So first you write a function that can tell whether a number contains a specific digit. The function could look like:
int contains_digit(int number, int digit)
{
while(number)
{
if ((number % 10) == digit) return 0; // Return zero when found
number /= 10;
}
return 1; // Return one if not found
}
Then you call that function for all digits in the original number and tests the digit to the number divided by 10. For instance if the number is 1234, you call the function like:
contains_digit(123, 4)
contains_digit(12, 3)
contains_digit(1, 2)
That can be something like:
int main( void )
{
int n = 12434;
int flag = 1;
while(n && flag)
{
flag = contains_digit(n/10, n % 10);
n /= 10;
}
printf("flag is %d\n", flag);
return 0;
}