c++ primer( 文本查询程序)
读取用户指定的任意文本文件,然后允许用户从该文件查找单词,查询的结果是该单词出现的次数,并列出每次出现所在的行,如果某单词在同一行中多次出现,程序将只显示改行的一次。行号按升序显示(int main()&&int main(int argc,char**argv)的区别算是了解了,但是跟int mian(int argc,char**argv){}中的文件操作还不熟悉,所以文件读取出现异常还不知道从哪里处理)【原来是中文字符不可以】
code:
//使用以vector容器存储行号的textQuery类
#include "TextQuery.h" string make_plural(size_t,const string&,const string&);
ifstream &open_file(ifstream&,const string&);
void print_results(const vector<TextQuery::line_no>& locs,
const string& sought,const TextQuery &file)
{
//如果找到单词sought,则输出该单词出现的行数
typedef vector<TextQuery::line_no >line_nums;
line_nums::size_type size=locs.size();
cout<<"\n"<<sought<<"occurs"<<size<<" "
<<make_plural (size,"time","s")<<endl; //输出出现该单词的每一行
line_nums::const_iterator it=locs.begin();
for(;it!=locs.end();++it){
cout<<"\t(line "<<(*it)+<<")"<<file.text_line (*it)<<endl;
}
} //main函数接受文件名为参数
int main(int argc,char**argv)
{
//open the file from which user will query words
//char fileName[]="h:\\test.txt";
ifstream infile;
if(argc<||!open_file(infile,argv[])){
cerr<<"No input file"<<endl;
cout<<"to here1";
system("pause");
return EXIT_FAILURE;
} TextQuery tq;
tq.read_file(infile); //建立容器map //循环接受用户的查询要求并输出结果
while(true){
cout<<"enter word to look for,or q to quit:";
string s;
cin>>s; //将s变为小写
string ret;
for(string::const_iterator it=s.begin();it!=s.end();++it){
ret+=tolower(*it);
}
s=ret; //如果用户输入文件结束符或字符‘q’及‘Q’,则结束循环
if(!cin||s=="q"||s=="Q") break; //获取出现所查询单词所有行的行号
vector<TextQuery::line_no>locs=tq.run_query (s); //输出出现次数及所有相关文本行
print_results(locs,s,tq); }
system("pause");
}
Main.cpp
#include "TextQuery.h"
#include<sstream> string TextQuery::text_line(line_no line)const
{
if(line<lines_of_text.size())
return lines_of_text[line];
throw out_of_range("line number out of range");
} //读输入文件,将每行存储为lines_of_text的一个元素
void TextQuery::store_file (ifstream &is)
{
string textline;
while(getline(is,textline))
lines_of_text.push_back (textline);
} //在输入vector中找以空白为间隔的单词
//将单词以及出现该单词的行的行号一起放入word_map
void TextQuery ::build_map ()
{
//处理输入vector中的每一行
for(line_no line_num=;line_num!=lines_of_text.size();++line_num)
{
//一次读一个单词
istringstream line(lines_of_text[line_num]);
string word;
while(line>>word){
//去掉标点
word=cleanup_str(word);
//将行号加入到vector容器中
if(word_map.count(word)==)//该单词不在map容器中
//下标操作将加入该单词
word_map[word].push_back (line_num);
else{
if(line_num!=word_map[word].back())
//行号与vector容器中最后一个元素不相等
word_map[word].push_back (line_num);
}
}
}
} vector<TextQuery::line_no>
TextQuery::run_query(const string &query_word)const
{
//注意,为了避免在word_map中加入单词,使用find函数而不用下标操作
map<string,vector<line_no> >::const_iterator
loc=word_map.find(query_word);
if(loc==word_map.end())
return vector<line_no>(); //找不到,返回空的vector对象
else
//获取并返回与该单词关联的行号vector对象
return loc->second ;
} //去掉标点并将字母变成小写
string TextQuery::cleanup_str (const string &word)
{
string ret;
for(string::const_iterator it=word.begin();it!=word.end();++it){
if(!ispunct(*it))
ret+=tolower(*it);
}
return ret;
} //定义函数make_plural 和open_file的源文件如下:
//function.cpp
//定义函数make_plural和open_file #include<fstream>
#include<string> using namespace std;
//如果ctr不为1,返回word的复数版本
string make_plural(size_t ctr,const string &word,const string &ending)
{
return (ctr==)?word:word+ending;
} //打开输入文件流in并绑定到给定的文件
ifstream &open_file(ifstream &in,const string&file)
{
in.close(); //close in case it was already open
in.clear(); //clear any existing errors
//if the open fails,the stream will be in an invalid state
in.open(file.c_str ());
return in ; //condition state is good if open succeeded
}
TextQuery.cpp
#ifndef TEXTQUERY_H
#define TEXTQUERY_H
#include<string>
#include<vector>
#include<map>
#include<iostream>
#include<fstream>
#include<cstring>
#include<cctype> using namespace std; class TextQuery{
public:
typedef string::size_type str_size;
typedef vector<string>::size_type line_no; //接口:
//read_file建立给定文件的内部数据结构
void read_file(ifstream &is)
{store_file(is);build_map();} //run_query查询给定单词并返回该单词所在行的行号集合
vector<line_no> run_query(const string&)const; //text_line返回输入文件中指定行号对应的行
string text_line(line_no) const;
private:
//read_file所用到辅助函数
void store_file(ifstream&); //存储输入文件
void build_map(); //将每个单词与一个行号集合相关联 //保存输入文件
vector<string> lines_of_text; //将单词与出现该单词的行的行号集合相关联
map<string,vector<line_no> >word_map; //去掉标点并将字母变成小写
static std::string cleanup_str(const std::string&);
};
#endif
TextQuery.h
c++ primer( 文本查询程序)的更多相关文章
- C++ Primer 学习笔记_38_STL实践与分析(12)--集成的应用程序容器:文本查询程序
STL实践与分析 --容器的综合应用:文本查询程序 引言: 本章中最重点的实例.由于不须要用到multiset与multimap的内容.于是将这一小节提到了前面.通过这个实例程序,大师分析问题的智慧, ...
- C++ 容器的综合应用的一个简单实例——文本查询程序
C++ 容器的综合应用的一个简单实例——文本查询程序 [0. 需求] 最近在粗略学习<C++ Primer 4th>的容器内容,关联容器的章节末尾有个很不错的实例.通过实现一个简单的文本查 ...
- C++ Primer第四版 15.9 再谈文本查询 程序实现
编程过程中发现书本中的示例程序并不完全,某些地方存在错误,现已改正并添加少许注释.. 1 #include<iostream> 2 #include<fstream> #inc ...
- C++ Primer : 第十二章 : 文本查询程序
C++ Primer书上这个例子讲的很不错,写写帮助自己理解标准库和智能指针. .h 文件内容 #include <fstream> #include <iostream> # ...
- C++Primer笔记——文本查询程序(原创,未使用类)
#include <iostream> #include <vector> #include <set> #include <map> #include ...
- C++ Primer中文本查询演示样例Query的实现
近期在看C++ Primer复习C++的语法,看到书中15.9章中的文本查询演示样例时,认为设计得非常不错,于是便动手照着实现了一个,改动了非常久最终执行成功了,从中也学习到了非常多的语法.以下把实现 ...
- c/c++ 继承与多态 文本查询的小例子(非智能指针版本)
问题:在上一篇继承与多态 文本查询的小例子(智能指针版本)在Query类里使用的是智能指针,只把智能指针换成普通的指针,并不添加拷贝构造方法,会发生什么呢? 执行时,代码崩掉. 分析下面一行代码: Q ...
- c/c++ 继承与多态 文本查询的小例子(智能指针版本)
为了更好的理解继承和多态,做一个文本查询的小例子. 接口类:Query有2个方法. eval:查询,返回查询结果类QueryResult rep:得到要查询的文本 客户端程序的使用方法: //查询包含 ...
- 第七篇T语言实例开发,文本与程序的几种打开方法(版5.3)
文本与程序的几种打开方法 文本文件的打开方法 函数名: cmd 命令 函数描述: 执行CMD命令 函数原型: cmd(cmdstr) 命令(cmd命令) 函数参数: cmdstr:cmd命令,此处执行 ...
随机推荐
- objc非主流代码技巧
原文:http://blog.sunnyxx.com/2014/08/02/objc-weird-code/ [娱乐向]objc最短的方法声明 先来个娱乐向的.方法声明时有一下几个trick: 返回值 ...
- Flas-SQLAchemy数据库操作使用学习笔记
Flas-SQLAchemy数据库操作使用学习笔记 Flask-SQLALchemy 是一个给你的应用添加 SQLALchemy 支持的 Flask 扩展.SQLALchemy 是Python语言的S ...
- 搭建完整邮件系统(postfix+dovecot+clamAV+Spamassassin+amavisd-new)
============================ 相关软件: 1. 发送邮件 --- postfix 2. 身份认证 --- sasl2 3. 接收邮件 --- dovecot 4. 防病毒邮 ...
- Object-C @synthesize -- 笔记
- awk使用入门
1.基本用法 awk '{pattern + action}' {filenames} pattern 表示 AWK 在数据中查找的内容 action 是在找到匹配内容时所执行的一系列命令. patt ...
- C primer plus 读书笔记第九章
本章的标题是函数.C的设计原则是把函数作为程序的构成模块. 1.函数概述 函数的定义:函数是用于完成特定任务的程序代码的自包含单元. 使用函数的原因:1.函数的使用可以省去重复代码的编写.2.使得程序 ...
- Android常用ProgressDialog设置
public static ProgressDialog initDialog(Context context) { ProgressDialog progressDialog = new Progr ...
- Java 异常处理的误区和经验总结--转载
本文着重介绍了 Java 异常选择和使用中的一些误区,希望各位读者能够熟练掌握异常处理的一些注意点和原则,注意总结和归纳.只有处理好了异常,才能提升开发人员的基本素养,提高系统的健壮性,提升用户体验, ...
- [转] linux下的僵尸进程处理SIGCHLD信号
什么是僵尸进程? 首先内核会释放终止进程(调用了exit系统调用)所使用的所有存储区,关闭所有打开的文件等,但内核为每一个终止子进程保存了一定量的信息.这些 信息至少包括进程ID,进程的终止状态,以及 ...
- 基于Android Volley的网络请求工具
基于Android Volley的网络请求工具. 一.说明 AndroidVolley,Android Volley核心库及扩展工程.AndroidVolleySample,网络请求工具示例工程.Re ...