如何检查 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
How do I check if a C++ std::string starts with a certain string, and convert a substring to an int?
提问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_value
is 98
.)
(例如,如果argv[1]
是--foo=98
,则foo_value
是98
。)
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 rfind
which has the pos
parameter. Here, pos
is the last index to be considered part of the search subject (so, if your string would be titititi
, the latter titi
is not considered because it starts later than the chosen pos=0
):
使用rfind
具有pos
参数的重载。这里,pos
是被视为搜索主题一部分的最后一个索引(因此,如果您的字符串是titititi
,titi
则不考虑后者,因为它晚于 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
str
is your original string,substr
is the substring you want to check, then
strncmp(str, substr, strlen(substr))
will return
0
ifstr
starts withsubstr
. The functionsstrncmp
andstrlen
are in the C header file<string.h>
如果
str
是您的原始字符串,substr
是您要检查的子字符串,则
strncmp(str, substr, strlen(substr))
0
如果str
以substr
.开头,则返回。函数strncmp
和strlen
在 C 头文件中<string.h>
(originally posted by Yaseen Rauf here, markup added)
(最初由 Yaseen Rauf在这里发布,添加了标记)
For a case-insensitive comparison, use strnicmp
instead 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_with
or std::basic_string_view::starts_with
.
使用 C++17,您可以将std::basic_string_view
& 与 C++20std::basic_string::starts_with
或std::basic_string_view::starts_with
.
The benefit of std::string_view
in 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_view
与std::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;
}