Как проверить, является ли строка строчными и буквенно-цифровыми?

Есть ли метод, который проверяет эти случаи? Или мне нужно разобрать каждую букву в строке и проверить, является ли она строчной (буквой) и является ли она числом/буквой?


person unwise guy    schedule 03.07.2012    source источник


Ответы (6)


Вы можете использовать islower(), isalnum() для проверки этих условий для каждого символа. Для этого нет функции на уровне строки, поэтому вам придется написать свою собственную.

person Oleksi    schedule 03.07.2012
comment
Хорошая точка зрения. Я отредактировал это, чтобы отразить это. Я не знал об этой функции. - person Oleksi; 03.07.2012
comment
Я немного смущен здесь, вы прокомментировали свой собственный ответ «Хороший вопрос ...» - person t0mm13b; 03.07.2012
comment
@ t0mm13b до того, как я сделал свой, был комментарий, указывающий на isalnum(). Я думаю, что это было удалено :P - person Oleksi; 03.07.2012
comment
@unwiseguy вы всегда можете принять ответы, нажав на галочку рядом с ответом. Upvoting — это тот, который требует 15 репутации. - person Oleksi; 03.07.2012
comment
Нет .. вам все равно придется ждать x-количество минут после публикации вопроса, чтобы принять ответ, но спасибо - person unwise guy; 03.07.2012
comment
См. мой ответ - на самом деле существует функция на уровне строки для этого, хотя большинство людей, вероятно, не ожидали бы ее найти. - person Jerry Coffin; 03.07.2012
comment
@JerryCoffin круто. Я этого не знал. Ваш ответ должен быть принятым. - person Oleksi; 03.07.2012
comment
@Oleksi: меня вполне устраивает то, что ваша была принята - хотя функция существует, я совсем не уверен, что рекомендую ее использовать. Я почти уверен, что большинству людей будет проще понять что-то вроде islower или isalnum в цикле или переданное в std::find. - person Jerry Coffin; 03.07.2012

Предполагая, что локаль "C" приемлема (или поменять местами другой набор символов для criteria), используйте find_first_not_of()

#include <string>

bool testString(const std::string& str)
{
      std::string criteria("abcdefghijklmnopqrstuvwxyz0123456789");
      return (std::string::npos == str.find_first_not_of(criteria);
}
person bgporter    schedule 03.07.2012
comment
Предполагается локаль C (что может не иметь значения для OP). - person aschepler; 03.07.2012
comment
@bgporter Извините за этот ответ почти два года спустя, но насколько эффективен этот метод? Я работаю над балансировщиком химических уравнений, и это кажется идеальной предварительной проверкой вместо выполнения нескольких проверок для каждого символа. - person Andrue; 21.02.2014
comment
Я предполагаю, что вопрос «эффективен по сравнению с чем?». Мой первый выбор состоит в том, чтобы предположить, что стандартная библиотека в целом будет достаточно быстрой (и относительно свободной от ошибок) по сравнению с написанным от руки кодом. - person bgporter; 23.02.2014
comment
@Andrue, это будет не очень эффективно, потому что std::find_first_not_of нужен внутренний цикл, чтобы проверить, не находится ли элемент в наборе, в отличие от isdigit, isalnum и islower, которые могут использовать всего несколько сравнений в зависимости от локали. - person phuclv; 15.12.2019

Это не очень хорошо известно, но локаль на самом деле имеет функции для одновременного определения характеристик целых строк. В частности, фасет ctype локали имеет scan_is и scan_not, которые сканируют первый символ, соответствующий заданной маске (буква, число, буквенно-цифровой, нижний, верхний, знак препинания, пробел, шестнадцатеричная цифра и т. д.), или первый символ. что не подходит, соответственно. В остальном они работают примерно так же, как std::find_if, возвращая то, что вы передали в качестве "конца", чтобы сигнализировать об ошибке, в противном случае возвращая указатель на первый элемент в строке, который не соответствует тому, что вы просили.

Вот краткий пример:

#include <locale>
#include <iostream>
#include <iomanip>

int main() {

    std::string inputs[] = { 
        "alllower",
        "1234",
        "lower132",
        "including a space"
    };

    // We'll use the "classic" (C) locale, but this works with any
    std::locale loc(std::locale::classic());

    // A mask specifying the characters to search for:          
    std::ctype_base::mask m = std::ctype_base::lower | std::ctype_base::digit;

    for (int i=0; i<4; i++) {
        char const *pos;
        char const *b = &*inputs[i].begin();
        char const *e = &*inputs[i].end();

        std::cout << "Input: " << std::setw(20) << inputs[i] << ":\t";

        // finally, call the actual function:
        if ((pos=std::use_facet<std::ctype<char> >(loc).scan_not(m, b, e)) == e)
            std::cout << "All characters match mask\n";
        else
            std::cout << "First non-matching character = \"" << *pos << "\"\n";
    }
    return 0;
}

Я подозреваю, что большинство людей предпочтут использовать std::find_if -- его использование почти такое же, но его можно довольно легко обобщить на множество других ситуаций. Несмотря на то, что это имеет гораздо более узкое применение, на самом деле это не намного проще для пользователя (хотя я полагаю, что если вы сканируете большие фрагменты текста, это может быть, по крайней мере, немного быстрее).

person Jerry Coffin    schedule 03.07.2012

Вы можете использовать tolower и strcmp, чтобы сравнить, если original_string и tolowered строка. И сделать числа индивидуально для каждого символа.

(ИЛИ) Сделайте оба для каждого персонажа, как показано ниже.

#include <algorithm>

static inline bool is_not_alphanum_lower(char c)
{
    return (!isalnum(c) || !islower(c));
}

bool string_is_valid(const std::string &str)
{
    return find_if(str.begin(), str.end(), is_not_alphanum_lower) == str.end();
}

Я использовал некоторую информацию из: Определите, строка содержит только буквенно-цифровые символы (или пробел)

person Kingkong Jnr    schedule 03.07.2012

Просто используйте std::all_of

bool lowerAlnum = std::all_of(str.cbegin(), str.cend(), [](const char c){
    return isdigit(c) || islower(c);
});

Если вас не волнует локаль (т.е. ввод представляет собой чистый 7-битный ASCII), то условие можно оптимизировать в

[](const char c){ return ('0' <= c && c <= '9') || ('a' <= c && c <= 'z'); }
person phuclv    schedule 15.03.2019

Если ваши строки содержат текст в кодировке ASCII, и вы хотите писать свои собственные функции (как я), то вы можете использовать это:

bool is_lower_alphanumeric(const string& txt)
{
  for(char c : txt)
  {
    if (!((c >= '0' and c <= '9') or (c >= 'a' and c <= 'z'))) return false;
  }
  return true;
}
person Gigi    schedule 03.07.2012