如何检查给定的 c++ 字符串或 char* 是不是仅包含数字?

Posted

技术标签:

【中文标题】如何检查给定的 c++ 字符串或 char* 是不是仅包含数字?【英文标题】:how to check if given c++ string or char* contains only digits?如何检查给定的 c++ 字符串或 char* 是否仅包含数字? 【发布时间】:2012-02-11 21:50:23 【问题描述】:

或者反过来找第一个非数字字符。

相同的函数适用于 string 和 char* 吗?

【问题讨论】:

【参考方案1】:

从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;

注意:isdigit 有 2 种类型,另一种版本是本地独立的和基于 ASCII 的。

【讨论】:

【参考方案2】:

#include &lt;regex&gt;

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

【讨论】:

【参考方案3】:

已经有几个人提到使用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)7.4 第 1 段,以下适用于来自 &lt;ctype.h&gt; 的函数的参数:

... 在所有情况下,参数都是int,其值应为 可表示为unsigned char 或应等于宏EOF 的值。如果 参数有任何其他值,行为未定义。

不幸的是,C++ 标准没有指定char 是无符号类型。相反,它在 ISO/IEC 14882:2011 3.9.1 [basic.fundamental] 第 1 段中指定:

... char 对象是否可以保存负值是实现定义的。 ...

显然,负值不能表示为unsigned char。也就是说,如果char 在实现上使用签名类型(实际上有几个这样做,例如,它是在 MacOS 上使用 gcc 或 clang 签名的),那么调用任何&lt;ctype.h&gt; 函数都会导致危险未定义的行为。

现在,为什么转换为 unsigned char 会做正确的事情?

根据 4.7 [conv.integral] 第 2 段:

如果目标类型是无符号的,则结果值是与源整数一致的最小无符号整数(模 2n,其中 n 是用于表示无符号类型的位数)。 [ 注意:在二进制补码表示中,这种转换是概念性的,位模式没有变化(如果没有截断)。 ——尾注]

也就是说,从 [可能] 签名的 charunsigned char 的转换是明确定义的,并导致结果在 &lt;ctype.h&gt; 函数的允许范围内。

【讨论】:

我不确定我是否理解您:您是否说将char 转换为unsigned char,可能会产生溢出或UB,比依靠isdigit() 检查@987654342 更好。 @ 属于['0'..'9'],具体以int 作为输入?如果可能的话,任何引用或理由都可能会有所帮助。 charunsigned char 的转换不会溢出或任何东西。即使char 已签名并且字符在负数范围内,它将保留原始位,但会在isdigit() 的定义范围内产生一个值。相关引用在 C 的 7.4 第 1 段中。【参考方案4】:

与 Misha 的回答相同,但更正确:sscanf(buf, "%*u%*c")==1

如果%d 数字提取失败,scanf 返回 0,如果 %c 捕获的数字后面还有任何内容,则返回 2。而且由于* 阻止了值的存储,因此您甚至不会出现溢出。

【讨论】:

这是迄今为止最好的答案。它适用于有符号/无符号、浮点与整数等。【参考方案5】:

当然,有很多方法可以只测试字符串中的数字字符。两种可能的方法是:

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 ?没有它就无法编译,std::isdigit 也不起作用。 @Dfr:有多个isdigit 函数(来自&lt;cctype&gt;&lt;locale&gt; 标头)。 See this related answer. c++11 的方式实在是太棒了 :) @Jichao:你是对的,但那将是一个不同的问题。 @AmitUpadhyay:我使用引用来避免复制传递的std::string 参数(复制可能会很昂贵)。它们也是const,以确保我不会修改调用者的变量。以这种方式使用 const 引用在 C++ 编程中非常常见。【参考方案6】:

如果严格要求您可以准确找到第一个非字符数字的位置,那么您必须检查每个字符。如果没有,我会使用这样的东西:

unsigned safe_atoi(const std::string& a)

    std::stringstream s(a);
    unsigned b;
    s >> b;
    return b;

【讨论】:

【参考方案7】:

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;

【讨论】:

【参考方案8】:

isdigit(int) 告诉您字符是否为数字。如果你打算假设 ASCII 和 base 10,你也可以使用:

int first_non_digit_offset= strspn(string, "0123456789")

【讨论】:

以上是关于如何检查给定的 c++ 字符串或 char* 是不是仅包含数字?的主要内容,如果未能解决你的问题,请参考以下文章

用于检查 char 数组是不是包含 Java 中用户给定字母的 if 语句

如何检查字符串是不是包含字符或数字 C++ 和 C#

使用 SET(C++) 检查两个给定字符串是不是为字谜时出现运行时错误

如何检查 C++ 字符串是不是为 int?

如何检查科学记数法是不是加倍C++

如果字符串向量包含 char 'p',我如何检查 c++