简体   繁体   English

C++ 检查字符串是否包含数字和。 只有[关闭]

[英]C++ check if a string contains numbers and . only [closed]

I want to know if there is a lambda or a clean short format in order to find if a single string contains only numeric values eg 0 - 9 and the full stop character eg only.我想知道是否有 lambda 或干净的短格式,以便查找单个字符串是否仅包含数值(例如 0 - 9)和句号(例如)。 For example string "123.45" should pass and strings "12jd", "12.4f" etc should fail.例如,字符串“123.45”应该通过,而字符串“12jd”、“12.4f”等应该失败。

This would be the code for your check, the constexpr stuff makes the function evaluatable at compile time.这将是您检查的代码,constexpr 的东西使 function 在编译时可评估。 And the static_assert checks the output at compile time.并且 static_assert 在编译时检查 output。 Basically doing a unit test at compile time.基本上在编译时进行单元测试。

string_view is a nice wrapper for string literals and makes the string literal more easy to pass into the function and allows the use of a range based for loop to loop over all the characters. string_view 是一个很好的字符串文字包装器,它使字符串文字更容易传递到 function 中,并允许使用基于范围的 for 循环来遍历所有字符。

#include <cassert>
#include <string_view>

constexpr bool is_positive_number(const std::string_view number_string)
{
    std::size_t number_of_points{ 0ul };

    // loop over all characters in string
    for (const auto character : number_string)
    {
        // a '.' is valid but there should only be one
        if (character == '.')
        {
            number_of_points++;
            if (number_of_points > 1) return false;
        }
        else
        {
            // if character is not a '.' then it must be betweern '0'-'9'
            if ((character < '0') || (character > '9')) return false;
        }
    }

    return true;
}

int main()
{
    static_assert(is_positive_number("1"));
    static_assert(is_positive_number("12"));
    static_assert(is_positive_number("123"));
    static_assert(is_positive_number("1."));
    static_assert(is_positive_number("1.2"));
    static_assert(is_positive_number("12.34"));
    static_assert(is_positive_number("007"));

    static_assert(!is_positive_number("12.3.4"));
    static_assert(!is_positive_number("-123"));
    static_assert(!is_positive_number("abc"));

    //auto lambda = [](const char* number_string)
    auto lambda = [](const std::string& number_string)
    {
        return is_positive_number(number_string);
    };

    auto is_ok = lambda("123");
    assert(is_ok);


    return 0;
}

This can be done with a straightforward scan of the text:这可以通过直接扫描文本来完成:

bool is_valid(const std::string& str) {
    int dots = 0;
    for (char c: str) {
        if (c == '.')
            ++dots;
        if (1 < dots || !std::isdigit(c))
            return false;
    }
    return true;
}

Another way would be to use the open-source compile-time regex library :另一种方法是使用开源 编译时正则表达式库

#include <ctre.hpp>

constexpr bool is_positive_number(std::string_view const s) noexcept {
    return static_cast<bool>(ctre::match<R"(\d+(?:\.\d+)?)">(s));
}

int main() {
    static_assert(is_positive_number("1.2"));
    static_assert(!is_positive_number("1..2"));
    static_assert(!is_positive_number("1e2"));
}

See Online在线查看

Using std::regex produces a two-liner if you dont count the static pattern如果您不计算 static 模式,则使用 std::regex 会产生两行

#include <string>
#include <regex>
#include <cassert>

bool is_positive_number( const std::string& str ) {
    static std::regex rx("^(\\+?)(0|([1-9][0-9]*))(\\.[0-9]*)?$");             // Getting the regex object 
    std::smatch match;
    return std::regex_match(str,match,rx);
}

int main()
{
    assert(is_positive_number("1"));
    assert(is_positive_number("12"));
    assert(is_positive_number("123"));
    assert(is_positive_number("1."));
    assert(is_positive_number("1.2"));
    assert(is_positive_number("12.34"));
    assert(is_positive_number("+12.34"));
    assert(!is_positive_number("007"));

    assert(!is_positive_number("123.23.23"));
    assert(!is_positive_number("-123"));
    assert(!is_positive_number("abc"));

    return 0;
}

This does not check all the cases like repeated dots but it's a one-liner这不会像重复点一样检查所有情况,但它是单行的

  bool ok = str.find_first_not_of( "0123456789." )==std::string::npos;

Use as in使用如

#include <algorithm>
#include <string>

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

int main()
{
    static_assert(is_positive_number("1"));
    static_assert(is_positive_number("12"));
    static_assert(is_positive_number("123"));
    static_assert(is_positive_number("1."));
    static_assert(is_positive_number("1.2"));
    static_assert(is_positive_number("12.34"));
    static_assert(is_positive_number("007"));

    static_assert(!is_positive_number("-123"));
    static_assert(!is_positive_number("abc"));

    return 0;
}

I don't think there is a built-in function that does exactly what you were looking for.我不认为有一个内置的 function 完全符合您的要求。 There is std::stod that converts a string into a double and tells you how many characters were converted successfully.std::stodstring转换为double精度并告诉您成功转换了多少个字符。 However, there are many non-conforming numbers that will work, such as -1 , NAN , 10E+3 .但是,有许多不合格的数字会起作用,例如-1NAN10E+3


One way you could do is first remove all numbers(0~9), then check against "" and "."您可以做的一种方法是首先删除所有数字(0~9),然后检查"""." :

constexpr bool is_num(std::string str)
{
    std::erase_if(str, [](unsigned char c){ return std::isdigit(c);};
    return str == "" || str == ".";
}

Note erase_if is from C++20, for pre-C++20, you would do:注意erase_if来自 C++20,对于 C++20 之前的版本,您可以:

constexpr bool is_num(std::string str)
{
    str.erase(std::remove_if(str.begin(), str.end(), 
              [](unsigned char c){ return std::isdigit(c); }), str.end());
    return str == "" || str == ".";
}

demo演示

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM