2013-12-14 32 views
1

一個人被要求輸入他們的信用卡號碼,它必須有16位數字,每4位數字後,它有一個空格或 - 。如何在C++中驗證此字符串?

我有代碼來檢查是否有空格或連字符以及檢查該人是否輸入字母。

這段代碼的問題是: 才說的出來的範圍,當我輸入字母,它也表示該條目是正確的,當我進不到我設定的長度爲。 任何想法,我錯了嗎?

#include<iomanip> 
#include <iostream> 
#include<conio.h> 
using namespace std; 
int main() { 
    string creditcardnum; 
    bool validcreditcardnum; 

    do{ 
     validcreditcardnum=true; 
     cout << "Enter your credit card number\t Enter 4 numbers followed by a space or -\n\t\t"; 
     cin >> creditcardnum; 
     if(validcreditcardnum==false){ 
     cout<<"Your credit card number is invalid\n\t\t"; 
     } 
     if (creditcardnum.length()!=19){ 
     validcreditcardnum==false; 
     } 
     for(unsigned short a= 0,b=5, c=10, d=15; 
           a<=3,b<=8,c<=13,d<=18; 
           a++, b++, c++, d++){ 
     if(!isdigit(creditcardnum.at(a))&& 
       !isdigit(creditcardnum.at(b))&& 
       !isdigit(creditcardnum.at(c))&& 
       !isdigit(creditcardnum.at(d)) 
       ) 
      validcreditcardnum==false; 
      } 
      if(
       creditcardnum.at (4) !=' '||'-'&& 
       creditcardnum.at (9) !=' '||'-'&& 
       creditcardnum.at (14)!=' '||'-'){ 
      validcreditcardnum==false; 

      } 
      while(validcreditcardnum==false); 
      if(validcreditcardnum=true) 
       cout << "Credit card number is correct"; 
      return 0; 
    } 
+0

你要跟也應該看看了盧恩檢查驗證信用卡號碼:HTTPS://en.wikipedia .org/wiki/Luhn_algorithm – ldrumm

+0

我想說做這種驗證的最好方法是使用['std :: regex'](http://en.cppreference.com/w/cpp/regex),[ boost :: regex'](http://www.boost.org/doc/libs/1_55_0/libs/regex/doc/html/index.html)或者,如果你不能使用[tag:C++ 11 ]。 –

+1

這個'if'看起來很奇怪:'if(creditcardnum.at(4)!=''||' - '&& creditcardnum.at(9)!=''||' - '&& creditcardnum.at(14)! =''||' - ')' – Jigsore

回答

0

你原來的代碼有一些其他問題。

我修改了你的代碼,讓它做你想做的事。它不優雅,但應該工作。這個對我有用。

int main() 
{ 
string sCreditcardnum; 
char szCreditCardNum[100]; 
memset(szCreditCardNum, 0, sizeof szCreditCardNum); 
bool validcreditcardnum = true; 

do { 
    if(validcreditcardnum == false) { 
     cout << "The credit card number provided is invalid\n\n"; 
     validcreditcardnum = true; 
    } 

    cout << "Enter your credit card number\t Enter 4 numbers followed by a space or -\n\t\t"; 
    cin.getline(szCreditCardNum, 30); 
    sCreditcardnum = szCreditCardNum; 
    if (sCreditcardnum.length() != 19) 
     validcreditcardnum = false; 

    for(unsigned short a=0, b=5, c=10, d=15; 
     a<=3,b<=8,c<=13,d<=18; 
     a++, b++, c++, d++) 
    { 
     if(!isdigit(sCreditcardnum.at(a)) || 
      !isdigit(sCreditcardnum.at(b)) || 
      !isdigit(sCreditcardnum.at(c)) || 
      !isdigit(sCreditcardnum.at(d))) 
     { 
      validcreditcardnum = false; 
      break; 
     } 
    } 

    if((sCreditcardnum.at (4) != ' ' && sCreditcardnum.at (4) != '-') || 
     (sCreditcardnum.at (9) != ' ' && sCreditcardnum.at (9) != '-') || 
     sCreditcardnum.at (14) != ' ' && sCreditcardnum.at (14) != '-') 
    { 
     validcreditcardnum = false; 
    } 
} 
while(validcreditcardnum == false); 
if(validcreditcardnum == true) 
    cout << "Credit card number is correct"; 
return 0; 

} 
+0

這很好,很少有問題,memset做了什麼,爲什麼程序員使用char 100,我認爲char只針對單個字母。 – user3102359

+0

memset用於初始化內存。未初始化的內存塊可能包含垃圾。當使用字符緩衝區時,將它們初始化是非常重要的,因爲有許多依賴'\ 0'作爲分隔符的字符串函數。至於爲什麼我使用了100個字符緩衝區,我只是選了一個大於20的任意數字來讓你的程序工作。 100沒有什麼特別之處,只需要比想要讀取的字符串的大小更大,以便程序不會崩潰。 – driftwood

+0

char是一個可以存儲單個字符的8位類型。 char []是一個char類型的數組,可以存儲字符串。這兩種類型都是C/C++語言的內置部分。相反,「std :: string」不是內置的C++類型,但是是STL(標準模板庫)庫的一部分。 – driftwood

2

這個表達式編譯,但它是不正確:

creditcardnum.at (4) !=' '|| '-' && ... 

上面的表達式總是true,因爲邏輯OR運算符||將其視爲true所有的非零值。

你可以重寫你的表達如下:

creditcardnum.at (4) !=' ' && creditcardnum.at (4) !='-' && ... 

此外,您使用它是沒有必要的逗號操作符:

for(unsigned short a= 0,b=5, c=10, d=15; 
          a<=3,b<=8,c<=13,d<=18; // <<== Here 
          a++, b++, c++, d++) 

這足以寫支票上的任何四個變量,因爲它們都在同一點增加。考慮用單個索引重寫這個循環,並且在你去時添加一個「偏移量」(或者爲偏移量使用嵌套循環)。

+0

現在一切正常,它在空間中也缺少一個getline,沒有你提到的額外的逗號操作符,它不會編譯,剩下一個問題,爲什麼字符串說出來當我輸入文字 – user3102359

+0

@ user3102359你輸入了什麼文字? (使用反向單引號「'來分隔文本以保持輸入狀態)。 – dasblinkenlight

+0

Twoproblems :(如果我輸入字母,它說超出範圍,如果我輸入4個字母和所有數字,它說正確的條目 – user3102359

0

想想如何將這個問題分成更簡單的子問題。一個明顯的問題是檢查std::string對象是否以四位數開頭。另一種方法是檢查std::string對象是以空格還是破折號開頭。寫這兩個函數,並用它們來驗證信用卡號碼。如果它以四位數字開頭,則刪除四位數字;然後檢查它是以空格還是短劃線開頭,如果是,則刪除第一個字符。重複,直到完成。

0

我建議將信用卡號碼視爲4個數字,而不是字符串或字符串集合。

C++輸入函數將讀取字符,構建一個數字,直到找到一個非數字字符。這意味着它會在遇到空格或數字組之間的連字符或連字符時停止。

要驗證組號的長度是4個位數,你檢查的範圍:

if ((group_number > 999) && (group_number < 10000)) 
{ 
    // group number has 4 digits 
} 

閱讀信用卡號碼可能是簡單的:

int group1; 
int group2; 
int group3; 
int group4; 
cin >> group1 >> group2 >> group3 >> group4; 
if (group1 < 0) group1 *= -1; // Turn into a positive number 
if (group2 < 0) group2 *= -1; 
if (group3 < 0) group3 *= -1; 
if (group4 < 0) group4 *= -1; 
+0

這是一個聰明的方法,謝謝。 – user3102359

0

在底部,您對validcreditcardnum有效性標誌的測試不正確。

if(validcreditcardnum=true) 

它應該是if(validcreditcardnum == true)。否則,您將無法獲得輸出消息「信用卡號碼正確」。

+0

剛剛嘗試過,它仍然總是返回true,如果我在字符串中輸入數字和字母,它說的是正確的。例如,1234-wrer-1231-abcd – user3102359

+0

我剛剛發佈了一個適用於我的代碼的修改版本,請查看。 – driftwood

0

你可以嘗試這樣的事情......

如果長度不等於19 布爾是假

for循環數到19或小於20 如果獲取到4 9或14位加1計數 如果計數不等於位的位置,然後 布爾等於false 收盤循環

for循環計數用p來19,但在五 組如果計數不等於你需要 布爾假 接近for循環的當前位置