如何检查 C++ std::string 是否以某个字符串开头,并将子字符串转换为 int?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1878001/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 21:28:15  来源:igfitidea点击:

How do I check if a C++ std::string starts with a certain string, and convert a substring to an int?

c++stringparsingsubstringstartswith

提问by Daryl Spitzer

How do I implement the following (Python pseudocode) in C++?

如何在 C++ 中实现以下(Python 伪代码)?

if argv[1].startswith('--foo='):
    foo_value = int(argv[1][len('--foo='):])

(For example, if argv[1]is --foo=98, then foo_valueis 98.)

(例如,如果argv[1]--foo=98,则foo_value98。)

Update:I'm hesitant to look into Boost, since I'm just looking at making a very small change to a simple little command-line tool (I'd rather not have to learn how to link in and use Boost for a minor change).

更新:我对研究 Boost 犹豫不决,因为我只是想对一个简单的小命令行工具做一个很小的改变(我宁愿不必学习如何链接和使用 Boost 为未成年人改变)。

回答by Ludovic Aubert

Use an overload of rfindwhich has the posparameter. Here, posis the last index to be considered part of the search subject (so, if your string would be titititi, the latter titiis not considered because it starts later than the chosen pos=0):

使用rfind具有pos参数的重载。这里,pos是被视为搜索主题一部分的最后一个索引(因此,如果您的字符串是titititititi则不考虑后者,因为它晚于 selected 开始pos=0):

std::string s = "tititoto";
if (s.rfind("titi", 0) == 0) {
  // s starts with prefix
}

Who needs anything else? Pure STL!

谁还需要什么?纯STL!

回答by Thomas

You would do it like this:

你会这样做:

std::string prefix("--foo=");
if (!arg.compare(0, prefix.size(), prefix))
    foo_value = atoi(arg.substr(prefix.size()).c_str());

Looking for a lib such as Boost.ProgramOptions that does this for you is also a good idea.

寻找一个像 Boost.ProgramOptions 这样的库来为你做这件事也是一个好主意。

回答by Felix Dombek

Just for completeness, I will mention the C way to do it:

为了完整起见,我将提到 C 的方式来做到这一点:

If stris your original string, substris the substring you want to check, then

strncmp(str, substr, strlen(substr))

will return 0if strstarts with substr. The functions strncmpand strlenare in the C header file <string.h>

如果str是您的原始字符串,substr是您要检查的子字符串,则

strncmp(str, substr, strlen(substr))

0如果strsubstr.开头,则返回。函数strncmpstrlen在 C 头文件中<string.h>

(originally posted by Yaseen Rauf here, markup added)

(最初由 Yaseen Rauf在这里发布,添加了标记)

For a case-insensitive comparison, use strnicmpinstead of strncmp.

对于不区分大小写的比较,请使用strnicmp代替strncmp

This is the C way to do it, for C++ strings you can use the same function like this:

这是执行此操作的 C 方法,对于 C++ 字符串,您可以使用相同的函数,如下所示:

strncmp(str.c_str(), substr.c_str(), substr.size())

回答by Ferruccio

If you're already using Boost, you can do it with boost string algorithms+ boost lexical cast:

如果您已经在使用 Boost,则可以使用boost 字符串算法+ boost 词法转换来实现:

#include <boost/algorithm/string/predicate.hpp>
#include <boost/lexical_cast.hpp>

try {    
    if (boost::starts_with(argv[1], "--foo="))
        foo_value = boost::lexical_cast<int>(argv[1]+6);
} catch (boost::bad_lexical_cast) {
    // bad parameter
}

This kind of approach, like many of the other answers provided here is ok for very simple tasks, but in the long run you are usually better off using a command line parsing library. Boost has one (Boost.Program_options), which may make sense if you happen to be using Boost already.

这种方法,就像这里提供的许多其他答案一样,适用于非常简单的任务,但从长远来看,您通常最好使用命令行解析库。Boost 有一个(Boost.Program_options),如果您碰巧已经在使用 Boost,这可能是有意义的。

Otherwise a search for "c++ command line parser" will yield a number of options.

否则,搜索“c++ 命令行解析器”将产生许多选项。

回答by Hüseyin Ya?l?

Code I use myself:

我自己使用的代码:

std::string prefix = "-param=";
std::string argument = argv[1];
if(argument.substr(0, prefix.size()) == prefix) {
    std::string argumentValue = argument.substr(prefix.size());
}

回答by matiu

Nobody used the STL algorithm/mismatchfunction yet. If this returns true, prefix is a prefix of 'toCheck':

还没有人使用过 STL算法/失配函数。如果返回 true,prefix 是 'toCheck' 的前缀:

std::mismatch(prefix.begin(), prefix.end(), toCheck.begin()).first == prefix.end()

Full example prog:

完整示例程序:

#include <algorithm>
#include <string>
#include <iostream>

int main(int argc, char** argv) {
    if (argc != 3) {
        std::cerr << "Usage: " << argv[0] << " prefix string" << std::endl
                  << "Will print true if 'prefix' is a prefix of string" << std::endl;
        return -1;
    }
    std::string prefix(argv[1]);
    std::string toCheck(argv[2]);
    if (prefix.length() > toCheck.length()) {
        std::cerr << "Usage: " << argv[0] << " prefix string" << std::endl
                  << "'prefix' is longer than 'string'" <<  std::endl;
        return 2;
    }
    if (std::mismatch(prefix.begin(), prefix.end(), toCheck.begin()).first == prefix.end()) {
        std::cout << '"' << prefix << '"' << " is a prefix of " << '"' << toCheck << '"' << std::endl;
        return 0;
    } else {
        std::cout << '"' << prefix << '"' << " is NOT a prefix of " << '"' << toCheck << '"' << std::endl;
        return 1;
    }
}


Edit:

编辑:

As @James T. Huggett suggests, std::equal is a better fit for the question: Is A a prefix of B?and is slight shorter code:

正如@James T. Huggett 所暗示的那样,std::equal 更适合以下问题:A 是 B 的前缀吗?并且是稍短的代码:

std::equal(prefix.begin(), prefix.end(), toCheck.begin())

Full example prog:

完整示例程序:

#include <algorithm>
#include <string>
#include <iostream>

int main(int argc, char **argv) {
  if (argc != 3) {
    std::cerr << "Usage: " << argv[0] << " prefix string" << std::endl
              << "Will print true if 'prefix' is a prefix of string"
              << std::endl;
    return -1;
  }
  std::string prefix(argv[1]);
  std::string toCheck(argv[2]);
  if (prefix.length() > toCheck.length()) {
    std::cerr << "Usage: " << argv[0] << " prefix string" << std::endl
              << "'prefix' is longer than 'string'" << std::endl;
    return 2;
  }
  if (std::equal(prefix.begin(), prefix.end(), toCheck.begin())) {
    std::cout << '"' << prefix << '"' << " is a prefix of " << '"' << toCheck
              << '"' << std::endl;
    return 0;
  } else {
    std::cout << '"' << prefix << '"' << " is NOT a prefix of " << '"'
              << toCheck << '"' << std::endl;
    return 1;
  }
}

回答by Marcelo Cantos

Given that both strings — argv[1]and "--foo"— are C strings, @FelixDombek's answeris hands-down the best solution.

鉴于这两个字符串 -argv[1]"--foo"- 都是 C 字符串,@FelixDombek 的答案无疑是最佳解决方案。

Seeing the other answers, however, I thought it worth noting that, if your text is already available as a std::string, then a simple, zero-copy, maximally efficient solution exists that hasn't been mentioned so far:

眼看着其他的答案,但是,我认为这值得一提的是,如果你的文本已经可以作为一个std::string,然后进行简单,零拷贝,最大限度地高效的解决方案存在尚未到目前为止提到:

const char * foo = "--foo";
if (text.rfind(foo, 0) == 0)
    foo_value = text.substr(strlen(foo));

And if foo is already a string:

如果 foo 已经是一个字符串:

std::string foo("--foo");
if (text.rfind(foo, 0) == 0)
    foo_value = text.substr(foo.length());

回答by Roi Danton

With C++17 you can use std::basic_string_view& with C++20 std::basic_string::starts_withor std::basic_string_view::starts_with.

使用 C++17,您可以将std::basic_string_view& 与 C++20std::basic_string::starts_withstd::basic_string_view::starts_with.

The benefit of std::string_viewin comparison to std::string- regarding memory management - is that it only holds a pointer to a "string" (contiguous sequence of char-like objects) and knows its size. Example without moving/copying the source strings just to get the integer value:

std::string_viewstd::string- 关于内存管理 -相比的好处是它只保存一个指向“字符串”(类似字符的对象的连续序列)的指针并且知道它的大小。不移动/复制源字符串只是为了获取整数值的示例:

#include <exception>
#include <iostream>
#include <string>
#include <string_view>

int main()
{
    constexpr auto argument = "--foo=42"; // Emulating command argument.
    constexpr auto prefix = "--foo=";
    auto inputValue = 0;

    constexpr auto argumentView = std::string_view(argument);
    if (argumentView.starts_with(prefix))
    {
        constexpr auto prefixSize = std::string_view(prefix).size();
        try
        {
            // The underlying data of argumentView is nul-terminated, therefore we can use data().
            inputValue = std::stoi(argumentView.substr(prefixSize).data());
        }
        catch (std::exception & e)
        {
            std::cerr << e.what();
        }
    }
    std::cout << inputValue; // 42
}

回答by Macsinus

text.substr(0, start.length()) == start

回答by razvanco13

Using STL this could look like:

使用 STL 这可能看起来像:

std::string prefix = "--foo=";
std::string arg = argv[1];
if (prefix.size()<=arg.size() && std::equal(prefix.begin(), prefix.end(), arg.begin())) {
  std::istringstream iss(arg.substr(prefix.size()));
  iss >> foo_value;
}