搜尋

首頁  >  問答  >  主體

如何C++抽取txt中某指定内容并保存到另外一个txt中?

A文件中,内容是这样的:

[fullText]abcd[rating]
[fullText]efg[rating]

我想要抽取[fullText] [rating]之间的内容,并将其保存到B文件中,
不同标签对的内容用空格隔开。
应该怎么写呢?

怪我咯怪我咯2804 天前612

全部回覆(3)我來回復

  • 黄舟

    黄舟2017-04-17 11:50:06

    思路和 @snailcoder 差不多。

    授人以魚不如授人以漁,我想給題主分享一下遇到這種問題的常規思路。

    1. 先觀察 [fullText]efg[rating] 的結構,顯然它是由前後兩個標籤夾住中間的內容。那麼要提取特定標籤中間的內容,肯定有一個字串匹配的過程。

    2. 為了更方便匹配字串,若能將[fullText]efg[rating] 分離成fullTextefgrating 這三個部分,然後匹配第一和第三個字符串,若匹配上,則提取第二個字串。

    3. 最基本的檔案操作,依行讀取 A.txt,將結果置入 B.txt,以空格分隔。


    細分一下,有以下重點功能:

    1. 讀寫檔案
    2. 分割字串

    對於 2,建議題主看一下我曾經總結過的一篇文章:字串分割技術。對於 1,則是 C++ 的基本運算。

    寫一個簡單的 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;
    }
    

    其中字串分割,我就直接用上面提到的文章裡的函數了:

    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;
    }
    

    最後你可以呼叫 pickup 來偵測是否產生符合要求的 B.txt:

    cppint main()
    {
        if ( pickup("A.txt", "B.txt", "fullText", "rating") )
            std::cout << "pickup success!" << std::endl;
    }
    

    完整程式碼請見:https://gist.github.com/pezy/7d9fb9fa74eebe819eba

    回覆
    0
  • 天蓬老师

    天蓬老师2017-04-17 11:50:06

    用正規表示式就幾行程式而已:

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

    回覆
    0
  • PHPz

    PHPz2017-04-17 11:50:06

    邏輯很簡單,知道一點字串操作和檔案操作就好。下面的程式碼可以實現你的要求,沒有考慮異常處理,也沒有過多考慮效率,需要的話你自己改改就好

    #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;
    }
    

    回覆
    0
  • 取消回覆