C:信用卡号检查器/Luhn';s算法

C:信用卡号检查器/Luhn';s算法,c,credit-card,luhn,C,Credit Card,Luhn,一切看起来都很好,似乎遵循Luhn的算法,但当我输入自己的信用卡号码或本应有效的样本号码:4388576018410707时,它仍然返回为无效 有人能找到问题吗 #include <stdio.h> int isvalid(long num); int sumofdoubleevenplace(long num); int getdigit(int num); int sumofoddplace(long num); int prefixmatched(long num,int d

一切看起来都很好,似乎遵循Luhn的算法,但当我输入自己的信用卡号码或本应有效的样本号码:4388576018410707时,它仍然返回为无效

有人能找到问题吗

#include <stdio.h>

int isvalid(long num);
int sumofdoubleevenplace(long num);
int getdigit(int num);
int sumofoddplace(long num);
int prefixmatched(long num,int d);
int getsize(long d);
int getprefix(long num,int k);

main(){
  long cardnum=0;
  printf("Enter credit card number ");
  scanf("%ld",&cardnum);
  if(isvalid(cardnum)==1)
    printf("Valid card number\n");
else
    printf("Invalid card number\n ");
return 0;
}

int isvalid(long num){
if(((sumofoddplace(num)+sumofdoubleevenplace(num))%10==0)
   && (getsize(num)<=16 && getsize(num)>=13)
   && (prefixmatched(num,4)==1 || prefixmatched(num,5)==1 ||
       prefixmatched(num,6)==1 || prefixmatched(num,37==1)))
    return 1;
else
    return 0;
}

int sumofdoubleevenplace(long num){
int numdigits=getsize(num)-1;
int sum=0,i;
num/=10;
for(i=0;i<numdigits;i+=2){
    sum+=getdigit((int)(2*(num % 10)));
    num/=100;
}
return sum;
}

int getdigit(int num){
return ((num-num%10)/10)+num%10;
}

int sumofoddplace(long num){
int numberofdigits=getsize(num);
int sum=0,i;
for(i=0;i<numberofdigits;i+=2){
    sum+=num%10;
    num/=100;
}
return sum;
}

int prefixmatched(long num,int d){
if(getprefix(num,getsize(d))==d)
    return 1;
else
    return 0;
}

int getsize(long d){
int n=0;
while(d!=0){
    d/=10;
    n++;
}
return n;
}

int getprefix(long num,int k){
int numberofdigits=getsize(num);
int i;
if(numberofdigits-k>0){
    for(i=0;i<numberofdigits-k;i++){
        num/=10;
    }
    return num;
}
else
    return num;
}
#包括
int是有效的(long num);
int sumofdoubleevenplace(长数值);
int getdigit(int num);
int sumofoddplace(长数值);
int prefixmatched(长num,int d);
int getsize(长d);
int getprefix(long num,int k);
main(){
长cardnum=0;
printf(“输入信用卡号”);
scanf(“%ld”、&cardnum);
if(isvalid(cardnum)==1)
printf(“有效卡号”);
其他的
printf(“无效卡号”);
返回0;
}
int是有效的(长num){
if(((sumofoddplace(num)+sumofofdoubleevenplace(num))%10==0)
&&(getsize(num)=13)
&&(prefixmatched(num,4)==1 | | prefixmatched(num,5)==1||
prefixmatched(num,6)==1 | | prefixmatched(num,37==1)))
返回1;
其他的
返回0;
}
int sumofdoubleevenplace(长数值){
int numdigits=getsize(num)-1;
int sum=0,i;
num/=10;

对于(i=0;i,由于长度只有4个字节,它最多只能存储2147483648


您需要存储4388576018410707,这显然不适合。请使用64位int,如
uint64\u t

首先要做的是打印您读取的数据;您尝试过了吗?使用64字节整数,您可以处理16位卡号,尽管输入格式必须非常严格。或者,您可以将数字作为strin读取g(这意味着您的程序可以允许使用可选标点符号;我发现网站不允许您在实际信用卡上的数字分组处键入空格或破折号,这非常令人讨厌)。调试问题时,请检查程序实际使用的输入数据是否与您预期的一致

如果使用32位编译,则会出现问题

  • 在64位模式下编译代码后,示例信用卡号被标识为有效

  • 当您的代码以32位模式编译时,示例信用卡号被标识为无效。(上面有一条注释,说明在您的计算机上使用编译器时,
    sizeof(long)==4
    。您是以32位模式编译,还是在Windows 64位平台上以64位模式编译。请参阅:)

  • 当我使用十多年前编写的Perl脚本时,示例CCN被标识为有效

  • 当我以32位模式(程序的修改版本)打印出scanf()读取的值时,我得到:

    这就区分了用户友好的表示格式(允许空格或破折号分隔数字组)和内部操作格式(计算机可以处理的数字字符串)。不应该让人们在没有标点的情况下键入16位数字,这是完全不文明的(尽管我遇到的每个网站都坚持不使用标点符号),但您可以很容易地编写一个函数,将16位数字格式化为带分隔符的数字


    上面的函数不是用来向用户显示数据的-它确实确定了问题所在,但程序员必须决定如何处理错误。

    您可以使用int
    long
    。它至少能够包含[−9223372036854775807,+9223372036854775807]范围


    根据标准,long-long是一种至少64位宽的整数类型。指定了两种64位整数类型:
    long-long-int
    unsigned-long-int

    该代码适用于您提供的卡号和我自己的信用卡。它返回“invalid number”不管我输入了什么。它可能是编译器特有的东西吗?可能是。你有没有按照用户Pubby的建议检查长的大小?长的大小是4字节。这意味着什么?因为你的代码是不可移植的-它假设
    long
    是64位的,但在你的系统上是32位的。使用正确的类型:
    uint64\u t
    。哪个标题下是“uint64\u t”?
    $ ./ccn <<< 4388576018410707
    Enter credit card number Invalid card number -0000000089805613
    $
    
    $ perl -MBRPS -e 'my($x, $y) = validate_account("4388-5760-1841-0708"); print "$x : $y\n";'
     : check digit on account number is incorrect
    $ perl -MBRPS -e 'my($x, $y) = validate_account("4388-5760-1841-0707"); print "$x : $y\n";'
    4388576018410707 : ok
    $ perl -MBRPS -e 'my($x, $y) = validate_account("4388576018410707"); print "$x : $y\n";'
    4388576018410707 : ok
    $ perl -MBRPS -e 'my($x, $y) = validate_account("4388 5760 1841 0707"); print "$x : $y\n";'
    4388576018410707 : ok
    $ perl -MBRPS -e 'my($x, $y) = validate_account("4388 57601841 0707"); print "$x : $y\n";'
     : invalid punctuation pattern
    $