之前总是习惯编写面向过程的程序,没有面向对象的思维,用这个文本查询程序作为一个面向对象的小练习. 用面向过程的方式很快就写完了,用面向对象实现的时候还是遇到不少小问题. 这个小程序实现了”打印文本中存在某单词所在的行”的功能:
代码语言:javascript复制root@yifei: ./textquery data.txt hello
查询到3个hello.
(line 2) ni hao a hello
(line 33) hello daming
(line 40 hello world.
面向过程实现文本查询程
代码语言:javascript复制#include <iostream>
#include <fstream>
#include <sstream>
#include <map>
#include <string>
#include <list>
#include <forward_list>
#include <deque>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <numeric>
#include <ctime>
#include <iterator>
#include <utility>
#include <memory>
using namespace std;
//判断文件名是否满足要求.
bool judgefilename(string filename){
string tail=".txt";
if(filename.compare(filename.size()-tail.size(),tail.size(),tail)==0){
return false;
}else{
cout<<"sorry,我只接受txt文件."<<endl;
return true;
}
}
//判断该行中是否含有要查询的文本
bool hasTextFromLine(string line,string querytext){
if(line.find(querytext,0)!=string::npos){
return true;
}else{
return false;
}
}
//打印查询结果
void printResult(map<int,string> &result,string querytext){
if(result.size()==0){
cout<<"查询到0个"<<querytext<<"."<<endl;
return ;
}
cout<<"查询到"<<result.size()<<"个"<<querytext<<endl;
for(auto a:result){
cout<<" (line ";
cout<<a.first<<") "<<a.second<<endl;
}
}
int main(int argc,char *argv[]){
/*
面向过程方法:
1.根据参数打开文件
2.读入文本并建立行号-那一行内容的map
3.查询含有结果的pair保存到map2中
4.输出map2的内容
*/
//变量定义
map<int,string> misfile;
map<int,string> misresult;
//输入参数判断
if(argc!=3){
cout<<"格式: <textquery> <filename> <text> ,请重新输入!"<<endl;
return -1;
}
string filename(argv[1]);
string text(argv[2]);
if(text.size()>100||judgefilename(filename)){
cout<<"参数错误! 请重新输入."<<endl;
return -2;
}
//读入文件 & 得出查询结果
ifstream is1(filename);
string tmp;
int linefile=1,lineresult=1;
while(getline(is1,tmp)){
misfile.insert({linefile,tmp}); linefile ;
if(hasTextFromLine(tmp,text)){
misresult.insert({lineresult,tmp});
lineresult ;
}
}
//输出查询结果
printResult(misresult,text);
return 0;
}
面向对象实现
代码语言:javascript复制//textquery.cpp
#include <iostream>
#include <fstream>
#include <sstream>
#include <map>
#include <string>
#include <list>
#include <forward_list>
#include <deque>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <numeric>
#include <ctime>
#include <iterator>
#include <utility>
#include <memory>
#include "TransactionProcess.h"
#include "QueryResult.h"//此头文件要在TextQuery.h前面
#include "TextQuery.h"
using namespace std;
/*
面向对象:
TransactionProcess:
私有成员:
int argc;
char *argv[];
成员函数:
判断参数;
TextQuery:
private:
存储整个文件的map<int,string>
QueryResult与TextQuery可以共享同一个map,所以使用shared_ptr
public:
空构造函数
使用文件名初始化
返回文件map的shared_ptr
读入string,查询之后返回vector<int>
QueryResult:
private:
string querytext 要查询的单词
shared_ptr<map<int,string>> misres_ptr 所有行的内容
vector<int> vires; 只标记拥有所查询单词的行号
public:
空构造函数
构造函数
打印结果的友元函数
*/
int main(int argc,char *argv[]){
TransactionProcess tranpro1(argc,argv);
if(tranpro1.judgeArg()==false) return -1;
shared_ptr<map<int,string>> smis=make_shared<map<int,string>>();
TextQuery tq(string(argv[1]),smis);
tq.textInput();
vector<int> vitmp=tq.returnResult(argv[2]);
QueryResult qr(argv[2],tq.returnFile(),vitmp);
printResult(qr);
return 0;
}
代码语言:javascript复制//TransactionProcess.h
#ifndef TRAN_PROC
#define TRAN_PROC
#include <iostream>
using namespace std;
class TransactionProcess{
private:
int argc;
char *argv[5];
public:
TransactionProcess()=default;
//TransactionProcess(int argc1,char *argv1[]):argc(argc1),argv(argv1) {}
TransactionProcess(int argc1,char *argv1[]);
bool judgeArg();
bool judgefilename(string filename);
};
TransactionProcess::TransactionProcess(int argc1,char *argv1[]){
argc=argc1;
for(int i=0;i<argc1;i ){
argv[i]=argv1[i];
}
}
bool TransactionProcess::judgeArg(){
//输入参数判断
if(argc!=3){
cout<<"格式: <textquery> <filename> <text> ,请重新输入!"<<endl;
return false;
}
string filename(argv[1]);
string text(argv[2]);
if(text.size()>100||judgefilename(filename)){
cout<<"参数错误! 请重新输入."<<endl;
return false;
}
return true;
}
//判断文件名是否满足要求.
bool TransactionProcess::judgefilename(string filename){
string tail=".txt";
if(filename.compare(filename.size()-tail.size(),tail.size(),tail)==0){
return false;
}else{
cout<<"sorry,我只接受txt文件."<<endl;
return true;
}
}
#endif
代码语言:javascript复制//TextQuery.h
#ifndef TEXTQUERY
#define TEXTQUERY
#include <iostream>
#include <memory>
#include <vector>
#include <string>
#include <map>
#include <fstream>
using namespace std;
class QueryResult;
class TextQuery{
private:
shared_ptr<map<int,string>> mis_ptr;
string textq;
public:
TextQuery()=default;
TextQuery(string str,shared_ptr<map<int,string>> ptr) : textq(str), mis_ptr(ptr) {}
void textInput();
shared_ptr<map<int,string>> returnFile();
vector<int> returnResult(string querytxt);
};
void TextQuery::textInput(){
ifstream fnameis(textq);
//读入文件
string tmp;
int linefile=1;
while(getline(fnameis,tmp)){
mis_ptr->insert({linefile,tmp}); linefile ;
}
}
shared_ptr<map<int,string>> TextQuery::returnFile(){
return mis_ptr;
}
vector<int> TextQuery::returnResult(string querytxt){
vector<int> vi1;
for(auto a:*mis_ptr){
if(a.second.find(querytxt)!=string::npos){
vi1.push_back(a.first);
}
}
return vi1;
}
#endif
代码语言:javascript复制//QueryResult.h
#ifndef QUERYRESULT
#define QUERYRESULT
#include <iostream>
#include <string>
#include <vector>
#include <memory>
#include <map>
using namespace std;
class QueryResult{
private:
string querytext;
shared_ptr<map<int,string>> misres_ptr;
vector<int> vires;
public:
QueryResult()=default;
QueryResult(string qt,shared_ptr<map<int,string>> misptr,vector<int> vi) :
querytext(qt),misres_ptr(misptr),vires(vi) {}
public:
friend void printResult(QueryResult &qr1);
};
//QueryResult::QueryResult(string qt,shared_ptr<map<int,string>> misptr,vector<int> vi){
//}
//打印查询结果
void printResult(QueryResult &qr1){
if(qr1.vires.size()==0){
cout<<"查询到0个"<<qr1.querytext<<"."<<endl;
return ;
}
cout<<"查询到"<<qr1.vires.size()<<"个"<<qr1.querytext<<endl;
for(auto a:qr1.vires){
cout<<" (line ";
cout<<a<<") "<<(*qr1.misres_ptr)[a]<<endl;
}
}
#endif
总结
头文件包含顺序 当ClassA.h中需要创建ClassB.h中的类的时候,如果a.cpp中需要包含以上两个头文件,那么在a.cpp中需要首先引用ClassB.h,然后再引用ClassA.h.
友元函数 1.友元函数可以访问类中的私有成员和其他数据,但是访问不可直接使用数据成员,需要通过对对象进行引用。 2.友元函数在调用上同一般函数一样,不必通过对对象进行引用。 3.一个类中的成员函数可以是另外一个类的友元函数,而且一个函数可以是多个类的友元函数。 4.类中通过使用关键字friend 来修饰友元函数,但该函数并不是类的成员函数,其声明可以放在类的私有部分,也可放在共有部分。友元函数的定义在类体外实现,不需要加类限定。
当不同的类可以共用数据时,可以利用shared_ptr智能指针来共享数据.
查找一个string中是否包含另一个string
代码语言:javascript复制if(stra.find(strb)!=string::npos){//该函数返回该串的位置
cout<<"存在该串"<<endl;
}else{
cout<<"不存在"<<endl;
}
欢迎与我分享你的看法。 转载请注明出处:http://taowusheng.cn/