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

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

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

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

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


逻辑很简单,知道一点字符串操作和文件操作就好。下面的代码可以实现你的要求,没有考虑异常处理,也没有过多考虑效率,需要的话你自己改改就好

#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 差不多。

授人以鱼不如授人以渔,我想给题主分享一下遇到这种问题的常规思路。

  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


用正则表达式就几行程序而已:

#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'
【热门文章】
【热门文章】