zl程序教程

您现在的位置是:首页 >  其他

当前栏目

面向过程与面向对象_文本查询程序

程序 查询 过程 文本 面向对象 面向
2023-06-13 09:15:03 时间

之前总是习惯编写面向过程的程序,没有面向对象的思维,用这个文本查询程序作为一个面向对象的小练习. 用面向过程的方式很快就写完了,用面向对象实现的时候还是遇到不少小问题. 这个小程序实现了”打印文本中存在某单词所在的行”的功能:

root@yifei: ./textquery data.txt hello
查询到3个hello.
	(line 2) ni hao a hello
	(line 33) hello daming
	(line 40 hello world.

面向过程实现文本查询程

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

面向对象实现

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

if(stra.find(strb)!=string::npos){//该函数返回该串的位置
	cout<<"存在该串"<<endl;
}else{
	cout<<"不存在"<<endl;
}

欢迎与我分享你的看法。 转载请注明出处:http://taowusheng.cn/