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, "\n"); } }
如果你不糾結一定要用C++,那可以更短:
perl -pe 's/\[fullText\](.*)\[rating\]//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++,那可以更短:
邏輯很簡單,知道一點字串操作和檔案操作就好。下面的程式碼可以實現你的要求,沒有考慮異常處理,也沒有過多考慮效率,需要的話你自己改改就好