how to iterate over a number to get every other digit - c

For a homework program we are asked to check if credit card numbers are valid.
While I am fairly sure about how I want to solve this problem I am stuck with iterating over a creditcard number and getting every second digit.
I already know that I need to use modulo and division and I do get the second to last number, but I am lost at how to iterate over the rest of the numbers.
In the code is the code I used to check that I did indeed get the second to last number, and after that some code I tried to use to iterate over the complete number. Hope somebody could show me in the right direction!
long number = 378282246310005;
int digit;
int cc_number;
cc_number = number % 10;
digit = cc_number / 10;
printf("%i\n", digit);
while (number > 0)
{
digit += number % 10;
number /= 10;
printf("%li", number);
}
printf("\n");

Before your while loop you reversed the last digit and the remaining number.
number % 10 is the last digit, number / 10 is the remaining number.
Adding to digit doesn't make sense if the variable is intended to contain a single digit. (You may need to add the digits for a validity check.)
Example code to extract all digits and their positions:
#include <stdio.h>
int main(void)
{
long number = 378282246310005;
int digit;
int position = 0;
printf("%li\n", number);
while (number > 0)
{
digit = number % 10;
number /= 10;
printf("(%i) %i ", position, digit);
position++;
}
printf("\n");
return 0;
}
This prints
378282246310005
(0) 5 (1) 0 (2) 0 (3) 0 (4) 1 (5) 3 (6) 6 (7) 4 (8) 2 (9) 2 (10) 8 (11) 2 (12) 8 (13) 7 (14) 3
To select every other digit you could check position % 2 or toggle a variable between 0 and 1 in every loop cycle.
Edit:
Explanation as requested in ron_g's comment: "Why's it printing out the digits in reverse?"
The loop separates the last digit from the remaining part of the number, so it prints the last digit first. Then it repeats the same with the remaining part as long as the remaining number is not 0.
The answer keeps the original implementation from the question which is based on storing the number as a long int. In this case it is easier to start with the last digit. When the number would be stored as a string it would be easier to start with the first digit.
/* number is initially the whole number or the remaining part */
while (number > 0)
{
/* remainder of division by 10 is the last digit */
digit = number % 10;
/* division by 10 is the remaining part after cutting off the last digit */
number /= 10;
printf("(%i) %i ", position, digit);
position++;
}

Related

Pinpoint each digit within a given number of any length

I am trying to find each digit of a number entered by the user.
The length of the number is up to the user.
So far I have:
managed to limit what the user enters by using long long card, meaning they cannot enter more than about 18 or 19 characters and only numbers are accepted.
managed to get the first and last digit of that number, as well as the count of the number.
Now I wanted to:
specifically ask for no more than 16 digits max - > but it keeps saying undeclared identifier and am not sure where I go wrong
be able to identify each digit, i.e.:
53689
1st digit:5
2nd digit:3
3rd digit:6
etc.
I learned about modulus but I can't figure out how to tell it to stop at the 2nd last/3rd last digit.
I feel it's something really simple but how? especially if I don't know if the user enters 5 numbers or 15, otherwise I could say (repeat modulus x-1 times) or something like that.
Just for now, my code in case you see anything for #1.
Before I tried to limit the entry-conditions, it worked fine showing me card, card length and 1st,last digit.
#include <cs50.h>
#include <stdio.h>
//finding first 2 numbers and last number and checking what card type
int main(void)
{
int count = 0;
do
{
long long card = get_long_long("Enter your card number: ");
}
while (card ! = 0)
{
card = card / 10;
count++;
}
printf("Card number: %llu\n", card);
printf("Number of digits: %d \n", count);
firstdigit = card;
while (firstdigit >= 20)
{
firstdigit = firstdigit / 10;
}
printf("First digit = %d \n", firstdigit);
lastdigit = card % 10;
printf("Last digit= %d \n", lastdigit);
return 0;
}
info: Yes it is from CS50 credit, I can't understand the full exercise yet so I decided to take it apart and only learn how to write a program that analyses the number for first 2 digits and tells me what card type it is. To do so I'm trying to learn how to count every number on any given number length for practice, for me to actually understand this slowly, so please don't share a full answer to the credit problem.
I also haven't learned arrays or more complex solutions yet either.
As others have advised, "break the problem down into smaller pieces".
Here's an example of that approach. Instead of dealing with a massive number all at once, this 'segments' the number into the typical 4 sections embossed into a credit card. This might give you a start toward a solution...
int main() {
int count = 0;
long long card = get_long_long("Enter your card number: ");
long long cpy = card;
int blk4 = cpy % 10000; // 4 rightmost digits as int
cpy = cpy / 10000; // shift right
int blk3 = cpy % 10000; // next 4 digits as int
cpy = cpy / 10000; // shift right
int blk2 = cpy % 10000; // next 4 digits as int
cpy = cpy / 10000; // shift right
int blk1 = cpy % 10000; // leftmost 3-4 digits as int
printf( "Card number: %04d %04d %04d %04d\n", blk1, blk2, blk3, blk4 );
return 0;
}
Having shown that, please be advised that a credit card "number" is not a "number" in the usual sense. It is a string made-up only of digits. Trying to solve this CV50 problem with "integers" is going to lead to tears. It's time to learn about arrays of characters (even if every character is an ASCII digit)...

is there a way to use Arrays in this C problem?

I am doing this problem:
"We have a huge decimal number N. Write a program to determine the followings:
The number of digits in N.
Is N an even number?
The number of zeros in it.
Is N a multiple of 11? Note that we can determine if N is a multiple of 11 by checking the difference between the sum of the odd positioned digits and the sum of the even positioned digits. For example, 82375 is not a multiple of 11 because the sum of the even positioned digits is 2 + 7 = 9, and the sum of the odd positioned digits is 8 + 3 + 5 = 16, and the difference between 9 and 16 is 7, which is not a multiple of 11.
We will give you the number one digit per line. For example, if you get digits ‘1’, ‘2’, ‘3’, ’4’, ‘0’ in order, then the number is 12340. The number will not start with 0.
Input Format
The input has several lines. Each line has a digit. EOF indicates the end of input.
Output Format
Output the four answers above line by line. If the number is even output a 1; otherwise a 0. If the number is a multiple of 11 output a 1; otherwise output a 0.
Subtask
10 points: you can store the decimal number in an integer without overflow
10 points: the number of digits is no more than 32768, so you can store digits in an array
80 points: you will get MLE if you use array"
my code is:
#include <stdio.h>
#include <stdbool.h>
int digit(long n);
int is_even(int n);
int count_zeros(long n);
int is_multiple(long n);
int main() {
int digits = 0;
long x;
scanf("%ld", &x);
digit(x);
int even = is_even(x);
printf("%d\n", even);
printf("%ld\n",count_zeros(x));
printf("%ld\n", is_multiple(x));
}
int digit(long n)
{
int digits = 0;
while (n > 0) {
n /= 10;
digits++;
}
printf("%ld\n", digits);
}
int is_even(int n)
{
if (n % 2 == 0)
return true;
else
return false;
}
int count_zeros(long n)
{
int count = 0;
while (n > 0) {
n /= 10;
if (n %10 == 0)
count++;
}
return count;
}
int is_multiple(long n)
{
if (n % 11 == 0) {
return true;
}
else
return false;
}
Basically i dont know how to meet the problem's requirement, so I made a simpler version of the problem. Any clue on how to do this?
If you comment on this, please be nice, I am a beginner and people was rude in the past,if you have nothing important to say, do not be mean/do not comment.
Well, the first problem with your current version is it only reads one integer. However problem states that each digit is on a separate line. The first approach may be to just replace that scanf with a loop and keeping multiplying by 10 and accumulating until end of file. Then the rest of the program would work fine.
A more advanced approach will be to use an array to store the digits. An integer can hold a very limited number of digits whereas you are only bounded with the size of available memory using array.
So in the reading loop rather than storing digits in an integer, you can store digits in an array (which could be fixed size because an upper limit is given). But for the rest of the program you should change the calculation to use digits in the array instead of the regular integer arithmetic.

How to find first two digits in C

Hello I have code to find out the first two digits of a number and save them to a variable in C and the code only works for even length numbers. I need something that will work for both even and odd length numbers. The number I need for first2 is the first two numbers.
long long int input = 6789466321
first2 = input;
while(first2 >= 100)
{
first2 = first2 / 100;
}
Divide by 10 at a time instead of 100 so that you are only removing one digit each iteration.
A function to return the first 2 digits of a long given an input that is a positive number and at least 2 digits (e.g. 10 or above).
int getFirst2Digits(long input)
{
long local = input;
while (local >= 100)
{
local /= 10;
}
return local;
}

Explain code: positive integer conversion to other cardinal number, reverse order display

// Program to convert a positive interger another base
#include <stdio.h>
int main (void)
{
const char baseDigits[16] = {'0','1','2','3','4','5','6','7',
'8','9','A','B','C','D','E','F' };
int convertedNumber[64];
long int numberToConvert;
int nextDigit, base, index = 0;
// get the number and the base
printf ("Number to be converted?");
scanf ("%ld", &numberToConvert);
printf("Base?");
scanf ("%i",&base);
// convert to the indicated base
do {
convertedNumber[index] = numberToConvert % base;
++index;
numberToConvert = numberToConvert / base;
}
while (numberToConvert != 0);
//display the result in the reverse order
printf(" Converted number = ");
for (--index;index >= 0; --index) {
nextDigit = convertedNumber[index];
printf ("%c", baseDigits[nextDigit]);
}
printf("\n");
return 0;
}
I do not understand this code. How will it be able to show the reverse order? Especially the for statement inside the brackets. Why does --index appear twice? What's the meaning it and index >=0? What's the use of nextDigit?
for (--index;index >= 0; --index) {
nextDigit = convertedNumber[index];
printf ("%c", baseDigits[nextDigit]);
Another new question:""
Why we also should output a number at least? and so here with the do loop?""
(Because using scanf to read long integer number of formatted input symbols is %ld. Because even if the user's input is 0 ,we also should output a number
at least, so here with the do loop)
For example, consider a number n, that needs to be converted to binary.
Now, if the number n is divided multiple times, by 2, you acquire the binary representation of the number in reverse.For example,
Say n=4, then considering the loop, we find that, the number is stored as 001, in convertedNumber, which is basically the reverse of the binary representation of 4(100).
At the end of the conversion,index is incremented an extra time.For the n=4 case, index=3(2increments + an extra).
So, the for(--index;index>=0;--index) basically states that,
start for loop at index=2(--index(3)=2), loop until index>=0, decrement once after every loop.This would print out the "reverse" of the reverse.(in the n=4 case, 001 is printed as 100, which is binary 4).
Your code basically converts base10 "numberToConvert" to a required base number. I hope you know about this. You can read this for more information.
Now analyse the code.
do {
convertedNumber[index] = numberToConvert % base;
++index;
numberToConvert = numberToConvert / base;
}
while (numberToConvert != 0);
This code actually do the conversion and stores each digit of new base number as a different number in array.
Example: If input is 146 and you want to convert it to base 13 number, then
convertedNumber[0] = 3
convertedNumber[1] = 11
At the end of the conversion thread exits from while loop and index value will be 2.
Now it comes to the for loop.
for (--index;index >= 0; --index) {
nextDigit = convertedNumber[index];
printf ("%c", baseDigits[nextDigit]);
}
You need to print value at index 1 and index 0. So index value start with decrementing itself.
Please remember, the first statement in for loop is executed only once. So effectively, there is only one --index;per loop.
It finds the character to display for a given digit. Ex: for index[1]=10, it prints 'A' and index[0]=3, it prints '3'. So output is A3. This is done to do conversion from base 10 to any base from 2 to 16 (However, that check is not there! You need to add a check for user entered base and make sure it is [2, 16]).

I don't understand itoa() in K&R book

I am reading K&R; so far I'm doing well with it, but there is something in function itoa() which I don't understand. Here in itoa() they say they reverse the numbers themselves. For example 10 is 01 (they reverse the string):
void itoa(int n, char s[])
{
int i, sign;
if ((sign = n) < 0) /* record sign */
n = -n; /* make n positive */
i = 0;
do { /* generate digits in reverse order */
s[i++] = n % 10 + '0'; /* get next digit */
} while ((n /= 10) > 0); /* delete it */
if (sign < 0)
s[i++] = '-';
s[i] = '\0';
reverse(s);
return;
}
I don't understand how it reversed the number. Even though we are just doing n % 10 + '0' then its the following digit which 10 then 1 gets deleted then it goes to 0 right ? Or I don't get its logic ?
In the do-while loop, it is pulling the numbers off from behind (the least significant digit first). So, if you had the number -123456789, it processes the 9, then the 8, then the 7, etc.
So, when it hits the null-terminator (3rd to last line), you would have "987654321-", which is then reversed.
n % 10 gives 0 for n = 10, so after the loop, the string s contains 01.
The call to reverse() fixes this.
The algorithm determines the digits from least to most significant order. Because the total number of digits that will be generated is not known in advance, the correct position cannot be determined as they are generated - the least significant digit will be at the end, but the 'end' is not known. So they are buffered in the order they are calculated (reverse) and then the whole string is reversed to correct the ordering.
One way of avoiding this is to determine the length in advance:
decimal_digits = (int)log10( n ) + 1 ;
but on devices without an FPU (and some with very simple FPUs) that is likely to be a heavier task than string reversal.

Resources