C++:设计一个保留字(或关键字)的统计程序,从源数据文件(C或C++语言程序)中,读取字符或字符串,与保留字文件中的保留字进行匹配比较,并统计计数。

版本更新2023.1.2

1.增加了面对对象的思想设计了包装类

2.增加了注释

3.补全了没有扫描次数和时间的问题

2.1题目:

设计一个保留字(或关键字)的统计程序

  1. l建立保留字文件;
  1. l从源数据文件(C或C++语言程序)中,读取字符或字符串,与保留字文件中的保留字进行匹配比较,并统计计数。
  1. l输出两张表文件:保留字及其计数,非保留字及其计数。
  1. l输出源文件的扫描次数和扫描所用时间。

2.2需求分析:

在大数据时代的背景下,通过对用户日常浏览,搜索内容的关键字进行提取并且进行统计,并把出现次数较频繁的非关键字提取成关键字,通过这种方法可以计算出用户的偏好。很多购物平台以及短视频平台都有此机制。通过对关键字的提取和统计,不仅方便用户,还能够给这些平台带来更多的收益。

此外,如果对源代码中的程序设计语言的关键字进行统计,也可以得出一些结论,如:代码量的多少,该源代码作者的写作风格等等。

2.3设计思想和方案设计:

  1. 首先要明确什么是关键字:就C++来说,关键字是指是电脑语言里事先定义的,有特别意义的标识符,有时又叫保留字。就是像数据类型(int,double,char等),定义操作(class,struct等)等。
  2. 根据题意要求,从源代码里获取关键字,那么前提就是代码的语句应该基本是合法的,如果出现关键字,那么关键字一定是标准的,另外像以下这些形式都不能算关键字:intt,classes,charcharchar。也就是说,关键字一旦添加其他的任何符号,它就从关键字变成了变量名,不具有关键字功能。
  3. 总结起来,就是从源代码中提取字符串和关键字进行比对,相同则数量加一。而执行时可以采用每次读一行,从没行中提取多个字符串的方法。具体判定条件就是以特定字符(不是字母和数字而且不是下划线的字符)为分割。

2.4核心代码(全部代码):

#include<iostream>
#include<string>
#include<fstream>
#include<time.h>
#define Maxsize 5000
using namespace std;
class word {	/*封装(面向对象)*/
private:
	string s;	/*关键字/非关键字本体*/
	int num;	/*出现次数*/
public:
	word() {		/*默认构造*/
		s = " ";
		num = 0;
	}
	word(string ss) {		/*带参构造*/
		s = ss;
		num = 0;	
	}
	string getword() { return s; }		/*关键字提取*/
	void changeword(string ss) { s = ss; }	/*单词改变*/
	void appear() { num++; }	/*出现函数,为该关键字次数加一*/
	int getnum() { return num; }	/*取得出现次数*/
};
word key[Maxsize];
word nokey[Maxsize];
int length = 0, ulength = 0;	/*个数*/
int legal(char c);
int main() {
	ifstream ifs;
	ofstream ofs;
	string buf;
	ifs.open("time.dat", ios::in);
	getline(ifs, buf);
	int n=0;
	for (int i = 0; i <buf.length(); i++) {		/*转次数为整数*/
		n *= 10;
		n += (int)(buf[i] - 48);
	}
	n++;
	cout << "第" << n << "次扫描" << endl;
	ifs.close();
	ofs.open("time.dat", ios::trunc);		/*清空再写*/
	ofs << n << endl;
	ofs.close();
	int start = clock();
	ifs.open("Allkey_words.dat", ios::in);		/*可以修改路径,需要统计的关键字*/
	if (!ifs.is_open())
	{
		cout << "Erro Read" << endl;
	}
	while (getline(ifs, buf))//文件读取
	{
		bool p = true;
		for (int i = 0; i < length; i++) {
			if (key[i].getword() == buf) {		/*判重*/
				p = false;
				break;
			}
		}
		if (p) {
			key[length].changeword(buf);
			length++;
		}
	}
	ifs.close();
	cout << "共有" << length+1 << "个关键字" << endl;
	ifs.open("stu_deal.cpp", ios::in);
	while (getline(ifs, buf))
	{
		for (int i = 0; i < buf.length(); i++) {
			string s;
			bool t = true;	/*是否为关键字*/
			while (legal(buf[i])) {
				s.push_back(buf[i]);		/*符合要求字符组合成字符串*/
				i++;
			}
			if (s == " " || s.length() == 0)continue;
			for (int i = 0; i < length; i++) {
				if (key[i].getword() == s) {
					key[i].appear();
					t = false;
					break;
				}
			}
			if (t) {
				bool p = true;
				for (int i = 0; i < ulength; i++) {		/*先找有没有出现过*/
					if (nokey[i].getword() == s) {
						p = false;
						nokey[i].appear();
						break;
					}
				}
				if (p) {	/*没出现过新建非关键字*/
					nokey[ulength].changeword(s);
					nokey[ulength].appear();
					ulength++;
				}
			}
		}
	}
	ofs.open("no_keywords.dat", ios::trunc);		/*轮流写入*/
	ofs << "非关键字:" << endl;
	for (int i = 0; i < ulength; i++) {
		ofs << nokey[i].getword() << " " << nokey[i].getnum() << "次" << endl;
	}
	ofs.close();
	ofs.open("keywords.dat", ios::trunc);
	ofs << "关键字:" << endl;
	for (int i = 0; i < length; i++) {
		ofs << key[i].getword() << " " << key[i].getnum() << "次" << endl;
	}
	ofs.close();
	int end = clock();
	cout << "此次扫描花费时间为:" << (end - start) << "毫秒" << endl;
}


int legal(char c) {		/*判断是否为允许的字符*/
	if (c >= 'a' && c <= 'z') {
		return 1;
	}
	else if (c >= 'A' && c <= 'Z') {
		return 1;
	}
	else if (c >= '0' && c <= '9') {
		return 1;
	}
	else if (c == '_')return 1;
	else return 0;
}

2.5测试用例:

此程序涉及文件操作:

key_words.dat:

包含部分c++关键字

test.cpp:

和此代码完全一致,只是复制版本文件名不同。

运行后得:

Keywords.dat:

no_keywords.dat:

2.6总结:

  1. 在此次试验中,我对C++的文件操作和字符串处理能力有了很大的提升,更能够分辨不同文件操作方式的真正用途,能在适当的时机和位置采用正确的文件操作方式。
  2. 体会到了关键字提取的重要性,认识到了关键字统计具体实施上的一些问题,并且学会了如何解决这些问题。
  3. 相对于现在热度很高的大数据关键字提取,本程序还存在一定的不足,主要在于关键字也有可能以子串的方式存在于字符串中,而对于源代码的检索方面则没有这种需求,但是如果需要的话可以在程序中添加相关字符串操作,如:KMP算法,字符串分割,字符串提取等。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

淬炼之火

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值