福大软工1816 · 第二次作业——单词词频统计

一、Fork的同名仓库的Github项目地址

github项目地址

二、PSP表格

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 0 0
· Estimate · 估计这个任务需要多少时间 360 480
Development 开发 0 0
· Analysis · 需求分析 (包括学习新技术) 240 240
· Design Spec · 生成设计文档 0 0
· Design Review · 设计复审 0 0
· Coding Standard · 代码规范 (为目前的开发制定合适的规范) 0 0
· Design · 具体设计 10
· Coding · 具体编码 80 80
· Code Review · 代码复审 0 0
· Test · 测试(自我测试,修改代码,提交修改) 5 10
Reporting 报告 60 120
· Test Repor · 测试报告 0 0
· Size Measurement · 计算工作量 10 10
· Postmortem & Process Improvement Plan · 事后总结, 并提出过程改进计划 10 10

三、解题思路描述

1.文本读入功能:在项目文件夹下创建test.txt的文本,利用fopen,fread函数来读取文件。
2.字符统计功能:利用fseek将指针放入文本末尾后用ftell来返回末尾指针到开头的距离即字符数。
3.行数统计功能:读取文件时候是一个个字符读取的,将存储文件的字符数组遍历一遍看是否有出现 ,出现则行数+1。
4.单词统计功能:利用strtok函数来切割文本,将每个分割好的单词存入*p,遍历并筛选判断字符串长度,再判断前四位是否是字母,若出现大写字母则通过ascii码+32来转化为小写字母。创立一个map(string,int)容器,通过count来判断该单词是否出现过,若未出现则insert一个新的项,若出现过了则在原来项中的int里++。
5.频率排序功能:将map中的string,int分别存入数组中,先排序int,再排序string,从而达到按序输出。
6.文本写入功能:通过fopen,fwrite自动创建一个result文本,并将需要的功能写入result文本。

四、设计实现过程

  • readtxt():用于读取test.txt文件
  • main():用于统计字符数、行数、词频数
  • sort():用于排序前十词频数
  • write():用于将结果写入result.txt文件
    main()中会调用其他三个函数。

五、代码测试

  • 读取的文本与程序放在同个文件夹

  • 代码执行后创建result文本

六、性能分析


消耗最大的函数

七、代码

1.读取文件
void readtxt()  //读取文件 
{
        cin >> test;
	FILE *fp;
	errno_t err;
	err = fopen_s(&fp, test, "r"); //读取test文件 
	fseek(fp, 0, SEEK_END);//将指针放到文件的末尾 
	charactersnum = ftell(fp);//返回指针末尾到开头的值 即字符长度 
	rewind(fp);	//还原 将指针放回开头 
	fread(s, charactersnum, 1, fp);
}
2.判断单词是否合理并记录合理单词
while (p)//遍历单词  并把单词放入数组wordsrep 频率放入数组numrep 
	{
		wordsmid = p;
		strcpy_s(words, wordsmid.c_str()); //将字符串转为字符数组 
		b = wordsmid.length(); //判断字符串的长度 

		for (j = 0; j <= 3; j++)//判断该单词是否符合前四位为字母
		{
			if (words[j] >= 'a' && words[j] <= 'z')
				pos = 1;
			else if (words[j] >= 'A' && words[j] <= 'Z')
			{
				words[j] = words[j] + 32;
				wordsmid = words;
				pos = 1;//将所有大写字母转换为小写字母
			}
			else
			{
				pos = 0;
				break;
			}
		}

		if (b >= 4 && pos == 1)//判断是否该单词不低于四个符号切前四位是字母 
		{
			wordsnum++;
			if (m1.count(wordsmid) == 0)
			{
				m1.insert(pair <string, int>(wordsmid, 1));
				wordsrep[i] = wordsmid;
				numrep[i] = 1;
				i++;
			}  //若该单词未记录,则在map中创建一个新的项 
			else
			{
				for (j = 0; j <= i; j++)
				{
					if (wordsrep[j].compare(wordsmid) == 0)
					{
						numrep[j] = numrep[j] + 1;
					}
				}
				m1[wordsmid]++;
			} //若该单词已记录,则将该单词记录的map里的int数量+1 
		}
		
		p = strtok_s(NULL, d , &buf);
	}
3.频率排序
void sort()  
{
	for (j = 0; j <= i - 1; j++)
	{
		for (k = i - 2; k >= j; k--)
		{
			if (numrep[k + 1] > numrep[k])
			{
				t1 = numrep[k + 1];
				numrep[k + 1] = numrep[k];
				numrep[k] = t1;
				t2 = wordsrep[k + 1];
				wordsrep[k + 1] = wordsrep[k];
				wordsrep[k] = t2;
			}
			if (numrep[k + 1] == numrep[k])
			{
				if (wordsrep[k + 1] < wordsrep[k])
				{
					t2 = wordsrep[k + 1];
					wordsrep[k + 1] = wordsrep[k];
					wordsrep[k] = t2;
					t1 = numrep[k + 1];
					numrep[k + 1] = numrep[k];
					numrep[k] = t1;
				}
			}
		}
	}
}
4.写入文件
void writetxt()  //输出文件 
{
	FILE *fp1;
	errno_t err;
	err = fopen_s(&fp1,"result.txt", "w");
	fwrite(res_c, res.length(), 1, fp1);
}

八、异常处理

  • 执行过程中多次出现过类似的问题,例如此处需要使用_itoa_s等,因为在vs下要使用安全函数。

九、总结

在这次的作业中,大部分时间花在代码上,因为并没有做过类似这样的项目,但在这次项目我学习到了许多新的函数用法 ,以及当程序执行报错时候应当如何解决,虽然感觉在这次作业中还有用许多笨办法,但是也算有所进步,希望能够在接下来的项目中越做越好。
原文地址:https://www.cnblogs.com/kkyblog/p/9606429.html