2014-02-22 206 views
0

我一直在寻找关于我要问什么的问题和答案,但我仍然没有找到解决方法。如何从C++中的字符串中提取子字符串?

我有,我有,提取约几件事信息的文本文件,它们都具有以下格式:

"string1":"string2" 

而在这之后,有更多的信息,我的意思是:

文本文件是这样的:

LINE 1个 XXXXXXXXXXXXXXXXXXXXXXXXXXXX “字符串1”: “字符串2” XXXXXXXXXXXXXXXXXXXXXXXXXX “STRING3”: “串,4” XXXXXXXXXXXXXXXXXXXXXXXXXXXX ...( '\ n')

LINE 2 XXXXXXXXXXXXXXXXXXXXXXXXXXXX “STRING5”: “string6” XXXXXXXXXXXXXXXXXXXXXXXXXX “string7”:(代码示例中使用的字符串) “string8” XXXXXXXXXXXXXXXXXXXXXXXXXXXX ...

XXX表示不相关的信息,我不需要和theEntireString店所有单行信息,并非全部文本文件的信息。

我必须首先找到string1的内容并将string2的内容存储到另一个没有引号的字符串中。问题是,当我收到最后一个报价时,我不得不停下来,但我不知道如何做到这一点。我想我必须使用函数find()和substr(),但尽管反复尝试,我没有成功。

我所做的是这样的:

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

可是这样一来,我想我存入串最后一个引号和字符串的其余部分。

+0

你真的需要一个好的编程手册,并从基础知识开始....但是,查找需要一个你想要查找的字符串的参数(也许是“\”:\“”),并返回搜索字符串中的位置,其中的模式substr(不是substring)的起始位置后面跟着要选择的字符的数量,所以也许'std :: string string1 = theEntireString.substr(1,theEntireString.find(“\”:\“”) - 1 );' – niemiro

+0

O(n^2)if您使用模式匹配算法或类似方法扫描所有内容,O(n)。 –

回答

0

假设无论是键或值包含引号。以下将输出“:”后面的值。如果您在输入字符串中有多个键值对,您可以在循环中重复提取值字段,前提是您保留上次找到的实例的位置记录。

#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 
+0

你的解决方案是完美的,但在我的txt文件中,格式是** string data =“XXXXX”key“:”val“XXXXX”key1“:”val1“XXXXXXX”** instead ** string data =“XXXXX \”密钥\“:\”val \“XXXXX \”key1 \“:\”val1 \“XXXXXXX”** – user3145085

+0

请注意,反斜杠只用于转义引号。“”XXXXX \“键\ “:\”val \“XXXXX \”key1 \“:\”val1 \“XXXXXXX”'磁盘上将变为'string data =“XXXXX”key“:”val“XXXXX”key1“:”val1“XXXXXXX”在cxx代码中,如果修改代码以读取文件或从stdin中读取,您将看到。 – tinlyx

+0

同样,您也可以使用C++ 11原始字符串语法,即“string data = R”(XXXXX“key”:“ val“XXXXX”key1“:”val1“XXXXXXX)”;',它不需要转义特殊字符。 – tinlyx

0

两个步骤:

首先,我们必须找到:的位置和拼接字符串分为两个部分:

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); 
+0

但是这种方式在字符串“final_second”中存储了行的其余部分,并且在您重新输入最后一个引号时不会停止。我编辑了这个帖子解释说,对不起。 – user3145085

1

“find”函数只是给你匹配字符串的位置来得到你需要使用“subst”函数的结果字符串。试试这个

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

,将解决你的问题

祝您好运...

0
#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 
0

你不需要任何字符串操作。我希望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; 

的帮助不大,功能字符是:

template< char C > 
std::istream& Char(std::istream& in) 
{ 
    char c; 
    if(in >> c && c != C) 
     in.setstate(std::ios_base::failbit); 
    return in; 
} 
相关问题