文本文件单词统计 数据结构课程设计

设计题目
1. 文本文件单词统计
1.1 【问题描述】
编写一个文本文件单词统计的程序,包括建立文件、单词统计、单词查询、单词定位的功能。
1.2 【基本要求】
程序应先询问用户的 ID (ID 号包括两个大写字母和 4 位数字 ) ,例如 :
请输入用户 ID : AB1234
程序应对输入的 ID 号验证,符合 ID 号要求的格式,然后程序提示四种选择 :
(1) 建立文件
(2) 单词统计
(3) 单词查询及定
(4) 退出
注意:
i) 文件至少包含 50 个英文单词(一定出现重复的单词,且一定包含数字)
ii) 文档不规范,单词之间可能不只有一个空格,并且有加引号的一些单词“ jiaozi
加引号的单词算单词,但数字不算单词
iii) 逐行扫描文本文件,计算文档中单词总数,及各个单词出现的频次,并且按照单词首字母 abcd ……
的顺序排列,显示并生成 soft.txt 文件
iv) 查询任意给出的单词是否存在,如果不存在,在屏幕上输出“ 查无此词! ”;如果存在,显示单词
出现的总次数,并且详细列出其 出现的位置。
例如:
请您输入待查询的词: of
单词 of 共出现了 2 次;
1 次出现在第 1 行,第 5 个位置;
2 次出现在第 3 行,第 1 个位置。
请您输入待查询的词:

完整代码 

#include<bits/stdc++.h>

using namespace std;

string s,word_text, words;
vector<string> words_single;   //存放要查找的单词 方便比较 
vector<string> v;
vector<string> v3;
vector<string> v4;
int n,row,col,temp;
string j = "%";     //解决最后一次出现的位置为0的问题 

int find_word(int col)
{
	words_single.insert(words_single.end(),j);
	for(int i=col;i<v3.size();i++)
	{
		words_single.insert(words_single.end(),v3[i]);
	}
	
	int sub_num2 = find(words_single.begin(),words_single.end(),words)-words_single.begin();
	if(sub_num2<words_single.size())
	{
		n++;
		col += sub_num2;
		int temp_col = col;
		if(col>11)
		{ 
			
			row = col/11+1;	
			temp_col = col%11;	
		}
		printf("它在文件output中第%d次出现的位置位于第%d行第%d列\n",n,row,temp_col);	
		words_single.clear();
		find_word(col);		
	}
	else
	{
		return 0;	
	}
}

int main()
{
	int flag=0;
	bool sign = 0;
	printf("请输入用户ID号:");
	cin >> s;
	vector<string> v2;
	vector<int> word_num;
	int num;  //去重后单词的个数 
	int sub_num;
	
//检查ID号格式是否正确   两个大写字母和四个数字 	
	regex pattern("[A-Z][A-Z]\\d{4}");       //正则 
	sign = std::regex_match(s,pattern);
	while(sign)
	{
		printf("请选择操作:\n"); 
		cout << "1 建立文件" << endl << "2 单词统计" <<endl << "3 单词查询及定位" << endl <<"4 退出" <<endl;
		scanf("%d",&flag);
		
		string filename("output.txt");    //输入时文本的存储空间 
		fstream output_fstream;
		
		string filename2("soft.txt") ;    //词频统计后单词的存储空间 
		fstream softfile;
		
		if(flag ==1)  //建立文件 
		{
		    output_fstream.open(filename, std::ios_base::out);  //文件名 与打开方式 
		    if (!output_fstream.is_open()) {
		        cerr << "Failed to open " << filename << '\n';
		    } 
			else {
				cout << "请输入您的文本:" ;
				cin.ignore();   //忽略换行 保证getline可以正确执行 
				getline(cin, word_text);
				
				char e[10000];
				strcpy(e, word_text.c_str());   //将string转为char 
				const char *D = "^ ";  //遇到这些字符时不作处理 
				char *P;
				P = strtok(e,D);
				
				while(P)
				{
					v4.push_back(P);//在容器尾部加入一个数据
	        		P=strtok(NULL,D);
				}
						
				for(int i=0;i<v4.size();i++)
				{
					if(i%11 == 0 and i!=0)
					{
						output_fstream <<  endl; //解决输入时 遇空格中断 
					}
					output_fstream <<  v4[i] << " "; //解决输入时 遇空格中断 
				}
		        
		        cerr << "输入成功,请打开'output.txt'文件自行查看" << endl<<endl;
		    }
		    output_fstream.close() ;
		}
		
		//对文档进行处理,使其规范化
			char c[10000];
			strcpy(c, word_text.c_str());   //将string转为char 
			const char *d = "!\\" "@#¥%……&*()—+=!$^&_}{}[];''""?></,\n 1234567890";  //遇到这些字符时不作处理 
			char *p;
			p = strtok(c,d);
						
		if(flag==2) //词频统计 
		{	
			while(p)
			{
				v.push_back(p);//在容器尾部加入一个数据
        		p=strtok(NULL,d);
			}
				
			sort(v.begin(),v.end());    //先排序  后统计 
			
		
			for(int i=0;i<v.size();i++){
				int cnt1 =0 ;                                //和计数方式有关 
				cnt1 = count(v2.begin(),v2.end(),v[i]);  //如果这个单词之前没出现过	
				if(!cnt1) 
				{
					int cnt = count(v.begin(),v.end(),v[i]);
					word_num.insert(word_num.end(),cnt);     //  次数 
					v2.insert(v2.end(),v[i]);	             //  单词 
				}
				else
				{
					continue; 
				} 
			}
			
			//将结果写入到文件当中 
			softfile.open(filename2, std::ios_base::out);  //文件名 与打开方式 
		    if (!softfile.is_open()) {
		        cerr << "Failed to open " << filename << '\n';
		    } 
			else {
			for(int i =0;i<v2.size();i++) 
			{
				cout << v2[i] << " " << word_num[i]<<endl;
				softfile << v2[i] << " " << word_num[i]<<endl; //解决输入时 遇空格中断
			}
		        
		        cerr << "输入成功,请打开'soft.txt'文件自行查看" << endl<<endl;
		    }
		    output_fstream.close() ;
		}
		
		else if(flag==3) //单词查询及定位 
		{
			int col = 0;
			while(p)
			{
				v3.push_back(p);//在容器尾部加入一个数据
        		p=strtok(NULL,d);
			}
			n = 0;     //置零,防止第几次叠加不是目标词的次数而出错 
			cout<< "请输入您要查询的词汇:" << endl;
			cin >> words;
			int cnt1 = count(v2.begin(),v2.end(), words);    //判断目标单词是否存在 
			if(!cnt1)
			{
				 cout << "查无此词"<<endl;
			}
			else if(cnt1)
			{
				 cout <<"您输入的待查词是:" << words<<endl;
				 sub_num = find(v2.begin(),v2.end(),words)-v2.begin();  //找到目标单词的下标 
				 printf("单词出现的次数是:%d \n",word_num[sub_num]);          //在存放次数的数组中找到次数  

				row = 1;	
				find_word(col);
			}		 
			words.clear();
			v3.clear() ;
		}
		else if(flag==4) 
		{
			cout << "您已退出该程序"; 
			break;
		}
	}
	
	while(!sign) 
	{
		printf("ID号格式为两个大写字母和四个数字,SD形如:AB1234。 \n"); 
		printf("ID号格式有误请重新输入 \n"); 
		main();
	}
	return 0;
}

代码分析

万能头文件 全局变量声明

#include<bits/stdc++.h>
 
using namespace std;
 
string s,word_text, words;
vector<string> words_single;   //存放要查找的单词 方便比较 
vector<string> v;              //用于存放初始输入经过规格化的文本
vector<string> v3;             //工具vector
vector<string> v4;             //工具vector
int n,row,col,temp; //n 第几次出现   row 行数  col 列数  temp工具人
string j = "%";     //解决最后一次出现的位置为0的问题

 好的点是全局变量声明后,在整个程序段中都可以使用

然后,声明了四个vector数组 缺点就是占的空间比较大,优点的话是不会发生数据的错乱或者混淆

功能三的实现 实现文件中单词的定位查询

int find_word(int col)     //col 用于记录行数
{
	words_single.insert(words_single.end(),j);    //j就是字符串"%"  
	for(int i=col;i<v3.size();i++)
	{
		words_single.insert(words_single.end(),v3[i]);
	}
	
    //sub_num2 存储目标单词的位置
	int sub_num2 = find(words_single.begin(),words_single.end(),words)-words_single.begin();
	if(sub_num2<words_single.size())
	{
		n++;
		col += sub_num2;
		int temp_col = col;
		if(col>11)
		{ 
			
			row = col/11+1;	
			temp_col = col%11;	
		}
		printf("它在文件output中第%d次出现的位置位于第%d行第%d列\n",n,row,temp_col);	
		words_single.clear();
		find_word(col);		
	}
	else
	{
		return 0;	
	}
}

 算法:切片,重新输入 然后定位查询 

在words_single开始插入字符 “%”的原因是,占起址为0的空间,然后减的时候减去0刚好得到对应的位置,也就是单词对应的位置

col用作标志位,每次从col的下一个开始再次存入数组中,然后采用find对新的数组进行查找相关词,找到后,再次重找到位置的下一个切片存入数组中,再次遍历查询,直到没有找到目标词,然后退出

v3是在主函数中经过处理的 char 类型的数组,以一个单词为单位进行遍历

主函数中依次实现四个功能

int main()
{ 
	int flag=0;        //标志用于指定进入哪个功能
	bool sign = 0;     // ID号是否符合格式的代码
	printf("请输入用户ID号:");
	cin >> s;
	vector<string> v2;      //字符型数组v2
	vector<int> word_num;   //
	int num;  //去重后单词的个数 
	int sub_num;   //功能2中查找对应单词出现次数的标志
	
//检查ID号格式是否正确   两个大写字母和四个数字 	
	regex pattern("[A-Z][A-Z]\\d{4}");       //正则 判断是否符合格式要求
	sign = std::regex_match(s,pattern);
	while(sign)       //当符合要求后进入
	{
		printf("请选择操作:\n"); 
		cout << "1 建立文件" << endl << "2 单词统计" <<endl << "3 单词查询及定位" << endl <<"4 退出" <<endl;
		scanf("%d",&flag); //要进行哪一项操作
		
		string filename("output.txt");    //输入时文本的存储空间 建立文件output 
		fstream output_fstream;
		
		string filename2("soft.txt") ;    //词频统计后单词的存储空间 
		fstream softfile;
		
		if(flag ==1)  //建立文件 
		{
		    output_fstream.open(filename, std::ios_base::out);  //文件名 与打开方式 此处以out方式打开
		    if (!output_fstream.is_open()) {          
		        cerr << "Failed to open " << filename << '\n';
		    } 
			else {
				cout << "请输入您的文本:" ;
				cin.ignore();   //忽略换行 保证getline可以正确执行 
				getline(cin, word_text);  将输入的内容全部接收 包括空格
				
				char e[10000];          //空间大点,存的单词可以多
				strcpy(e, word_text.c_str());   //将string转为char 
				const char *D = "^ ";  //遇到这些字符时不作处理 
				char *P;
				P = strtok(e,D);
				
				while(P)
				{   //此处v4用于将文本以单词为单位输入                
					v4.push_back(P);  //在容器尾部加入一个数据  
	        		P=strtok(NULL,D);
				}
						
				for(int i=0;i<v4.size();i++)
				{
					if(i%11 == 0 and i!=0)
					{
						output_fstream <<  endl; //解决输入时 遇空格中断 
					}
					output_fstream <<  v4[i] << " "; //解决输入时 空格消失 v4是一个char类型的没有空格的数组 
				}
		        
		        cerr << "输入成功,请打开'output.txt'文件自行查看" << endl<<endl;
		    }
		    output_fstream.close() ;   //关闭文件
		}
		
		//对文档进行处理,使其规范化 为功能二 词频统计做准备
			char c[10000];
			strcpy(c, word_text.c_str());  //将string转为char 
			const char *d = "!\\" "@#¥%……&*()—+=!$^&_}{}[];''""?></,\n 1234567890";  //遇到这些字符时,单词统计不作处理 
			char *p;
			p = strtok(c,d);
						
		if(flag==2) //词频统计 
		{	
			while(p)
			{   //压入容器中便于遍历处理
				v.push_back(p); //在容器尾部加入一个数据
        		p=strtok(NULL,d); 
			}
				
			sort(v.begin(),v.end());    //先排序  后统计  按A-Z和a-z 的方式进行统计
			
		
			for(int i=0;i<v.size();i++){
				int cnt1 =0 ;                                //和计数方式有关 
				cnt1 = count(v2.begin(),v2.end(),v[i]);  	
				if(!cnt1)                                    //如果这个单词之前没出现过
				{
					int cnt = count(v.begin(),v.end(),v[i]); //计数 统计该单词一共出现了几次
					word_num.insert(word_num.end(),cnt);     //  word_num 容器 用于存放次数 
					v2.insert(v2.end(),v[i]);	             //  v2 用于存放单词 
				}   //需要注意的是,这个位置的单词和对应的次数 必须分别存放在数组下标相同的位置
				else
				{
					continue; //如果这个单词出现过,就不再统计
				} 
			}
			
			//将结果写入到文件当中  该文件已 Key:value 方式存放 
			softfile.open(filename2, std::ios_base::out);  //文件名 与打开方式 
		    if (!softfile.is_open()) {
		        cerr << "Failed to open " << filename << '\n';
		    } 
			else {
			for(int i =0;i<v2.size();i++) 
			{
				cout << v2[i] << " " << word_num[i]<<endl;     //在显示器上显示统计结果
				softfile << v2[i] << " " << word_num[i]<<endl; //统计结果存入文档中,解决输入时 遇空格中断
			}
		        
		        cerr << "输入成功,请打开'soft.txt'文件自行查看" << endl<<endl;  //两次换行 界面简洁
		    }
		    output_fstream.close() ;   //文件关闭
		}
		
		else if(flag==3) //单词查询及定位 
		{
			int col = 0;
			while(p)
			{
				v3.push_back(p);//在容器尾部加入一个数据
        		p=strtok(NULL,d);
			}
			n = 0;     //置零,防止第几次叠加不是目标词的次数而出错 
			cout<< "请输入您要查询的词汇:" << endl;
			cin >> words;
			int cnt1 = count(v2.begin(),v2.end(), words);    //判断目标单词是否存在 
			if(!cnt1)
			{
				 cout << "查无此词"<<endl;
			}
			else if(cnt1)
			{
				 cout <<"您输入的待查词是:" << words<<endl;
				 sub_num = find(v2.begin(),v2.end(),words)-v2.begin();  //找到目标单词的下标 
				 printf("单词出现的次数是:%d \n",word_num[sub_num]);          //在存放次数的数组中找到次数  

				row = 1;	
				find_word(col);  //调用查找功能
			}		 
			words.clear();
			v3.clear() ;
		}
		else if(flag==4) 
		{
			cout << "您已退出该程序"; 
			break;
		}
	}
	
	while(!sign) 
	{
		printf("ID号格式为两个大写字母和四个数字,SD形如:AB1234。 \n"); 
		printf("ID号格式有误请重新输入 \n"); 
		main();
	}
	return 0;
}
  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值