user3102359
user3102359

Reputation: 3

How do I validate this string in C++?

A person is asked to enter their credit card number, it has to have 16 digits, after every 4 digits, it has a space or -.

I have code to check if there are spaces or a hyphen as well as checking if that person entered letters instead.

The problem with this code is that: It says out of range when I enter letters and it also says the entry is correct when I entered less than what I set the length to be. Any ideas where I am going wrong?

#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;
    }

Upvotes: 1

Views: 1379

Answers (6)

user3127943
user3127943

Reputation: 15

You could try something like this...

If length not equal to 19 bool is false

for loop to count up to 19 or less than 20 if gets to 4 9 or 14th position add 1 to the count if position on count not equal digit then bool equals false close for loop

for loop counting up to 19 but in groups of five if positon of count not equal to what you require bool false close for loop

Upvotes: 0

driftwood
driftwood

Reputation: 2121

Your original code had a number of other issues.

I modified your code to get it to do what you want. Its not elegant but should work. It works for me.

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;

}

Upvotes: 0

driftwood
driftwood

Reputation: 2121

At the bottom, your test of the validcreditcardnum flag of validity is incorrect.

if(validcreditcardnum=true)

It should be if(validcreditcardnum == true). Otherwise you won't get the output messages "Credit card number is correct".

Upvotes: 0

Thomas Matthews
Thomas Matthews

Reputation: 57749

I suggest treating the credit card number as 4 numbers and not as a character string or set of character strings.

The C++ input functions will read characters, building a number, until a non-numeric character is found. This means that it will stop when it encounters the space or dash or hyphen between the number groups.

To verify that a group number is 4 digits in length, you check the range:

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

Reading a credit card number could be as simple as:

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;  

Upvotes: 0

Pete Becker
Pete Becker

Reputation: 76523

Think about how to separate this problem into simpler sub-problems. One obvious one is to check whether a std::string object begins with four digits. Another is to check whether an std::string object begins with a space or a dash. Write those two functions, and use them to validate the credit card number. If it starts with four digits, remove the four digits; then check whether it starts with a space or a dash, and if it does, remove the first character. Repeat until done.

Upvotes: 0

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 727137

This expression compiles, but it is incorrect:

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

The expression above is always true, because logical OR operator || treats all non-zero values as true.

You can rewrite your expression as follows:

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

Also, you are using the comma operator where it's not needed:

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

It is enough to write a check on any of the four variables, because they all increment at the same point. Consider rewriting this loop with a single index, and add an "offset" to it as you go (or use a nested loop for the offsets).

Upvotes: 2

Related Questions