84669 personnes étudient
152542 personnes étudient
20005 personnes étudient
5487 personnes étudient
7821 personnes étudient
359900 personnes étudient
3350 personnes étudient
180660 personnes étudient
48569 personnes étudient
18603 personnes étudient
40936 personnes étudient
1549 personnes étudient
1183 personnes étudient
32909 personnes étudient
A文件中,内容是这样的:
[fullText]abcd[rating] [fullText]efg[rating]
我想要抽取[fullText] [rating]之间的内容,并将其保存到B文件中, 不同标签对的内容用空格隔开。 应该怎么写呢?
[fullText] [rating]
走同样的路,发现不同的人生
思路和 @snailcoder 差不多。
授人以鱼不如授人以渔,我想给题主分享一下遇到这种问题的常规思路。
先观察 [fullText]efg[rating] 的结构,显然它是由前后两个标签夹住中间的内容。那么要提取特定标签中间的内容,肯定有一个字符串匹配的过程。
[fullText]efg[rating]
为了更方便匹配字符串,若能将 [fullText]efg[rating] 分离成 fullText、efg、rating 这三个部分,然后匹配第一和第三个字符串,若匹配上,则提取第二个字符串。
fullText
efg
rating
最基本的文件操作,按行读取 A.txt,将结果置入 B.txt,按空格分隔。
细分一下,有如下重点功能:
对于 2,建议题主看一下我曾经总结过的一篇文章:字符串分割技术。对于 1,则是 C++ 的基本操作。
写一个简单的 pickup 函数:
pickup
cppbool pickup(const string &source, const string &dest, const string &label_front, const string &label_back) { ifstream ifs( source ); if ( ifs.fail() ) return false; ofstream ofs( dest ); if ( ofs.fail() ) return false; for ( string line; std::getline(ifs, line); ) { vector<string> content; if ( 3 == split( line, "[]", content ).size() && content[0] == label_front && content[2] == label_back ) ofs << content[1] << " "; } return true; }
cpp
bool pickup(const string &source, const string &dest, const string &label_front, const string &label_back) { ifstream ifs( source ); if ( ifs.fail() ) return false; ofstream ofs( dest ); if ( ofs.fail() ) return false; for ( string line; std::getline(ifs, line); ) { vector<string> content; if ( 3 == split( line, "[]", content ).size() && content[0] == label_front && content[2] == label_back ) ofs << content[1] << " "; } return true; }
其中字符串分割,我就直接用上面提到的文章里的函数了:
cppvector<string> &split( const string &str, const string &delimiters, vector<string> &elems, bool skip_empty = true ) { string::size_type pos, prev = 0; while ( ( pos = str.find_first_of(delimiters, prev) ) != string::npos ) { if ( pos > prev ) { if ( skip_empty && 1 == pos - prev ) break; elems.emplace_back( str, prev, pos - prev ); } prev = pos + 1; } if ( prev < str.size() ) elems.emplace_back( str, prev, str.size() - prev ); return elems; }
vector<string> &split( const string &str, const string &delimiters, vector<string> &elems, bool skip_empty = true ) { string::size_type pos, prev = 0; while ( ( pos = str.find_first_of(delimiters, prev) ) != string::npos ) { if ( pos > prev ) { if ( skip_empty && 1 == pos - prev ) break; elems.emplace_back( str, prev, pos - prev ); } prev = pos + 1; } if ( prev < str.size() ) elems.emplace_back( str, prev, str.size() - prev ); return elems; }
最后你可以调用 pickup 来检测是否生成符合要求的 B.txt:
cppint main() { if ( pickup("A.txt", "B.txt", "fullText", "rating") ) std::cout << "pickup success!" << std::endl; }
int main() { if ( pickup("A.txt", "B.txt", "fullText", "rating") ) std::cout << "pickup success!" << std::endl; }
完整代码请见:https://gist.github.com/pezy/7d9fb9fa74eebe819eba
用正则表达式就几行程序而已:
#include <iostream> #include <regex> int main() { std::regex r("\\[fullText\\](.*)\\[rating\\]"); std::string l; while(std::cin) { std::getline(std::cin, l); std::cout << std::regex_replace(l, r, "$1\n"); } }
如果你不纠结一定要用C++,那可以更短:
perl -pe 's/\[fullText\](.*)\[rating\]/$1/g'
逻辑很简单,知道一点字符串操作和文件操作就好。下面的代码可以实现你的要求,没有考虑异常处理,也没有过多考虑效率,需要的话你自己改改就好
#include <iostream> #include <fstream> #include <string> using namespace std; class Solution { public: int ProcessFile(const string &src_file, const string &dest_file, const string &head, const string &end) { ifstream input(src_file.c_str(), ifstream::in); if (!input) { return -1; } ofstream output(dest_file.c_str(), ofstream::out); if (!output) { return -1; } string line; string ::size_type head_len = head.length(); while(getline(input, line)) { string::size_type head_pos = line.find(head, 0); string::size_type end_pos = line.find(end, head_pos + head_len); output << line.substr(head_pos + head_len, end_pos - head_pos - head_len) << ' '; } input.close(); output.close(); return 0; } }; int main() { string src_file = "input.txt", dest_file = "output.txt"; string head_name = "[fullText]", end_name = "[rating]"; Solution sln; if (sln.ProcessFile(src_file, dest_file, head_name, end_name) < 0) { cout << "Fail..." << endl; } else { cout << "Success..." << endl; } return 0; }
思路和 @snailcoder 差不多。
授人以鱼不如授人以渔,我想给题主分享一下遇到这种问题的常规思路。
先观察
[fullText]efg[rating]
的结构,显然它是由前后两个标签夹住中间的内容。那么要提取特定标签中间的内容,肯定有一个字符串匹配的过程。为了更方便匹配字符串,若能将
[fullText]efg[rating]
分离成fullText
、efg
、rating
这三个部分,然后匹配第一和第三个字符串,若匹配上,则提取第二个字符串。最基本的文件操作,按行读取 A.txt,将结果置入 B.txt,按空格分隔。
细分一下,有如下重点功能:
对于 2,建议题主看一下我曾经总结过的一篇文章:字符串分割技术。对于 1,则是 C++ 的基本操作。
写一个简单的
pickup
函数:其中字符串分割,我就直接用上面提到的文章里的函数了:
最后你可以调用
pickup
来检测是否生成符合要求的 B.txt:完整代码请见:https://gist.github.com/pezy/7d9fb9fa74eebe819eba
用正则表达式就几行程序而已:
如果你不纠结一定要用C++,那可以更短:
逻辑很简单,知道一点字符串操作和文件操作就好。下面的代码可以实现你的要求,没有考虑异常处理,也没有过多考虑效率,需要的话你自己改改就好