我如何在c++中实现以下(Python伪代码)?
if argv[1].startswith('--foo='):
foo_value = int(argv[1][len('--foo='):])
(例如,如果argv[1]是——foo=98,那么foo_value是98。)
更新:我很犹豫是否要研究Boost,因为我只是想对一个简单的小命令行工具做一个非常小的改变(我宁愿不学习如何链接并使用Boost进行一个小的改变)。
我如何在c++中实现以下(Python伪代码)?
if argv[1].startswith('--foo='):
foo_value = int(argv[1][len('--foo='):])
(例如,如果argv[1]是——foo=98,那么foo_value是98。)
更新:我很犹豫是否要研究Boost,因为我只是想对一个简单的小命令行工具做一个非常小的改变(我宁愿不学习如何链接并使用Boost进行一个小的改变)。
当前回答
在c++ 17中,你可以使用std::basic_string_view,在c++ 20中使用std::basic_string::starts_with或std::basic_string_view::starts_with。
std::string_view与std::string相比的好处是——关于内存管理——它只保存一个指向“字符串”(连续的char类对象序列)的指针,并且知道它的大小。示例:不移动/复制源字符串,只获取整数值:
#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
}
其他回答
如果你已经在使用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
}
这种方法,就像这里提供的许多其他答案一样,适用于非常简单的任务,但从长远来看,您通常最好使用命令行解析库。Boost有一个(Boost. program_options),如果您碰巧已经在使用Boost,这可能是有意义的。
否则,搜索“c++命令行解析器”会得到许多选项。
假设两个字符串——argv[1]和"——foo"——都是C字符串,@FelixDombek的答案无疑是最好的解决方案。
然而,看到其他答案,我认为值得注意的是,如果你的文本已经作为std::string可用,那么一个简单的、零拷贝的、最大效率的解决方案存在,到目前为止还没有提到:
const char * foo = "--foo";
if (text.rfind(foo, 0) == 0)
foo_value = text.substr(strlen(foo));
如果foo已经是一个字符串:
std::string foo("--foo");
if (text.rfind(foo, 0) == 0)
foo_value = text.substr(foo.length());
c++ 20更新:
使用std:: string:: starts_with
https://en.cppreference.com/w/cpp/string/basic_string/starts_with
std::string str_value = /* smthg */;
const auto starts_with_foo = str_value.starts_with(std::string_view{"foo"});
从c++ 11开始,std::regex_search还可以用来提供更复杂的表达式匹配。下面的示例还通过std::stof处理浮点数,并将其转换为int。
然而,如果前缀不匹配,下面所示的parseInt方法可能会抛出std::invalid_argument异常;这可以很容易地根据给定的应用程序进行调整:
#include <iostream>
#include <regex>
int parseInt(const std::string &str, const std::string &prefix) {
std::smatch match;
std::regex_search(str, match, std::regex("^" + prefix + "([+-]?(?=\\.?\\d)\\d*(?:\\.\\d*)?(?:[Ee][+-]?\\d+)?)$"));
return std::stof(match[1]);
}
int main() {
std::cout << parseInt("foo=13.3", "foo=") << std::endl;
std::cout << parseInt("foo=-.9", "foo=") << std::endl;
std::cout << parseInt("foo=+13.3", "foo=") << std::endl;
std::cout << parseInt("foo=-0.133", "foo=") << std::endl;
std::cout << parseInt("foo=+00123456", "foo=") << std::endl;
std::cout << parseInt("foo=-06.12e+3", "foo=") << std::endl;
// throw std::invalid_argument
// std::cout << parseInt("foo=1", "bar=") << std::endl;
return 0;
}
正则表达式模式的神奇之处将在下面的回答中详细说明。
编辑:之前的答案没有执行到整数的转换。
为了完整起见,我将提到C的方法:
如果str是你的原始字符串,substr就是你想要的子字符串 检查,然后 Strncmp (str, substr, strlen(substr)) 将返回0如果STR 从substr开始。函数strncmp和strlen在C 头文件<string.h>
(最初由Yaseen Rauf在这里发布,添加了标记)
对于不区分大小写的比较,请使用strnicmp而不是strncmp。
这是C语言的方法,对于c++的字符串,你可以像这样使用相同的函数:
strncmp(str.c_str(), substr.c_str(), substr.size())