1. 未封装版本
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <map>
#include <algorithm>

using namespace std;

map<int, const string> readText(ifstream &f) {
    int pos = 1;
    string tmp;
    map<int, const string> text;
    while (getline(f, tmp)) {
        text.emplace(pos, tmp);
        ++pos;
    }
    if (text.empty()) {
        cout << "empty file" << endl;
    }
    return text;
}

int search(const string target, map<int, const string> &m, map<int, const string> &result) {
    int line = 1;
    int times = 0;
    for (const auto i:m) {
        auto pos = i.second.find(target);
        if (pos != string::npos) {
            result.emplace(line, i.second);
            ++times;
        }
        ++line;
    }
    return times;
}

int main() {
    ifstream f("test.txt");
    if (f) {
        cout << "Enter the target" << endl;
        string target;
        cin >> target;
        map<int, const string> content = readText(f);
        map<int, const string> result;
        int times = search(target, content, result);

        cout << "The result: " << endl;
        for (const auto i:result) {
            cout << "The word occurs " << times << " times" << endl;
            cout << "Occur at line " << i.first << " with string: " << i.second << endl;
        }
    } else {
        cout << "cannot open file" << endl;
        exit(1);
    }
}
  1. 使用TextQuery和QueryResult封装版本
    TextQuery.h
#pragma once
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <memory>
#include "QueryResult.h"

using namespace std;

class QueryResult;

class TextQuery {
public:
    using line_no = vector<string>::size_type;
    TextQuery(ifstream &f);
    QueryResult query(const string &s) const;
private:
    map<string, shared_ptr<set<line_no>>> m_vm;
    shared_ptr<vector<string>> m_text;
};

TextQuery.cpp

#include "stdafx.h"
#include <sstream>
#include "TextQuery.h"

TextQuery::TextQuery(ifstream &f)
   :m_text(new vector<string>) {
    string tmp;
    line_no pos = 1;
    while (getline(f, tmp)) {
        m_text->push_back(tmp);
        stringstream line(tmp);
        string word;
        while (line >> word) {
            auto &lines = m_vm[word]; // fuck this shit,要用引用类型,否则m_vm的second一直为空
            if (!lines) {
                lines.reset(new set<line_no>);
            }
            lines->insert(pos);
        }
        ++pos;
    }
}

QueryResult TextQuery::query(const string &s) const {
   shared_ptr<set<line_no>> nodata(new set<line_no>());
    auto itr = m_vm.find(s);
    if (itr == m_vm.end()) {
       return QueryResult(s, m_text, nodata);
    } else {
        return QueryResult(s, m_text, itr->second);
    }
}

QueryResult.h

#pragma once
#include <iostream>
#include <string>
#include <map>
#include <set>
#include <vector>
#include <memory>

using namespace std;

class QueryResult {
   friend ostream& print(std::ostream&, const QueryResult&);
public:
    using line_no = vector<string>::size_type;
    QueryResult(const string target, shared_ptr<vector<string>> sv, shared_ptr<set<line_no>> ss);
private:
    string m_target;
    shared_ptr<vector<string>> m_text;
    shared_ptr<set<line_no>> m_lines;
};

QueryResult.cpp

#include "stdafx.h"
#include "QueryResult.h"

ostream& print(std::ostream &os, const QueryResult &r) {
    os << "The word: " << r.m_target << endl;
    os << "Occur at line: " << endl;
    for (const auto i:*(r.m_lines)) {
        os << i << " with string: " << *(r.m_text->begin() + i - 1) << endl; // vector的索引和文本的行号相差1,此处需要减去1,否则vector解引用会越界
    }
    return os;
}

QueryResult::QueryResult(const string target, shared_ptr<vector<string>> text, shared_ptr<set<line_no>> lines)
    : m_target(target), m_text(text), m_lines(lines) {}

main.cpp

// query.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
#include "TextQuery.h"
#include "QueryResult.h"

using namespace std;

int main()
{
   ifstream f("test.txt");
   if (f) {
      string target;
      TextQuery t(f);
      cout << "Please enter the target" << endl;
      while (cin >> target) {
         QueryResult q = t.query(target);
         print(cout, q);
      }
   }
   else {
      cout << "Cannot open file" << endl;
      exit(1);
   }

    return 0;
}
  1. 配合StrBlob及StrBlobPtr一起使用
    QueryResult .h
#pragma once
#include <iostream>
#include <string>
#include <map>
#include <set>
#include <vector>
#include <memory>
#include "StrBlob.h"

using namespace std;

class QueryResult {
   friend ostream& print(std::ostream&, QueryResult&);
public:
    using line_no = vector<string>::size_type;
    QueryResult(const string target, StrBlob text, shared_ptr<set<line_no>> lines);
    set<line_no>::iterator begin();
    set<line_no>::iterator end();
    shared_ptr<vector<string>> get_file();
private:
    string m_target;
    StrBlob m_text;
    shared_ptr<set<line_no>> m_lines;
};

QueryResult .cpp

#include "stdafx.h"
#include "QueryResult.h"
#include "StrBlobPtr.h"

ostream& print(std::ostream &os, QueryResult &r) {
    os << "The word: " << r.m_target << endl;
    os << "Occur at line: " << endl;
    for (const auto i:*(r.m_lines)) {
        os << i << " with string: " << r.m_text.off(i - 1).deref() << endl;
        cout << "=======================================================================" << endl;
    }
    return os;
}

QueryResult::QueryResult(const string target, StrBlob text, shared_ptr<set<line_no>> lines)
    : m_target(target), m_text(text), m_lines(lines) {}
set<line_no>::iterator QueryResult::begin() {
	return m_lines->begin();
}
set<line_no>::iterator QueryResult::end() {
	return m_lines->begin();
}
shared_ptr<vector<string>> QueryResult::get_file() {
	return m_text;
}

TextQuery .h

#pragma once
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <memory>
#include "QueryResult.h"
#include "StrBlob.h"

using namespace std;

class QueryResult;

class TextQuery {
public:
    using line_no = vector<string>::size_type;
    TextQuery(ifstream &f);
    QueryResult query(const string &s) const;
private:
    map<string, shared_ptr<set<line_no>>> m_vm;
    StrBlob m_text;
};

TextQuery.cpp

#include "stdafx.h"
#include <sstream>
#include "TextQuery.h"

TextQuery::TextQuery(ifstream &f)
   :m_text() {
    string tmp;
    line_no pos = 1;
    while (getline(f, tmp)) {
        m_text.push_back(tmp);
        stringstream line(tmp);
        string word;
        while (line >> word) {
            auto &lines = m_vm[word];
            if (!lines) {
                lines.reset(new set<line_no>);
            }
            lines->insert(pos);
        }
        ++pos;
    }
}

QueryResult TextQuery::query(const string &s) const {
    shared_ptr<set<line_no>> nodata(new set<line_no>());
    auto itr = m_vm.find(s);
    if (itr == m_vm.end()) {
       return QueryResult(s, m_text, nodata);
    } else {
        return QueryResult(s, m_text, itr->second);
    }
}

StrBlob.h

#pragma once
#include <iostream>
#include <vector>
#include <string>
#include <memory>

class StrBlobPtr;

class StrBlob {
public:
   typedef std::vector<std::string>::size_type size_type;
   StrBlob();
   StrBlob(std::initializer_list<std::string> il);
   size_type size() { return data->size(); }
   const size_type size() const { return data->size(); }
   bool empty() { return data->empty(); }
   void push_back(const std::string &s) { data->push_back(s); }
   void pop_back();
   std::string& front();
   const std::string& front() const;
   std::string& back();
   const std::string& back() const;

   friend class StrBlobPtr;
   StrBlobPtr begin(); // 不建议将实现写在此处,会造成"incomplete type is not allowed" error
   StrBlobPtr end();
   StrBlobPtr off(size_t);
private:
   std::shared_ptr<std::vector<std::string>> data;
   void check(size_type i, const std::string &msg) const;
};

StrBlob.cpp

#include "stdafx.h"
#include <stdexcept> // out_of_range
#include "StrBlob.h"
#include "StrBlobPtr.h"

StrBlob::StrBlob() {
   data = std::make_shared<std::vector<std::string>>();
}

StrBlob::StrBlob(std::initializer_list<std::string> il) {
   data = std::make_shared<std::vector<std::string>>(il);
}

void StrBlob::check(size_type i, const std::string &msg) const {
   if (i >= data->size()) {
      throw std::out_of_range(msg);
   }
}

void StrBlob::pop_back() {
   check(0, "pop_back on empty StrBlob");
   data->pop_back();
}

std::string& StrBlob::front() {
   check(0, "front on empty StrBlob");
   return data->front();
}

const std::string& StrBlob::front() const {
   check(0, "front on empty StrBlob");
   return data->front();
}

std::string& StrBlob::back() {
   check(0, "back on empty StrBlob");
   return data->back();
}

const std::string& StrBlob::back() const {
   check(0, "back on empty StrBlob");
   return data->back();
}

StrBlobPtr StrBlob::begin() { return StrBlobPtr(*this); }
StrBlobPtr StrBlob::end() { return StrBlobPtr(*this, data->size()); }
StrBlobPtr StrBlob::off(size_t i) { return StrBlobPtr(*this, i); }

StrBlobPtr.h

#pragma once
#include <memory>
#include <vector>
#include "StrBlob.h" // 有#program once的存在,不用担心重复定义的问题

class StrBlobPtr
{
public:
   StrBlobPtr() :curr{ 0 } {}
   StrBlobPtr(StrBlob &a, size_t sz = 0)
      : wptr(a.data), curr(sz) {}
   ~StrBlobPtr() {};
   std::string &deref() const;
   StrBlobPtr &incr();
   friend bool eq(const StrBlobPtr &lhs, const StrBlobPtr &rhs);
private:
   std::shared_ptr<std::vector<std::string>> check(std::size_t, const std::string&) const;
   std::weak_ptr<std::vector<std::string>> wptr;
   std::size_t curr;
};

StrBlobPtr.cpp

#include "stdafx.h"
#include "StrBlobPtr.h"
#include <exception>

std::string & StrBlobPtr::deref() const {
   auto p = check(curr, "Dereference past the end");
   return (*p)[curr];
}
StrBlobPtr & StrBlobPtr::incr() {
   check(curr, "Increment past the end");
   ++curr;
   return *this;
}

std::shared_ptr<std::vector<std::string>> StrBlobPtr::check(std::size_t sz, const std::string &msg) const {
   auto p = wptr.lock();
   if (p) {
      if (p->size() > sz) {
         return p;
      }
      else {
         throw std::out_of_range(msg);
      }
   }
   else {
      throw std::runtime_error("unbound StrBlobPtr");
   }
}

bool eq(const StrBlobPtr &lhs, const StrBlobPtr &rhs) {
   auto lp = lhs.wptr.lock(), rp = rhs.wptr.lock();
   if (lp == rp) {
      return (!lp || lhs.curr == rhs.curr);
   }
   else {
      return false;
   }
}

test.txt

Oscar Fingal O’Flahertie Wills Wilde (16 October 1854 - 30 November 1900) was an Irish writer, poet, and prominent aesthete who, after writing in different forms throughout the 1880s, became one of London’s most popular playwrights in the early 1890s. Today he is remembered for his epigrams, plays and the tragedy of his imprisonment, followed by his early death.
Wilde’s parents were successful Dublin intellectuals and from an early age he was tutored at home, where he showed his intelligence, becoming fluent in French and German. He attended boarding school for six years, then matriculated to university at seventeen years of age. Reading Greats, Wilde proved himself to be an outstanding classicist, first at Dublin, then at Oxford. His intellectual horizons were broad: he was deeply interested in the rising philosophy of aestheticism (led by two of his tutors, Walter Pater and John Ruskin) though he also profoundly explored Roman Catholicism and finally converted on his deathbed.
After university Wilde moved to London, into fashionable cultural and social circles. As a spokesman for aestheticism, he tried his hand at various literary activities; he published a book of poems, lectured America and Canada on the new “English Renaissance in Art” and then returned to London to work prolifically as a journalist for four years. Known for his biting wit, flamboyant dress, and glittering conversation, Wilde was one of the best known personalities of his day. At the turn of the 1890s, he refined his ideas about the supremacy of art in a series of dialogues and essays; though it was his only novel, The Picture of Dorian Gray, which began a more lasting oeuvre. The opportunity to construct aesthetic details precisely, combined with larger social themes, drew Wilde to writing drama. He wrote Salome in French in Paris in 1891, but it was refused a licence. Unperturbed, Wilde produced four society comedies in the early 1890s, which made him one of the most successful playwrights of late Victorian London.
At the height of his fame and success, whilst his masterpiece, The Importance of Being Earnest, was still on stage in London, Wilde sued his lover’s father for libel. After a series of trials, Wilde was convicted of gross indecency with other men and imprisoned for two years, held to hard labour. In prison he wrote De Profundis, a long letter which discusses his spiritual journey through his trials, forming a dark counterpoint to his earlier philosophy of pleasure. Upon his release he left immediately for France, never to return to Ireland or Britain. There he wrote his last work, The Ballad of Reading Gaol, a long poem commemorating the harsh rhythms of prison life. He died destitute in Paris at the age of forty-six.

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐