2

すべてが正常に見え、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;
}
4

3 に答える 3

4

最初に行うことは、読み取ったデータを印刷することです。やってみましたか?64バイトの整数を使用すると、16桁のカード番号を処理できますが、入力形式はかなり厳密である必要があります。または、数字を文字列として読み取ることもできます(つまり、プログラムでオプションの句読点を使用できます。実際のクレジットカードで数字がグループ化されている場所にスペースやダッシュを入力できないのは非常に面倒です)。問題をデバッグするときは、プログラムが実際に処理している入力データが期待どおりであることを確認してください。

32ビットコンパイルを使用している場合は、問題があります。

  • コードを64ビットモードでコンパイルすると、サンプルのクレジットカード番号が有効であると識別されます。

  • コードを32ビットモードでコンパイルすると、サンプルのクレジットカード番号が無効として識別されます。(コンパイラを使用するマシンには、その上にコメントがありsizeof(long) == 4ます。32ビットモードでコンパイルするか、Windows 64ビットプラットフォームで64ビットモードでコンパイルするかのいずれかです。参照:onのビットサイズはいくつですか。 long64ビットWindows?

  • 10年以上前に書いたPerlスクリプトを使用したとき、サンプルCCNは有効であると識別されました。

  • scanf()32ビットモード(プログラムの修正バージョン)で読み取った値を印刷すると、次のようになります。

    $ ./ccn <<< 4388576018410707
    Enter credit card number Invalid card number -0000000089805613
    $
    

    これbashは、プログラムへの標準入力として文字列(数値)を供給するために特定の機能を使用しています。

奪うべき教訓

  1. お使いのコンピュータが数字の方法で何を処理できるかを知ってください。

  2. からの戻り値を確認してくださいscanf()

  3. ただし、それでもオーバーフローには役立ちません。テキストの行を文字列に読み込んでから、strtol()または相対を使用して変換を確認することをお勧めします。注意して、オーバーフローやアンダーフロー、無効な値などを見つけることができます。また、ユーザーが入力した内容を報告できますが、数値変換(または偽の数値変換)が失敗した場合、プログラムが見たものを報告することはできません。 。

  4. 入力データを印刷します。正の数を入力したときに出力に負の数が表示された場合は、問題がある理由がすぐにわかります。

  5. それが私のプログラムだったとしたら、入力を求める代わりにコマンドライン引数を処理することになります。


Perlの例:

$ 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
$

これにより、ユーザーフレンドリーで数字のグループをスペースまたはダッシュで区切ることができる表示形式と、コンピューターが処理できる内部操作形式(数字列)が区別されます。句読点なしで16桁の数字を入力させてはいけません。それはまったく文明化されていません(私が遭遇したすべてのWebサイトは句読点がないと主張しています)。16桁の数字を区切り記号でフォーマットするのに十分簡単な関数を書くことができます。

上記の関数は、ユーザーにデータを提示することを目的としたものではありません。問題が何であるかを識別しますが、プログラマーはエラーの処理方法を決定する必要があります。

于 2012-02-08T04:51:54.363 に答える
2

longは4バイトしかないため、最大で保存できます2,147,483,648

明らかに収まらない4,388,576,018,410,707を保管する必要があります。のような64ビット整数を使用しuint64_tます。

于 2012-02-08T03:47:23.563 に答える
0

intを使用できますlong long。少なくとも[-9223372036854775807、+9223372036854775807]の範囲を含むことができます

C99標準によると、long longは、少なくとも64ビット幅の整数型です。指定された2つの整数64ビットタイプがあります:long long intおよびunsigned long long int

于 2016-02-24T11:26:44.227 に答える