Я писал код и столкнулся с некоторыми проблемами. Я хотел написать функцию, которая проверяет, есть ли в строке гласные, и попытался сделать это через цикл for с оператором switch внутри. Видимо, не работает и почему-то никогда не возвращает true.

bool scanStr(string userInp) {
    for (int i = 0; i < userInp.size(); i++) {
        switch (userInp[i])
        {
        case 'a':
        case 'A':
        case 'e':
        case 'E':
        case 'i':
        case 'I':
        case 'o':
        case 'O':
        case 'u':
        case 'U':
        case 'y':
        case 'Y':
            return true;
            break;
        default:
            return false;
        }
    }
}

Я попробовал просто проверить, действительно ли программа выполняет итерацию по строке, и это было так, поэтому я не понимаю, почему в функции она всегда возвращает false?

int main() {
    string userInp;
    string pigLatin;

    cout << "Please enter a string to convert to pig Latin: " << endl;
    cin >> userInp;
    cout << endl;

    // tests
    for (int i = 0; i < userInp.size(); i++) { //checking if it actually iterates
        cout << userInp[i];
    }
    cout << endl;

    if (scanStr(userInp))
        cout << "it has a vowel" << endl;
    else
        cout << "no vowel" << endl;

    system("pause");
    return 0;
}

Сначала я подумал, что это потому, что цикл продолжался, хотя после последнего случая был оператор break, но я не совсем уверен, является ли это причиной.

Любые идеи?

c++
3
Panthy 18 Апр 2016 в 09:17

4 ответа

Лучший ответ

Проблема заключалась в том, что если какой-либо символ не был гласным, функция немедленно возвращала false. Также используйте const &. const позволяет передавать константные строки, а ссылка экономит некоторое время, потому что C ++ не должен копировать всю строку.

bool scanStr(const string & userInp) {
    for (int i = 0; i < userInp.size(); i++) {
        switch (userInp[i])
        {
        case 'a':
        case 'A':
        case 'e':
        case 'E':
        case 'i':
        case 'I':
        case 'o':
        case 'O':
        case 'u':
        case 'U':
        case 'y':
        case 'Y':
            return true;
            break;
        }
    }
    return false;
}
1
tomascapek 18 Апр 2016 в 09:26

Я бы посоветовал вам извлечь логику проверки гласных в отдельную функцию:

bool is_vowel(char x)
{
    switch (x)
    {
    case 'a':
    case 'A':
    case 'e':
    case 'E':
    case 'i':
    case 'I':
    case 'o':
    case 'O':
    case 'u':
    case 'U':
    case 'y':
    case 'Y':
        return true;
    default:
        return false;
    }
}

Тогда вы можете использовать стандартный алгоритм вместо цикла:

#include <algorithm>
#include <string>

bool contains_vowel(const std::string& str)
{
    return std::any_of(str.begin(), str.end(), is_vowel);
}

(Я переименовал scanStr в contains_vowel, потому что это имя более информативно.)

13
fredoverflow 18 Апр 2016 в 06:37

Удалите эти строки из своей функции:

    default:
        return false;

Они заставляют вашу функцию возвращать false для первой негласной буквы, с которой она сталкивается.

Вы хотите вернуть false, только если вы достигли конца цикла и еще не вернули true.

bool scanStr(string userInp) 
{
    for (int i = 0; i < userInp.size(); i++) 
    {
        switch (userInp[i])
        {
        case 'a':
        case 'A':
        case 'e':
        case 'E':
        case 'i':
        case 'I':
        case 'o':
        case 'O':
        case 'u':
        case 'U':
        case 'y':
        case 'Y':
            return true;
        }
    }

    return false;
}

Лучшим подходом в современном C ++ было бы:

bool scanStr(const std::string& userInp) 
{
    for (const auto c : userInp) 
    {
        switch (c)
        {
        case 'a':
        case 'A':
        case 'e':
        case 'E':
        case 'i':
        case 'I':
        case 'o':
        case 'O':
        case 'u':
        case 'U':
        case 'y':
        case 'Y':
            return true;
        }
    }

    return false;
}

Но если вы не знаете, что это означает, не беспокойтесь об этом сейчас, ваша книга или учебное пособие объяснит вам достаточно скоро.

5
nvoigt 18 Апр 2016 в 06:34

Сначала компилятор превратит регистр переключателя в поисковую таблицу, затем auto будет определен компилятором как тип данных на основе присвоенного значения (в данном случае это char).

Или просто отдайте его своему компилятору, он знает, как это сделать.

bool scanStr(string userInp)
{
    for(auto c : userInp)
    {
        switch (c)
        {
            case 'a': case 'A':
            case 'e': case 'E':
            case 'i': case 'I':
            case 'o': case 'O':
            case 'u': case 'U':
            case 'y': case 'Y':

            return true;
        }
    }

    return false;
}
0
Khaled.K 18 Апр 2016 в 07:33