I'm trying to create a program which asks for a 13-16
digit credit card number, and re-prompts if the user enters non-numerical values. So far my program works when I enter 16
digit values; however, it re-prompts if I enter anything less.
How do I get my program to accept a minimum of 13
digits and max of 16
digits?
#include <stdio.h>
#include <cs50.h>
#include <stdlib.h>
int main(void)
{
long cn;
char buf[18], *endptr;
do
{
printf("card number please: ");
fgets(buf, 17, stdin);
cn = strtol(buf, &endptr, 0);
} while (*endptr != '\0' || endptr == buf);
printf("%ld\n", cn);
}
You can use strcspn
to locate the end of the char
array in the while
condition, you can return the size of the char
array till it finds '\0'
(or '\n'
since you don't seem to be removing it from the array), you can then use this to set a minimum size for the input.
#include <string.h>
//...
do{
//...
while (strcspn(buf, "") < 14); //less than 13 chars will repeat the cycle
//...
You could also remove the '\n'
from buf
, in which case you can use strlen
:
//...
do{
fgets(buf, 17, stdin);
buf[strcspn(buf, "\n")] = '\0';
while (strlen(buf) < 13); //by removing '\n' you can use strlen
//...
The max size of buf
will be 16
because you limit the size in fgets
to 17
, so it will store 16
characters plus the null-terminator, you can reduce the size of your array to 17
, since the 18th
element is useless.
Also be aware that long
is not always 8 bytes, https://en.wikibooks.org/wiki/C_Programming/limits.h
This being said, there is an inherit problem with the code, it consumes everything, aphabetic caracters, spaces, etc., so if you have an input of 1234 1234 1234 1234
, only 1234
will be converted by strtol
.
In theexample below I'm removing everything that is not a digit and maintaining all your other specs:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int main()
{
long long cn; //long long is never smaller than 8 bytes
int i, c;
char buf[17];
do {
i = 0;
printf("card number please: ");
while ((c = fgetc(stdin)) != '\n' && c != EOF && strlen(buf) < 17) //max size 16
{
if (isdigit(c)) //only digits
buf[i++] = c;
}
buf[i] = '\0';
} while (strlen(buf) < 13); //min size 13
cn = strtoll(buf, NULL, 10); //strtoll for long long
printf("%lld\n", cn);
}
If we're specifically talking about credit card numbers, you might want to enforce it only by the number of digits the user enters and not the number of total characters since credit card numbers are often entered with spaces or dashes between them.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int numberofdigits(char *str)
{
int i = 0, n = 0;
while(str[i])
{
n += !!(isdigit(str[i]));
i++;
}
return n;
}
int main()
{
char str[100];
int digits;
do
{
printf("Enter a credit card number: ");
fgets(str, 100, stdin);
digits = numberofdigits(str);
printf("Read %d digits.\n", digits);
}
while((digits < 13) || (digits > 16));
printf("Thanks for entering \"%s\"\n", str);
return 0;
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.