Как проверить, если данная строка C ++ или char * содержит только цифры? - PullRequest
45 голосов
/ 17 января 2012

Или наоборот найдите первый нецифровый символ.

Применяются ли одинаковые функции для строки и для символа *?

Ответы [ 8 ]

95 голосов
/ 17 января 2012

Конечно, есть много способов проверить строку только для числовых символов. Два возможных метода:

bool is_digits(const std::string &str)
{
    return str.find_first_not_of("0123456789") == std::string::npos;
}

или

bool is_digits(const std::string &str)
{
    return std::all_of(str.begin(), str.end(), ::isdigit); // C++11
}
12 голосов
/ 17 января 2012

Несколько человек уже упоминали, чтобы использовать isdigit().Тем не менее, обратите внимание, что это не совсем тривиально, поскольку char может быть подписано, что приведет к передаче отрицательного значения в isdigit().Однако эта функция может принимать только положительные значения.То есть вы хотите что-то похожее на это:

if (s.end() == std::find_if(s.begin(), s.end(),
    [](unsigned char c)->bool { return !isdigit(c); })) {
    std::cout << "string '" << s << "' contains only digits\n";
}

Кажется, причина для преобразования в unsigned char не очевидна.Итак, вот соответствующие цитаты из их соответствующих стандартов:

В соответствии с ISO / IEC 9899: 2011 (или ISO / IEC 9899: 1999), параграф 1 7.4, следующее относится к аргументам функций из <ctype.h>:

... Во всех случаях аргументом является int, значение которого должно быть представлено как unsigned char или равным значению макроса EOF.Если аргумент имеет какое-либо другое значение, поведение не определено.

К сожалению, стандарт C ++ не определяет, что char является неподписанным типом.Вместо этого он указывает в ISO / IEC 14882: 2011 3.9.1 [basic.fundamental] параграф 1:

... Определяется реализацией, может ли объект char содержать отрицательные значения....

Очевидно, что отрицательное значение не может быть представлено как unsigned char.То есть, если char использует подписанный тип в реализации (на самом деле есть несколько, которые делают, например, он подписан в MacOS с использованием gcc или clang), существует опасность, что вызов любой из функций <ctype.h> вызоветнеопределенное поведение.

Теперь, почему преобразование в unsigned char делает правильные вещи?

Согласно 4.7 [conv.integral] параграфу 2:

Если тип назначения является беззнаковым, полученное значение является наименьшим целым числом без знака, соответствующим исходному целому числу (по модулю 2 n , где n - число битов, используемых для представления типа без знака).[Примечание: в представлении дополнения до двух это преобразование является концептуальным, и в битовой комбинации нет изменений (если нет усечения).- конец примечания]

То есть преобразование из [потенциально] подписанного char в unsigned char является четко определенным и приводит к тому, что результат находится в допустимом диапазоне для <ctype.h>функции.

5 голосов
/ 17 января 2012

isdigit(int) сообщает вам, является ли символ цифрой. Если вы собираетесь использовать ASCII и базу 10, вы также можете использовать:

int first_non_digit_offset= strspn(string, "0123456789")
4 голосов
/ 17 января 2012

В том же духе, что и ответ Миши, но более правильно: sscanf(buf, "%*u%*c")==1.

scanf возвращает 0, если не удается извлечь цифру %d, и 2, если есть что-то после цифр, захваченных%c.А поскольку * предотвращает сохранение значения, вы даже не можете получить переполнение.

3 голосов
/ 17 января 2012

Заголовочный файл cctype содержит большое количество функций классификации символов, которые можно использовать для каждого символа в строке.Для числовых проверок это будет isdigit.

Следующая программа показывает, как проверять каждый символ строки C или C ++ (процесс в значительной степени идентичен с точки зрения проверки реальных символов, единственно действительныхразница в том, как получить длину):

#include <iostream>
#include <cstring>
#include <cctype>
int main (void) {
    const char *xyzzy = "42x";
    std::cout << xyzzy << '\n';
    for (int i = 0; i < std::strlen (xyzzy); i++) {
        if (! std::isdigit (xyzzy[i])) {
            std::cout << xyzzy[i] << " is not numeric.\n";
        }
    }

    std::string plugh ("3141y59");
    std::cout << plugh << '\n';
    for (int i = 0; i < plugh.length(); i++) {
        if (! std::isdigit (plugh[i])) {
            std::cout << plugh[i] << " is not numeric.\n";
        }
    }

    return 0;
}
1 голос
/ 21 марта 2017

На cplusplus.com вы можете использовать функцию isdigit следующим образом:

// isdigit example (C++)
#include <iostream>       // std::cout
#include <string>         // std::string
#include <locale>         // std::locale, std::isdigit
#include <sstream>        // std::stringstream

int main ()
{
  std::locale loc;
  std::string str="1776ad";
  if (isdigit(str[0],loc))
  {
    int year;
    std::stringstream(str) >> year;
    std::cout << "The year that followed " << year << " was " << (year+1) << ".\n";
  }
  return 0;
}

Примечание: существует 2 типа isdigit, другая версия является локальной и основанной на ASCII.

0 голосов
/ 12 февраля 2017

#include <regex>

std::string string( "I only have 3 dollars!" );
std::cout << std::regex_search( string, std::regex( "\\d+" ) ); // true

и

std::string string( "I only have three dollars!" );
std::cout << std::regex_search( string, std::regex( "\\d+" ) ); // false
0 голосов
/ 17 января 2012

Если существует строгое требование, чтобы вы могли точно определить, где находится первая не-символьная цифра, вам придется проверять каждый символ.Если нет, я бы использовал что-то вроде этого:

unsigned safe_atoi(const std::string& a)
{
    std::stringstream s(a);
    unsigned b;
    s >> b;
    return b;
}
...