C-String : incompatibility between char and const char *

I'm doing a code with only C-String. This code is about to check if the password that the user input is correct in the following format: mmmDDYY.fl

mmm - three lowercase characters for month, e.g. "mar" is March (you don’t need to verify that it’s an actual month, just three lowercase characters)
DD - two digits for day
YY - two digits for year
. - a period
fl - two lowercase characters for first and last initials

On line 23 , I get the following error : Can you give me a further (better) explanation on that and how can I fix this? I have been reading things online since but not really understanding. Once I fix this I was about to use the same principle to check for YY.

Also, on line 27, I get the error :
Can you give me a further (better) explanation on that and how can I fix this?

So I have 2 error, I'm trying to fix.

Here's the code :

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
#include <iostream> // preprocessor directive //
#include <cstring>
#include <cstdlib>
using namespace std;

int main()
{
    const int maxChars = 128;
    char password[maxChars];
    int dFirstDigits, dSecondeDigits;

    cout << "Enter the password : \n";
    cin >> password; //nov1498.st password i'm testing

    //check if the first three character are lowercase
    if (!islower(password[0]) || !islower(password[1]) || !islower(password[2]))
    {
        cout << "The password format is not correct.\n";
        return 1;
    }

    //converting character of password of index 3 and 4 to int and then check if they are digits
    dFirstDigits = atoi(password[3]); // error here
    

    //check if the character on index 7 is a "." (period)
    if (password[7] != ".") // error here too
    {
        cout << "The password format is not correct.\n";
    }

    //check if the last two characters are in lowercase.
    if (!islower(password[8]) || !islower(password[9]) || !islower(password[2]))
    {
        cout << "The password format is not correct.\n";
        return 1;
    }

    return 0;
}


Last edited on
Line 23: atoi needs at parameter a pointer to a c-string, not a single char. But with password[3] you give to it a single char.
So if you want to convert your c-string since the 4th character, you need to pass a pointer to the c-string, pointing to the 4th position in the c-string:
dFirstDigits = atoi( password + 3 );

Line 27: Here you have the opposite error, namely trying to compare a single char with a whole c-string.
Fix it by changing the double quotes by single quotes.
Last edited on
Apparently, when I do the change on line 23 :

1
2
dFirstDigits = atoi(password + 3);
    cout << dFirstDigits << "\n";


The cout gives me :


Enter the password : 
nov1498.st
1498


Why do I get char from index 3 to 6 instead of just the char of index 3?
I wanted to convert only the char of index 3 here.



Last edited on
dFirstDigits = password[3] - '0';
The double quotes are a shorthand for writing a C-string literal:
1
2
3
"." // is converts to array of two elements: {'.', 0}
'.' // is a single character
// 0, null, '\0' is not the same as printable character '0' 


As said, the atoi() takes a C-string. Not a single character. When you give it string "1498.st" it is able to convert the four first characters into number 1498.

The dFirstDigits = password[3] - '0'; uses the fact that the printable digit characters are consecutive in the ASCII table:
{ ..., '0', '1', '2', '3', '4', ... }

index_of( '2' ) - index_of( '0' ) is thus 2, etc
Last edited on
As you don't actually need the value of the numeric digits, just check that these are digits - like checking for lower case. Also you can check that the length of the entered password is 10 chars.

 
cin >> password;


When using this with a c-style string, please don't. This has buffer overflow issues.

For simple code, consider:

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
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cctype>
using namespace std;

int main()
{
	const int maxChars {128};

	char password[maxChars] {};

	cout << "Enter the password: ";
	cin.getline(password, maxChars);

	if (strlen(password) != 10) {
		cout << "The password format is not correct.\n";
		return 1;
	}

	//check for lowercase
	if (!islower(password[0]) || !islower(password[1]) || !islower(password[2]) || !islower(password[8]) || !islower(password[9])) {
		cout << "The password format is not correct.\n";
		return 2;
	}

	//check if the character on index 7 is a "." (period)
	if (password[7] != '.') {
		cout << "The password format is not correct.\n";
		return 3;
	}

	//check index 3 and 4 if they are digits
	if (!isdigit(password[3]) || !isdigit(password[4]) || !isdigit(password[5]) || !isdigit(password[6])) {
		cout << "The password format is not correct.\n";
		return 4;
	}

	cout << "The format is correct!\n";
}

Last edited on
1
2
3
4
> //check for lowercase
> if (!islower(password[0]) || ...
> //check index 3 and 4 if they are digits
> if (!isdigit(password[3]) || ...


Do not use functions from <cctype> (std::islower, std::isdigit etc.) with ordinary chars, particularly if they are read from input.

Like all other functions from <cctype>, the behavior of std::islower is undefined if the argument's value is neither representable as unsigned char nor equal to EOF. To use these functions safely with plain chars (or signed chars), the argument should first be converted to unsigned char
https://en.cppreference.com/w/cpp/string/byte/islower#Notes
In the example from cppreference I tried to output the character c and it printed garbage anyway.

That's considerably more "unsafe" than using functions like islower() with the default character type.
> In the example from cppreference I tried to output the character c and it printed garbage anyway.

It may not be a printable character in the particular locale.


> That's considerably more "unsafe" than using functions like islower() with the default character type.

No.
Topic archived. No new replies allowed.