-2
printf("Enter your Credit/Debit Card Number.\n");
scanf("%ld",&card_num);

while(card_num>0)
{
    count++;
    card_num = card_num/10;
}
printf("%d",count);

The above code contains a huge problem.

Let's assume if a card is starting with 0 then the loop will fail. And Count 1 less digit.

Meaning if it's a 15 digit card then it will show 14.

To solve this problem I made (while card_num> = 0) But the problem with this is it's going to infinite loop. Since 0/10 = 0 and it will go infinity Note: I am not allowed to use arrays.

Aditya
  • 23
  • 4
  • 11
    Treating sequence of digits like credit card number as integer is a bad idea. Read it as string and treat as string. – MikeCAT May 28 '21 at 12:53
  • 2
    What type is `card_num`? Credit card numbers can be 16+ digits which *will not fit in `int`*. Just treat it as a string as Mike says. – tadman May 28 '21 at 12:54
  • 2
    Ah, but you are not allowed to use arrays... Then one possible solution is reading characters one-by-one. Recursion may be useful to retain multiple data. – MikeCAT May 28 '21 at 12:54
  • Just like number in math doesn't have leading zeros, neither does number in computers. You can't have an `int` variable with the (decimal) value `012`, instead it's just `12`. – Some programmer dude May 28 '21 at 12:55
  • 2
    The problem is really your solution. If you use an integer type that is actually large enough to hold a 16 digit number, you can do the count as you describe; if the result is less than the number of expected digits, then you know how many leading zeros there are. (If you don't know the number of expected digits, you have a different problem.) The false limitation to not use an array is absurd. The data should be treated as a string. – William Pursell May 28 '21 at 13:14

2 Answers2

0

Also, I would like do it so:

#include <stdio.h>

int main(void)
{
    char singleChar;
    int count = 0;
    
    printf("Enter your Credit/Debit Card Number.\n");
    while((singleChar = getchar()) != '\n')
    {
        if (singleChar >= '0' && singleChar <= '9')
        {
            count++;
        }
    }
    
    printf("%d",count);
    return 0;
}

Shorter Version:

#include <stdio.h>

int main(void)
{
    char singleChar;
    int count = 0;
    
    printf("Enter your Credit/Debit Card Number.\n");
    while((singleChar = getchar()) != '\n')
    {
        //@Clifford wanna isdigit()
        if (isdigit(singleChar))
        {
            count++;
        }
    }
    
    printf("%d",count);
    return 0;
}

Output:

Enter your Credit/Debit Card Number.
00123
5

Enter your Credit/Debit Card Number.
0034567854378987
16
  • If The starting of Card number include 0 like 00123 it gives count as 3 instead of 5 – Aditya May 28 '21 at 13:23
  • I am bad at explaining my question. I sorry my english is also bad. But I was telling that if credit card start with 0 it doesn't work the counter variable. – Aditya May 28 '21 at 13:26
  • Suggest change `if (singleChar >= '0' && singleChar <= '9')` to `if( isdigit( singleChar ) )`. Also `while( (singleChar = getchar()) != '\n && singleChar != EOF)`. – Clifford May 28 '21 at 13:39
  • @Clifford EOF is only for End of file. Or why you want it also as check ? – MitnickCodeHelper May 28 '21 at 14:38
  • Because `stdin` can be redirected. If the input were in a file and you did `myprog – Clifford May 28 '21 at 14:55
  • @Clifford okay, but my version is not for that use case. The counter will be increase by every number in that file. We would not find each cardnumber in that file. This could will be count each number like dates or something else. I think wrong use case. – MitnickCodeHelper May 28 '21 at 15:12
  • You cannot tell how the user will use the code. For repeated automated testing for example it is highly likely that you would use redirection - and with a short input to test that use case. Moreover it is not your question - you do not know the use case. It is just a good habit to get into that's all. Advice only; I can't get that excited about it - I have seen others do so though. – Clifford May 28 '21 at 15:30
0

While storing a credit card number in an integer is a bad idea because it is not an arithmetic object, it is possible to do it by making leading zeros implicit - adding then only at presentation. For example:

printf( "%16.16llu", card_num ) ;

will print 16 digits with leading zeros.

In that case any value less than 10000000000000000 is valid:

#include <stdio.h>
#include <math.h>

int main()
{
    unsigned long long card_num = 0 ;
    
    printf( "Enter your Credit/Debit Card Number.\n");
    scanf( "%llu", &card_num ) ;
    
    int count = 16 ;
    
    if( card_num > 9999999999999999ULL )
    {
        count = (int)log10( (double)card_num ) + 1 ; 
    }
    
    printf("%d\n", count);
    printf( "%16.16llu", card_num ) ;
    return 0;
}

One issue with the above is that if a number is entered with leading zeros, but more than 16 significant digits, the leading zeros are not counted - the (int)log10( (double)card_num ) + 1 expression yields the number of significant digits. But if you are counting digits for validation, but leading zeros are valid then you need only test card_num <= 10000000000000000ull - the number of digits is irrelevant.

#include <stdio.h>
#include <stdbool.h>

#define MAX_CARD_NUM  9999999999999999ULL

int main()
{
    unsigned long long card_num = 0 ;
    bool card_valid = false ;

    while( !card_valid )
    {
        printf( "Enter your Credit/Debit Card Number.\n");
        int check = scanf( "%llu", &card_num ) ;
        card_valid = (check == 1 && card_num <= MAX_CARD_NUM ) ;
        
        if( !card_valid )
        {
            printf( "Invalid card number\n" ) ;
        }
    }

    printf( "%16.16llu", card_num ) ;
    return 0;
}

However while it is be possible to encode and store a card number in an integer, it does not make much sense for initial entry because you would normally want to check the user had explicitly entered the leading zeroes as they are important security information, and you cannot do that with integer entry. In which case you would do better to enter and validate a string and then if you wish, convert the string to an integer encoding:

#include <stdio.h>
#include <stdbool.h>
#include <ctype.h>
#include <stdlib.h>

#define CARD_NUM_LEN 16

int main()
{
    unsigned long long card_num = 0 ;
    bool card_valid = false ;
    char card_str[32] ;

    while( !card_valid )
    {
        printf( "Enter your Credit/Debit Card Number.\n");
        fgets( card_str, sizeof( card_str) - 1, stdin  ) ;

        card_valid = true ;
        int numlen = 0 ;
        for( numlen = 0; card_valid && 
                         card_str[numlen] != '\0' && 
                         card_str[numlen] != '\n'; numlen++ )
        {
            card_valid = isdigit( card_str[numlen] ) && numlen < CARD_NUM_LEN ;
        }
        card_valid = card_valid && numlen == CARD_NUM_LEN ;
        card_str[numlen] = '\0' ;
        
        if( !card_valid )
        {
            printf( "Invalid card number\n" ) ;
        }
    }

    printf( "String: %s\n", card_str ) ;

    // Convert validated string to integer
    card_num = strtoull( card_str, NULL, 10 ) ;

    // Present the integer version with leading zeros.
    printf( "Number: %16.16llu", card_num ) ;
    return 0;
}
Clifford
  • 88,407
  • 13
  • 85
  • 165