1.增加了面对对象的思想设计了包装类
2.增加了注释
3.补全了没有扫描次数和时间的问题
2.1题目:
设计一个保留字(或关键字)的统计程序
- l建立保留字文件;
- l从源数据文件(C或C++语言程序)中,读取字符或字符串,与保留字文件中的保留字进行匹配比较,并统计计数。
- l输出两张表文件:保留字及其计数,非保留字及其计数。
- l输出源文件的扫描次数和扫描所用时间。
在大数据时代的背景下,通过对用户日常浏览,搜索内容的关键字进行提取并且进行统计,并把出现次数较频繁的非关键字提取成关键字,通过这种方法可以计算出用户的偏好。很多购物平台以及短视频平台都有此机制。通过对关键字的提取和统计,不仅方便用户,还能够给这些平台带来更多的收益。
此外,如果对源代码中的程序设计语言的关键字进行统计,也可以得出一些结论,如:代码量的多少,该源代码作者的写作风格等等。
2.3设计思想和方案设计:
- 首先要明确什么是关键字:就C++来说,关键字是指是电脑语言里事先定义的,有特别意义的标识符,有时又叫保留字。就是像数据类型(int,double,char等),定义操作(class,struct等)等。
- 根据题意要求,从源代码里获取关键字,那么前提就是代码的语句应该基本是合法的,如果出现关键字,那么关键字一定是标准的,另外像以下这些形式都不能算关键字:intt,classes,charcharchar。也就是说,关键字一旦添加其他的任何符号,它就从关键字变成了变量名,不具有关键字功能。
- 总结起来,就是从源代码中提取字符串和关键字进行比对,相同则数量加一。而执行时可以采用每次读一行,从没行中提取多个字符串的方法。具体判定条件就是以特定字符(不是字母和数字而且不是下划线的字符)为分割。
#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;
}
此程序涉及文件操作:
key_words.dat:
包含部分c++关键字
test.cpp:
和此代码完全一致,只是复制版本文件名不同。
运行后得:
Keywords.dat:
no_keywords.dat:
- 在此次试验中,我对C++的文件操作和字符串处理能力有了很大的提升,更能够分辨不同文件操作方式的真正用途,能在适当的时机和位置采用正确的文件操作方式。
- 体会到了关键字提取的重要性,认识到了关键字统计具体实施上的一些问题,并且学会了如何解决这些问题。
- 相对于现在热度很高的大数据关键字提取,本程序还存在一定的不足,主要在于关键字也有可能以子串的方式存在于字符串中,而对于源代码的检索方面则没有这种需求,但是如果需要的话可以在程序中添加相关字符串操作,如:KMP算法,字符串分割,字符串提取等。