2014-10-14 4 views
0

Итак, я пытаюсь прочитать строку из cin, затем прокручиваю строку, чтобы подсчитать, какие символы в этой строке на самом деле являются буквами в английском алфавите. Я написал программу, которая работает очень хорошо, но я хочу знать, есть ли более эффективный способ сделать это, без перебора по всему английскому алфавиту.Как игнорировать не-буквы из std :: cin

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

int main() { 

    string my_str; //will use to store user input 
    getline(cin, my_str); //read in user input to my_str 

    int countOfLetters = 0; //begine count at 0 
    string alphabet = "abcdefghijklmnopqrstuwxyz"; //the entire english alphabet 

    for(int i = 0; i < my_str.length(); i++){ 
     for(int j = 0; j < alphabet.length(); j++){ 
      if (tolower(my_str.at(i)) == alphabet.at(j)){ //tolower() function used to convert all characters from user inputted string to lower case 
        countOfLetters += 1; 
      } 
     } 
    } 

    cout << countOfLetters; 
    return 0; 
} 

EDIT: Вот мой новый и улучшенный код:

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

int main() { 

    string my_str; //will use to store user input 
    getline(cin, my_str); //read in user input to my_str 

    int countOfLetters = 0; //begine count at 0 
    string alphabet = "abcdefghijklmnopqrstuwxyz"; //the entire english alphabet 

    for(unsigned int i = 0; i < my_str.length(); i++){ 
      if (isalpha(my_str.at(i))){ //tolower() function used to convert all characters from user inputted string to lower case 
        countOfLetters += 1; 
      } 
     } 


    cout << countOfLetters; 
    return 0; 
} 
    enter code here 

ответ

1

Вы могли бы, возможно, использовать isalpha:

for(int i = 0; i < my_str.length(); i++) 
    if (isalpha(my_str.at(i)) 
     countOfLetters++; 
+0

Ну Алекс, вы были первыми, так что, я думаю, вы получаете репутацию! Спасибо за короткий и сладкий ответ. Я обновил свой OP своим модным новым кодом. – FluffyKittens

+0

@AdamJ Обратите внимание, что я фокусировался на _ "без прокрутки по всему английскому алфавиту" _. Если вы заинтересованы в том, чтобы весь цикл был короче и в стиле C++, проверьте ответ ** @ 0x499602D2 **. – AlexD

2

Используйте isalpha(), чтобы увидеть, какие символы являются буквами и исключить их.

Таким образом, вы можете изменить свой код так:

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

int main() { 

    string my_str; 
    getline(cin, my_str); 

    int countOfLetters = 0; 

    for (size_t i = 0; i < my_str.length(); i++) { // int i produced a warning 
    if (isalpha(my_str.at(i))) { // if current character is letter 
     ++countOfLetters;   // increase counter by one 
    } 
    } 

    cout << countOfLetters; 
    return 0; 
} 
0

Вы также можете проверить, если ИНТ бросок между 65-90 или 97-122

на примере

(int)'a' 

Должно быть указано 97

Это будет самый эффективный способ, без каких-либо сомнений. Его лучше, чем использование isalpha().

Проверить http://www.asciitable.com/ для ASCI номеров

+1

Определенно используйте '' A'', а не магическое число 65 ... и действительно ли это на самом деле быстрее, чем 'isalpha' может удивить вас. –

+0

Он хочет проверить, находится ли летер в алфавите, поэтому, если ((int) letter> 64 && (int) letter <91) это в алфавите, самая простая и самая эффективная проверка: o – Etixpp

+0

Это более значимо и получает тот же код: 'letter> = 'A' && letter <= 'Z'' Но тогда вам нужно проверить два случая, и тогда таблица поиска становится конкурентоспособной. –

1

Вы можете использовать алгоритм std::count_if() вместе с интерфейсом итератора для подсчета символов, для которых некоторые предикат возвращает истинное. Предикат может использовать std::isalpha() для проверки алфавитных символов. Например:

auto count = std::count_if(std::begin(str), std::end(str), 
          [&] (unsigned char c) { return std::isalpha(c); }); 
+0

Не можете ли вы передать 'std :: isalpha' непосредственно в качестве предиката? Зачем заворачивать его в лямбда? –

+0

@BenVoigt В '' есть другая перегрузка ', которая принимает аргумент шаблона и отдельный экземпляр' std :: locale', но я не хотел использовать приведение, чтобы выбрать правильный. – 0x499602D2

+0

Избежание перегруженности хаоса - достаточно справедливая причина. –

0

isalpha работает хорошо для этой конкретной проблемы, но есть более общее решение, если список символов, которые принимают не так просто. Например, если вы хотите добавить некоторую пунктуацию.

std::set<char> good_chars; 
good_chars.insert('a'); good_chars.insert('A'); 
good_chars.insert('b'); good_chars.insert('B'); 
// ... 
good_chars.insert('z'); good_chars.insert('Z'); 
good_chars.insert('_'); 
// the above could be simplified by looping through a string of course 

for(int i = 0; i < my_str.length(); i++){ 
    countOfLetters += good_chars.count(my_str[i]); 
} 
+0

До тех пор, пока вы не перейдете к полному юникоду, простая таблица поиска (например, почти все реализации использования isalpha) намного быстрее и ниже накладных расходов, чем 'std :: set', и столь же гибкая. –

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