如何在C++中从字符串中提取子字符串

How to extract a substring from a string in C++?

本文关键字:字符串 提取 C++      更新时间:2023-10-16

关于我要问的问题,我已经找了上千个问题和答案,但我仍然没有找到方法来解释。

我有一个文本文件,我必须从中提取有关几件事的信息,所有这些都具有以下格式:

"string1":"string2"

在那之后,还有更多的信息,我的意思是:

文本文件是这样的:

第1行XXXXXXXXXXXXXXXXXXXXXX"字符串1":"字符串2"XXXXXXXXXXXXXXXXXXXXXXXX"字符串3":"串4"XXXXXXXXXXXXXXXX。。。('\n')

第2行XXXXXXXXXXXXXXXXXXXXXX"字符串5":"字符串6"XXXXXXXXXXXXXXXXXX"字符串7":"串8"XXXXXXXXXXXXXXXX。。。

XXX表示我不需要的无关信息,EntireString(代码示例中使用的字符串)存储单行的所有信息,而不是文本文件的所有信息。

我必须先找到字符串1的内容,然后将字符串2的内容存储到另一个没有引号的字符串中。问题是,当我到达最后一句话时,我不得不停下来,我不知道该怎么做。我想我必须使用函数find()和substr(),但尽管我反复尝试,还是没有成功。

我所做的事情是这样的:

string extractInformation(string theEntireString)
{
string s = ""string1":"";    
string result = theEntireString.find(s);
return result;
}

但通过这种方式,我想我将最后一句引号和字符串的其余部分存储到字符串中。

"查找";函数只是给你匹配字符串的位置,以获得你需要使用";子";作用试试这个

string start,end;
start = theEntireString.substr(1,theEntireString.find(":")-2);
end = theEntireString.substr(theEntireString.find(":")+2,theEntireString.size()-1);

这将解决你的问题

假设键或值包含引号。以下将输出":"之后的值。如果输入字符串中有多个键值对,您也可以在循环中使用它来重复提取值字段,前提是您要记录最后找到的实例的位置。

#include <iostream>
using namespace std;
string extractInformation(size_t p, string key, const string& theEntireString)
{
string s = """ + key +"":"";
auto p1 = theEntireString.find(s);
if (string::npos != p1)
p1 += s.size();
auto p2 = theEntireString.find_first_of('"',p1);
if (string::npos != p2)
return theEntireString.substr(p1,p2-p1);
return "";
}
int main() {
string data = ""key":"val" "key1":"val1"";
string res = extractInformation(0,"key",data);
string res1 = extractInformation(0,"key1",data);
cout << res << "," << res1 << endl;
}

输出:

val,val1

两个步骤:

首先,我们必须找到:的位置,并将字符串拼接成两部分:

string first = theEntireString.substr(0, theEntireString.find(":"));
string second = theEntireString.substr(theEntireString.find(":") + 1);

现在,我们必须删除"":

string final_first(first.begin() + 1, first.end() - 1);
string final_second(second.begin() + 1, second.end() - 1);

您不需要任何字符串操作。我希望XXXXX不包含任何",所以你可以直接从文件中读取这两个字符串:

ifstream file("input.txt");
for( string s1,s2; getline( getline( file.ignore( numeric_limits< streamsize >::max(), '"' ), s1, '"' ) >> Char<':'> >> Char<'"'>, s2, '"' ); )
cout << "S1=" << s1 << " S2=" << s2 << endl;

小帮助函数Char是:

template< char C >
std::istream& Char( std::istream& in )
{
char c;
if( in >> c && c != C )
in.setstate( std::ios_base::failbit );
return in;
}
#include <regex>
#include <iostream>
using namespace std;
const string text = R"(
XXXXXXXXXXXXXXXXXXXXXXXXXXXX"string1":"string2"XXXXXXXXXXXXXXXXXXXXXXXXXX"string3"  :"string4" XXXXXXXXXXXXXXXXXXXXXXXXXXXX...
XXXXXXXXXXXXXXXXXXXXXXXXXXXX"string5":  "string6"XXXXXXXXXXXXXXXXXXXXXXXXXX"string7"  :  "string8" XXXXXXXXXXXXXXXXXXXXXXXXXXXX...
)";
int main() {
const regex pattern{R"~("([^"]*)"s*:s*"([^"]*)")~"};
for (auto it = sregex_iterator(begin(text), end(text), pattern); it != sregex_iterator(); ++it) {
cout << it->format("First: $1, Second: $2") << endl;
}
}
Output:
First: string1, Second: string2
First: string3, Second: string4
First: string5, Second: string6
First: string7, Second: string8
  • 运行(使用clang和libc++):http://coliru.stacked-crooked.com/a/f0b5fd383bc227fc
  • 这就是原始字符串文字在理解它们的编辑器中的样子:http://bl.ocks.org/anonymous/raw/9442865/