如何在 C++ 中搜索 std::string 中的子字符串?

Posted

技术标签:

【中文标题】如何在 C++ 中搜索 std::string 中的子字符串?【英文标题】:How do you search a std::string for a substring in C++? 【发布时间】:2008-12-06 21:59:53 【问题描述】:

我正在尝试用 C++ 解析一个简单的字符串。我知道该字符串包含一些带有冒号的文本,后跟一个空格,然后是一个数字。我想只提取字符串的数字部分。我不能只对空格进行标记(使用 sstream 和

一些示例字符串可能是:

总磁盘空间:9852465

可用磁盘空间:6243863

部门:4095

我想使用标准库,但如果您有其他解决方案,您也可以发布,因为其他有相同问题的人可能希望看到不同的解决方案。

【问题讨论】:

【参考方案1】:
std::string strInput = "Total disk space: 9852465";
std::string strNumber = "0";
size_t iIndex = strInput.rfind(": ");
if(iIndex != std::string::npos && strInput.length() >= 2)

  strNumber = strInput.substr(iIndex + 2, strInput.length() - iIndex - 2)

【讨论】:

不要使用!= -1!请改用!= string::npos 为什么不,康拉德,它不起作用,是不是效率低下???好奇的人想知道。 -1 是一个实现细节,string::npos 根据定义是正确的。 不保证有效。该标准说如果没有找到任何东西,find 返回npos,它定义了npos = -1。但是,npos 的类型为 std::size_t。一些编译器会在比较无符号数和有符号数时发出警告,并根据设置将其视为错误 这样更好——我的性格类型喜欢看到为什么要以某种方式做事的解释,而不仅仅是从上面传下来的一些法令:-)【参考方案2】:

为了完整起见,这里有一个简单的 C 解决方案:

int value;
if(sscanf(mystring.c_str(), "%*[^:]:%d", &value) == 1)
    // parsing succeeded
else
    // parsing failed

解释:%*[^:] 表示要读入尽可能多的非冒号字符,* 禁止赋值。然后,在冒号和任何中间空格之后读入整数。

【讨论】:

谢谢,我喜欢人们提供替代解决方案。我相信这对未来的 C 程序员会有帮助。 我个人非常喜欢你的解决方案,就像 Konrads 一样 :) 即使他们不搜索子字符串,他们也展示了如何干净地解析它【参考方案3】:

我不能只对空格进行标记(使用 sstream 和

没错,但你可以使用std::getline:

string not_number;
int number;
if (not (getline(cin, not_number, ':') and cin >> number)) 
    cerr << "No number found." << endl;

【讨论】:

寻找换行符;我假设您打算使用将分隔符作为第三个参数的 getline 的重载并为该参数传入 ':'? 谢谢亚当,我忘记了第三个论点,正如您所猜测的那样,这正是他的帖子的全部内容。 :-/ 谢谢,康拉德。我不知道重载的 getline() 函数。以这种方式重载函数对我来说似乎很奇怪,因为它不再有一行。 @Adam:感谢您对此的解释。这让我彻底糊涂了。 :) 或者,if(!(cin.ignore(numeric_limits::max(), ':') >> number)) cout 【参考方案4】:

类似于 Konrads 的答案,但使用 istream::ignore

int number;
std::streamsize max = std::numeric_limits<std::streamsize>::max();
if (!(std::cin.ignore(max, ':') >> number)) 
    std::cerr << "No number found." << std::endl;
 else 
    std::cout << "Number found: " << number << std::endl;

【讨论】:

是的,这实际上是更好的答案。但是,IIRC 在某些平台上存在ignoremax 的一些问题(可能是由于有符号/无符号不匹配)。但是,此信息可能已过时。 是的,我在 std 中读到 streamsize 必须具有签名类型。我实际上只是抬头,因为我想知道为什么 ppl 不做 streamsize(-1) :)【参考方案5】:

我很惊讶没有人提到正则表达式。它们是作为 TR1 的一部分添加的,也包含在 Boost 中。这是使用正则表达式的解决方案

typedef std::tr1::match_results<std::string::const_iterator> Results;

std::tr1::regex re(":[[:space:]]+([[:digit:]]+)", std::tr1::regex::extended);
std::string     str("Sectors: 4095");
Results         res;

if (std::tr1::regex_search(str, res, re)) 
    std::cout << "Number found: " << res[1] << std::endl;
 else 
    std::cerr << "No number found." << std::endl;

这看起来需要做更多的工作,但恕我直言,你会从中得到更多。

【讨论】:

【参考方案6】:
const std::string pattern(": ");
std::string s("Sectors: 4095");
size_t num_start = s.find(pattern) + pattern.size();

【讨论】:

以上是关于如何在 C++ 中搜索 std::string 中的子字符串?的主要内容,如果未能解决你的问题,请参考以下文章

如何从 std::string 执行“getline”?

如何从 std::string 中获取 2 个字符并将其转换为 C++ 中的 int?

GCC 如何连接多个 C++ std::string 变量?

如何使用 UTF-8 字符序列在 C++ 中初始化 const char* 和/或 const std::string?

C++ std::string::find_last_of()函数(在字符串中搜索与参数中指定的任何字符匹配的最后一个字符)(从后往前找)(文件路径中找文件名,/\兼容windows和linux)

C++ std::string::find_last_of()函数(在字符串中搜索与参数中指定的任何字符匹配的最后一个字符)(从后往前找)(文件路径中找文件名,/\兼容windows和linux)