Или, наоборот, найдите первый несимметричный символ.
Выполняют те же функции для строки и для char *?
Или, наоборот, найдите первый несимметричный символ.
Выполняют те же функции для строки и для char *?
Конечно, существует множество способов проверки строки только для числовых символов. Возможны два способа:
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
}
Несколько человек уже упомянули использовать 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
не очевидно. Итак, вот соответствующие цитаты из их соответствующих стандартов:
В соответствии с ИСО/МЭК 9899: 2011 (или ИСО/МЭК 9899: 1999) 7.4 параграфа 1 для аргументов функций из <ctype.h>
применяется следующее:
... Во всех случаях аргумент равен
int
, значение которого должно быть представляемый какunsigned char
или должен равняться значению макросаEOF
. Если аргумент имеет любое другое значение, поведение undefined.
К сожалению, стандарт С++ не указывает, что char
является неподписанным типом. Вместо этого он указывает в ИСО/МЭК 14882: 2011 3.9.1 [basic.fundamental] пункт 1:
... Определяется реализацией, может ли объект
char
содержать отрицательные значения....
Ясно, что отрицательное значение не может быть представлено как unsigned char
. То есть, если char
использует подписанный тип в реализации (на самом деле есть несколько, которые, например, подписаны на MacOS с использованием gcc или clang), существует опасность того, что вызов любой из функций <ctype.h>
приведет к undefined.
Теперь, почему преобразование в unsigned char
делает правильные вещи?
Согласно пункту 4.7 [conv.integral], пункт 2:
Если тип назначения не указан, результирующее значение представляет собой наименьшее беззнаковое целое, сравнимое с исходным целым числом (по модулю 2 n где n - количество бит, используемых для представления неподписанного типа). [Примечание. В представлении с двумя дополнениями это преобразование является концептуальным и нет изменений в битовой схеме (если нет усечения). -end note]
То есть преобразование из [потенциально] подписанного char
в unsigned char
хорошо определено и приводит к тому, что результат находится в допустимом диапазоне для функций <ctype.h>
.
isdigit(int)
указывает, является ли символ цифрой. Если вы собираетесь использовать ASCII и базу 10, вы также можете использовать:
int first_non_digit_offset= strspn(string, "0123456789")
В том же духе, что и Миша, но правильнее: sscanf(buf, "%*u%*c")==1
.
scanf
возвращает 0, если извлечение цифр %d
завершается с ошибкой, и 2, если после цифр, отмеченных символом %c
, есть что-либо. И поскольку *
предотвращает сохранение значения, вы даже не можете получить переполнение.
Заголовочный файл cctype
имеет большое количество функций классификации символов, которые вы можете использовать для каждого символа в строке. Для числовых проверок это будет isdigit
.
Следующая программа показывает, как проверять каждый символ строки 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;
}
Если это строгое требование, чтобы вы могли точно определить, где находится первая несимвольная цифра, вам нужно будет проверить каждый символ. Если нет, я бы использовал либо что-то вроде этого:
unsigned safe_atoi(const std::string& a)
{
std::stringstream s(a);
unsigned b;
s >> b;
return b;
}
#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
Из 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.