Validating a C - String (Numeric or Alphabetic)

Write a program that asks the user to enter a part number to order. The rules for creating a part number are as follows:

a) The first character must be an "A", "B", or "C".
b) The second and third characters must be numeric; their value when taken as a pair must be between 10 and 49 (inclusive).
c) The fourth character must be a lowercase letter.
d) The fifth and sixth characters must be numeric; their values when taken as a pair must be between 22 and 66 (inclusive).

Is array mapping the best way to validate my character? Is there a more convenient or effective way of validating it? Here I've done an example of me trying to solve part (a). Please help to check if I can improve on any part of my program.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <cctype>
#include <cstring>
#include <iostream>
using namespace std;

int main()
{
    //Variable declaration
    char firstText[2], firstChar[] = "ABC", fullPartCode[15];

    //Prompt user for first character
    cout << "You are required to enter a part number to order." << endl;
    cout << "Please enter the first character." << endl;
    cin >> firstText;

    //Initialize boolean to false as default
    bool arr[strlen(firstText)] = {false};

    //Validating first character
    for (int i = 0; i < strlen(firstText); i++)
    {
        for (int j = 0; j <strlen(firstChar); j++)
        {
           if (firstText[i] == firstChar[j])
           {
               arr[i] = true;
               strcpy(fullPartCode, firstText);
           }
        }

        //Displays error message if first character is invalid
        if (arr[i] == false)
        {
            cout << endl << "The part code is invalid." << endl;
        }
    }

    //Displays the full part code
    cout << endl << fullPartCode << endl;

    return 0;
}
Last edited on
If I try to enter 2 alphabets, this is my output. It should display the error message once as well since the program has to only accept 1 alphabet, not 2, but it doesn't do it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
You are required to enter a part number to order.
Please enter the first character.
AB

The part code is invalid.

The part code is invalid.

The part code is invalid.

AB╕■"

Process returned 0 (0x0)   execution time : 2.277 s
Press any key to continue. 


How should I correct my program?
Last edited on
I would recommend you retrieve a string from the user, then validate that string to insure it meets the requirements of the assignment.

Your program has several problems as written. First you're probably overflowing your array bounds and your variable names are misleading.

char firstText[2], firstChar[] = "ABC", fullPartCode[15];
Remember that firstText can hold at most a single character supplied by the user. The variable firstChar[] holds a const C-string not a single char like it's name would suggest.

You should never use a method to retrieve a C-string that doesn't limit the number of characters retrieved to avoid buffer overflow problems, I suggest using istream.getline() instead of the extraction operator.

You are too quick to use loops - they aren't useful here.

If using c-strings, get a 6-character array from the user and test the individual characters or pairs of characters as required. Since (b) and (d) do essentially the same thing (with different parameters) you could usefully write a short function here.

You will find many character functions that do immediately what you want; e.g. isdigit(), islower() etc - look these up.
Thank you for your advices, I'll certainly look up isdigit and islower character function
So in the beginning I would have to get the whole string from the user instead of asking the user for the characters one by one? Then after retrieving the entire string, I have to validate each character type one by one? So in order to do that I would have to initialize the position where the character is then validate it according to its requirement?
Last edited on
It is entirely up to you whether you get the whole character array in one go, or character by character - you can do it either way.

If the whole was entered in one go, say as char array part[] then, remembering the the array index starts at [0]:
part[0] is tested to be 'A', 'B' or 'C';
part[1] and part[2] are tested to be numerical digits and, after conversion to a 2-digit number must lie between 10 and 49 (many ways of achieving this)
part[3] must be lower case;
part[4] and part[5] are tested to be numerical digits and, after conversion to a 2-digit number, must lie between 22 and 66.

Alternatively, you can enter the characters (possibly integer for the 2nd and 4th case) and you do the same test.

You can do it either way and it is entirely up to you. I can't, however, see anywhere loops would be particularly beneficial.
The code runs but there are a couple of problems, the validation for my second/third character and fourth/fifth character for the numeric number doesn't validate correctly. For example,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

You are required to enter a part number to order.

The first character of the part code has to be an 'A', 'B', or 'C'
The second and third character of the part code has to be
numeric (10 to 49 (inclusive)).
The fourth character must be a lowercase letter.
The fifth and sixth character must be numeric (22 to 66 (inclusive)).

After reading the terms above, please enter the part code accordingly.
A09a11


The full part code is A09a11

Process returned 0 (0x0)   execution time : 6.318 s
Press any key to continue.


By right, it is suppose to display the error message. This is my code for it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68

#include <cctype>
#include <cstring>
#include <iostream>
using namespace std;

int main()
{
    //Variable declaration
    char fullPartCode[6];

    //Prompt user for part code
    cout << "You are required to enter a part number to order." << endl;
    cout << endl << "The first character of the part code has to be an 'A', 'B', or 'C'" << endl;
    cout << "The second and third character of the part code has to be \nnumeric (10 to 49 (inclusive))." << endl;
    cout << "The fourth character must be a lowercase letter." << endl;
    cout << "The fifth and sixth character must be numeric (22 to 66 (inclusive))." << endl;
    cout << endl << "After reading the terms above, please enter the part code accordingly." << endl;
    cin >> fullPartCode;

    //Validation for first character
    if (fullPartCode[0] != 'A' && fullPartCode[0] != 'B' && fullPartCode[0] != 'C')
    {
        cout << endl << "ERROR: The first character of the part code has to be an 'A', 'B', or 'C'" << endl;
        return 0;
    }

    //Validation for second character
    if (fullPartCode[1] < 1 && fullPartCode[1] > 4)
    {
        cout << endl << "ERROR: The second and third character of the part code has to be numeric (10 to 49 (inclusive))." << endl;
        return 0;
    }

    //Validation for third character
    if (!isdigit(fullPartCode[2]))
    {
        cout << endl << "ERROR: The second and third character of the part code has to be numeric (10 to 49 (inclusive))." << endl;
        return 0;
    }

    //Validation for fourth character
    if (!islower(fullPartCode[3]))
    {
        cout << endl << "ERROR: The fourth character must be a lowercase letter." << endl;
        return 0;
    }

    //Validation for fifth character
    if (fullPartCode[4] < 2 && fullPartCode[4] > 6)
    {
        cout << endl << "ERROR: The fifth and sixth character must be numeric (22 to 66(inclusive))." << endl;
        return 0;
    }

    //Validation for sixth character
    if (fullPartCode[5] < 2 && fullPartCode[5] > 6)
    {
        cout << endl << "ERROR: The fifth and sixth character must be numeric (22 to 66(inclusive))." << endl;
        return 0;
    }

    //Display part code
    cout << endl << endl << "The full part code is " << fullPartCode << endl;

    return 0;
}
Last edited on
You haven't performed the two-character numerical tests correctly.

Problem 1 - you don't check whether fullPartCode[1] is a numerical digit. (Similarly later with fullPartCode[4].)

Problem 2 - you haven't converted your two-character pairs to integers, to see if they lie between 10 and 49 (or 22 and 66). You have tried to compare characters with integers in lines 29 and 50 - although characters do have integer representations they are not the ones you think here and these comparisons are inappropriate.

You need to think how to convert a character pair, say cd, to a number, which you can then compare with the required range. There are many ways of doing it and I would like to see you try it first.
Plus let's not forget that you're overflowing the bounds of your array if you enter a correctly formatted string.

Plus even if your array was large enough to hold the string you still have a buffer overflow waiting to happen. You should never use a method to extract a C-string that doesn't limit the number of characters it will try to retrieve. I really recommend you use getline() instead of the extraction operator.

It may also be easier to convert the "numbers" to integers to do the comparison. This is fairly easy since the location of these "numbers" are at a fixed position in your string. Something like:

1
2
    // Validation for the first number.
    int value_to_validate = atoi(&fullPartCode[1]);


Here I'm passing the address of the starting location of that first "number" to atoi() which will convert that part of the string to an integer.

You may also want to check the length of the string, before anything else, if it is not the correct length there is no reason to check the rest for the rest of the entries.

Since every character is actually represented by an integer, corresponding to its position in the character sequence, you can get the integer represented by a digit character c as
c - '0'.
Thus, if you want the two-digit decimal number represented by characters c and d just set
int n = 10 * ( c - '0' ) + ( d - '0' );

An alternative method is to use sscanf() to get digits from a c-string, or use atoi() as @jlb suggests.

There are plenty of other methods.
Okay I'll look into the problem. Thank you for your help once again lastchance and jlb
Topic archived. No new replies allowed.