Вопрос

Welcome. I have two problems. Firstly - function size bool (const char * pass) to check whether the amount of the chars inside of string is at least 8, but there is something wrong. Its always showing that there is minimum 8 chars, even is string contain only 3 chars.

My job is to create several small functions for checking the correctness of the entered string of chars. Can You help you with this one? If all small functions inside of bool check(...) return true i need to write in the console "STRING IS OKAY".

I will be grateful for any suggestions.

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

    //Check the amount of chars
    bool size (const char* pass){
        if(sizeof(pass) > 7)
                        return true;
    }

    //Checks if the ASCII are located between 32 to 126
    bool isPrint (const char* pass){
        for(int x=0; x <= sizeof(pass); x++){
            if(isprint(pass[x]))
                return true;
        }
    }


    //Check the amount of numbers
    bool isNum (const char* pass){
        for(int x=0; x <= sizeof(pass); x++){
            if(isdigit(pass[x]))
                return true;
        }
    }

    //Check the amount of Upper letters
    bool isUpperLetter (const char* pass){
        for(int x=0; x <= sizeof(pass); x++){
            if(isupper(pass[x]))
                return true;
        }       
    }

    //Check the amount of lower letters
    bool isLowerLetter (const char* pass){
        for(int x=0; x <= sizeof(pass); x++){
            if(islower(pass[x]))
                return true;
        }       
    }

    //Check the amount of Punctuation Marks
    bool isPunctMark (const char* pass){
        for(int x=0; x <= sizeof(pass); x++){
            if(ispunct(pass[x])){
                return true;
            }
        }       
    }


    //All small moduls together
    bool check (const char* pass){
        size(pass);
        isPrint(pass);
        isNum(pass);
        isUpperLetter(pass);
        isLowerLetter(pass);
        isPunctMark(pass);
    }

    int main() {
        char x;
        cout << "Enter the string of characters" << endl;
        cin >> x;
        const char *password = &x;
        check(password);
    }
Это было полезно?

Решение

sizeof(pass) returns the size of the pointer. Which is implementation specific, and if your function is always returning true, we can guess that sizeof(char*) is 8, implying you have a 64-bit system.

On many other systems, it will return 4, or may even return 2 or 1, dependant on the architecture.

You probably want to check the length of the string the pointer is pointing to like so:

int len=strlen(pass);
if(len>=8)   //Check for >=8 is clearer than >7)
{
   return true;
}

You could also iterate over the string and check for null. But why bother when there is a nice std library routine that does the job.

to run all checks, do something like

bool isValid(const char* const pass)
{
     if(!isPrint(pass))
     {

         return false;
     }
     if (!isNum(pass))
     {
         return false;
      }
     //etc
 }

You could also have a big long

if(isPrint(pass)&&isNum(pass) .....)
{
    return true;
}

but that would be messier, and harder to debug.

Другие советы

sizeof gives you the size of the type of the object passed to it. It is evaluated strictly at compile time. You are passing it a const char *, which is 8 on 64 bit systems.

To get the length of a C-style string, you can use the C function strlen, in the header <cstring>.

That said, I would recommend not doing this. I would recommend moving away from C strings to C++ std::strings, because they are much easier to use correctly.

Now as it is, you are very much using C strings INcorrectly!

int main() {
    char x;
    cout << "Enter the string of characters" << endl;
    cin >> x;
    const char *password = &x;
    check(password);
}

You read a single char (x), then take its address and treat this as a C string. Now there are two significant problems here.

First, you probably meant to read more than one character.

Second, you will hit undefined behaviour, and your computer may well blow up, because C strings are supposed to be a pointer to a NUL-terminated array of char. Any functions that expect a C string will loop through look for an ending '\0', which x does not have, since it is not even an array in the first place.

So, if you use std::string from the <string> header, you can have much safer code, without all this faffing with pointers, NUL-terminators, and such.

(untested)

// one of your functions for example
bool isUpperLetter (const std::string& s){
    for(int x=0; x < s.size(); ++x){ // Use <, not <=. C++ uses 0-indexing.
        if(isupper(s[x]))
            return true;
    }
    return false; // you forgot this!
}


int main() {
    std::string s;
    std::cout << "Enter a string:\n";
    std::cin >> s;

    isUpperLetter(s);
}

By the way, this won't work if your input string contains spaces, but one thing at a time!

(Next steps if you learn fast: Read up on std::getline and the <algorithm> header. std::count_if looks very relevant.)

And while we're at it, kill bad habits early, and read up on why you should avoid using namespace std; and std::endl.

EDIT

From your comment, you are stuck with the signature bool check(const char*), so I guess you are supposed to be learning about how to work with C strings. Let's for the moment assume your instructors know what they are doing.

Then the normal way to loop through a C string is with a pointer, checking for '\0'. So for instance, to count the number of uppercase letters (and really, you don't write it this way for real code. Or at least, if you tried to on a project I was working on I would strongly suggest you fix it):

int countUppercase (const char* c)
{
    if(NULL==c) return 0;

    int count = 0;
    for ( ; '\0' != *c ; ++c ) // loop while not found the NUL
    {
        if (isupper(*c))
            ++count;
    }

    return count;
}

I still strongly recommend reading into a std::string if you can get away with it. If not, you're next best bet is probably std::istream::getline.

You are checking the sizeof(pass), which is size of const char*. You should iterate over the array and chack for str[i]=='\0' instead.

EDIT: As suggested, you can also use strlen() function instead.

As there was already mentioned you use sizeof pointer in loops of your functions instead of the actual length of the passed string. Moreover sometimes comments before functions do not correspond what they do or have to do. For example

//Check the amount of numbers
bool isNum (const char* pass){
    for(int x=0; x <= sizeof(pass); x++){
        if(isdigit(pass[x]))
            return true;
    }
}

In the comment there is written "check the amount of numbers". I think you should return number of digits in the given string.

So I would rewrite the function the following way

//Check the amount of numbers
size_t DigitCount ( const char* pass )
{
    size_t count = 0;

    for ( ; *pass; ++pass )
    {
        if ( isdigit( *pass ) ) ++count;
    }

    return count;
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top