2013-11-01 1 views
1

Добро пожаловать. У меня две проблемы. Во-первых - размер функции bool (const char * pass), чтобы проверить, не превышает ли количество символов внутри строки не менее 8, но что-то не так. Он всегда показывает, что минимально 8 символов, даже строка содержит всего 3 символа.Как проверить, какие функции возврата и правильно рассчитать символы

Моя задача - создать несколько небольших функций для проверки правильности введенной строки символов. Можете ли вы помочь вам с этим? Если все маленькие функции внутри проверки bool (...) возвращают true, мне нужно написать в консоли «STRING OKAY».

Буду благодарен за любые предложения.

#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); 
    } 
+0

Вы получаете размер указателя, который, вероятно, '8' на вашей системе. Вероятно, вы хотите ['strlen'] (http://en.cppreference.com/w/cpp/string/byte/strlen) или еще лучше [' std :: string'] (http: //en.cppreference .com/ж/CPP/строка/basic_string). – BoBTFish

+0

Ваша строка символов считывается в 'char', который отлично до тех пор, пока вы ожидаете только одного символа. Вы не можете использовать 'strlen' на одном' char', потому что это не '\ 0' завершено. Используйте 'std :: string'. – mars

+0

Я не уверен, почему вы получили downvoted .... Вопрос соответствует правилам сайта. Вы опубликовали код, у вас была проблема с проблемой ... Может быть, эти средства, достаточные для downvote, могут комментировать и объяснять. – mjs

ответ

4

sizeof(pass) возвращает размер указателя. Это специфично для реализации, и если ваша функция всегда возвращает true, мы можем предположить, что sizeof(char*) - это 8, подразумевая, что у вас 64-разрядная система.

Во многих других системах он вернет 4 или может даже вернуть 2 или 1, в зависимости от архитектуры.

Вы, вероятно, хотите, чтобы проверить длину строки указатель, указывающий так:

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

Вы также можете итерацию по строке и проверить на нуль. Но зачем беспокоиться, когда есть хорошая стандартная программа std, которая выполняет эту работу.

для выполнения всех проверок, сделать что-то вроде

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

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

Вы могли бы также иметь большой длинный

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

но это будет грязнее и сложнее для отладки.

+0

Ранний утренний мозг пердеть. Исправленный. (Полагает, что он работает над 8-битным микро. Который будет ложью) – mjs

+0

Хорошо, спасибо! А как насчет второго вопроса? как проверить, возвращаются ли все функции true? –

+0

@mjs LOL, справедливо. –

2

Вы проверяете sizeof(pass), который является размером сопзИте полукокс *. Вы должны перебирать массив и chack вместо str[i]=='\0'.

EDIT: Как и было предложено, вы также можете использовать функцию strlen().

+2

Зачем это делать, когда вы можете использовать ['strlen'] (http://en.cppreference.com/w/cpp/string/byte/strlen)? (что, скорее всего, очень сильно оптимизировано, но больше не переписывать его самостоятельно.) – BoBTFish

+0

@BoBTFish Вы правы – LeeNeverGup

+0

Кроме того, 'std :: string (pass) .size()> 7' ... –

3

sizeof дает вам размер типа передаваемого ему объекта. Он оценивается строго во время компиляции. Вы передаете его const char *, который находится в 8 на 64 битовых системах.

Чтобы получить длину C -style строки, вы можете использовать функцию Cstrlen в заголовке <cstring>.

Это, я бы рекомендовал не делая это. Я бы рекомендовал отказаться от C строк до C++std::strings, потому что они намного проще в использовании.

Теперь, так оно и есть, вы очень используете строки C Неверно!

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

Вы читать одногоchar (x), а затем взять его адрес и рассматривать это как C строки. Здесь есть две существенные проблемы.

Во-первых, вы, вероятно, должны были читать более одного персонажа.

Во-вторых, вы ударите неопределенное поведение, и ваш компьютер вполне может взорвать, потому что C строки должны быть указателем на NUL -завершённый массив char. Любые функции, ожидающие строки C, будут проходить через поиск конца '\0', которого x не имеет, поскольку это даже не массив.

Таким образом, если вы используете std::string из заголовка <string>, вы можете иметь гораздо более безопасный код, без всего этого faffing с указателями, NUL -terminators, и тому подобное.

(непроверенные)

// 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); 
} 

Кстати, это не будет работать, если входная строка содержит пробелы, но одна вещь, в то время!

(Следующие шаги, если вы научитесь быстро: Читайте на std::getline и заголовок <algorithm>std::count_if выглядит очень актуально.).

И пока мы на него, убить вредные привычки рано, и читать о том, почему вас следует избегать using namespace std; и std::endl.

EDIT

Ваш комментарий, вы застряли с подписью bool check(const char*), так что я думаю, вы должны быть узнать о том, как работать с C строк. Давайте на данный момент предположим, что ваши инструкторы знают, что они делают.

Тогда нормальный способ петли через строку C с указателем, проверка на '\0'. Например, чтобы подсчитать количество прописных букв (и, действительно, вы не пишете это так для реального кода. Или, по крайней мере, если вы пытались в проекте, над которым я работал, я настоятельно рекомендую вам исправить его) :

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

Я до сих пор настоятельно рекомендую прочитать в std::string, если вы можете уйти с ним. Если нет, то вы, вероятно, следующий лучший вариант, вероятно, std::istream::getline.

+0

Спасибо за ответ. Я уже решил проблему, но вас заинтересовало то, что я думаю, что я переписал эту программу :). –

+0

@ DanielZawadzki Пожалуйста, сделайте это! Не принимайте это лично, но это ** плохо **. Надеюсь, мне удалось решить самые важные моменты. Абсолютно принципиальная вещь здесь - использовать 'std :: string'. Могу я спросить, откуда вы учитесь? Вы можете рассмотреть возможность получения [хорошей книги] (http://stackoverflow.com/q/388242/1171191). – BoBTFish

+0

Мне пришлось использовать структуру bool check (const char * pass), потому что она работает в моей школе, но я тоже хочу переписать ее для себя. :). –

1

Как уже упоминалось, вы используете указатель sizeof в цикле своих функций вместо фактической длины переданной строки. Более того, иногда комментарии перед функциями не соответствуют тому, что они делают или должны делать. Например

//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 numbers 
size_t DigitCount (const char* pass) 
{ 
    size_t count = 0; 

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

    return count; 
} 
+0

спасибо также :) –

Смежные вопросы