7-2 词频统计(30 分)

请编写程序,对一段英文文本,统计其中所有不同单词的个数,以及词频最大的前10%的单词。

所谓“单词”,是指由不超过80个单词字符组成的连续字符串,但长度超过15的单词将只截取保留前15个单词字符。而合法的“单词字符”为大小写字母、数字和下划线,其它字符均认为是单词分隔符。

输入格式:

输入给出一段非空文本,最后以符号#结尾。输入保证存在至少10个不同的单词。

输出格式:

在第一行中输出文本中所有不同单词的个数。注意“单词”不区分英文大小写,例如“PAT”和“pat”被认为是同一个单词。

随后按照词频递减的顺序,按照词频:单词的格式输出词频最大的前10%的单词。若有并列,则按递增字典序输出。

输入样例:

This is a test.

The word "this" is the word with the highest frequency.

Longlonglonglongword should be cut off, so is considered as the same as longlonglonglonee.  But this_8 is different than this, and this, and this...#
this line should be ignored.

输出样例:(注意:虽然单词the也出现了4次,但因为我们只要输出前10%(即23个单词中的前2个)单词,而按照字母序,the排第3位,所以不输出。)

23
5:this
4:is
#include<iostream>
#include<vector>
#include<map>
#include<string>
#include<algorithm>

using namespace std;

map<string, int> mp;

struct Words {//定义了一个word结构体
	string str;
	int count;
};

bool cmp(const Words &w1, const Words &w2) {//排序用到的比较函数
	if (w1.count > w2.count) {
		return true;
	}
	if (w1.count == w2.count) {
		return w1.str < w2.str;
	}
	return false;
}

int main() {
	string word;
	char c;
	while (true) {
		scanf("%c",&c);//一个一个字母往里输入
		if (c >= 'A'&&c <= 'Z' || c >= 'a'&&c <= 'z' || c >= '0'&&c <= '9' || c == '_') {
			if (c >= 'A'&&c <= 'Z') {
				c = (c - 'A' + 'a');//将大写字母转化为小写字母,统计词频不分大小写
			}
			if (word.length() < 15) {
				word += c;//如果这个单词长度小于15,就把这个字母加到这个单词的末尾
			}
		}
		else if (c == '#' || word.length() > 0) {
			if (!mp[word]) {//如果map里面没有这个单词,就插入这个单词,并把key(单词出现的次数)设为1
				mp[word] = 1;
			}
			else {
				mp[word]++;//如果已经有了,就把频率+1
			}
			word.clear();//把word清空,方便下一个单词输入
			if (c == '#') {
				break;//如果输入等于#,则输入结束
			}
		}
	}
	map<string, int>::iterator iter;//迭代器
	vector<Words> vec;//定义一个Words类型的vector,方便排序
	Words w;
	for (iter = mp.begin(); iter != mp.end(); iter++) {//通过迭代器遍历map
		//cout << iter->first << " " << iter->second << endl;
		if (iter->first.length()>0)
		{
			w.str = iter->first;
			w.count = iter->second;
			vec.push_back(w);
		}
		
	}
	sort(vec.begin(), vec.end(), cmp);//对vector进行排序
	int count = vec.size()*0.1;
	cout << vec.size() << endl;
	for (int i = 0; i < count; i++) {
		cout << vec[i].count << ":" << vec[i].str << endl;
	}
	return 0;
}


1 创建L4 1项目 2 给定一个存放了三段文章的字符串数组 点击 “文件显示”按钮 将第一段文章内容显示在文本框中 再次点击“文件显示”按钮 将第二段文章显示在文本框中 以此类推 filestr[0] "Singles Day in China is the celebration or mourning of being unattached Started by students in Nanjing in the mid 1990s the date was selected in observation of its four solitary digits "; filestr[1] "While relatively obscure in most other countries Singles Day is likely to increase in prominence as more single men in China are unable to find female partners According to a recent study by the Chinese Academy of Social Sciences more than 24 million Chinese men could find themselves without spouses by 2020 "; filestr[2] "Celebrating Singles Day comes in many forms across the Asian nation and like Christmas and Valentine"s Day it has become a multi million dollar industry "; 注意:利用给定文章或者自选文章都可以 注意我们只讨论简单的情况 文章中只有逗号和句号两种特殊符号 2 点击“词频统计”按钮 系统将文本框中的字符串包括的单词及其个数统计出来 如图2所示 提示1:文章需要经过若干次处理 大小写处理 替换特殊符号处理 隔单词处理 提示2:利用hashtable进行统计 单词作为key 个数作为value foreach string i in strword if ht Contains i ht Add i 1 ; else ht[i] int ht[i] + 1; 提示3:格式化输出统计结果 string str string Format "{0 15} {1 3}" de Key de Value ; txtFile Text txtFile Text +str + " r n";">1 创建L4 1项目 2 给定一个存放了三段文章的字符串数组 点击 “文件显示”按钮 将第一段文章内容显示在文本框中 再次点击“文件显示”按钮 将第二段文章显示在文本框中 以此类推 filestr[0] "Singles Day in China is [更多]
### 回答1: 在C语言中实现7-4题,即词频统计,可以通过使用哈希表的方式来解决。哈希表是根据关键字直接访问存储位置的数据结构,它通过计算关键字的哈希值,将其映射到某个数组或链表的位置,实现高效的查找和插入操作。 具体实现步骤如下: 1. 定义一个哈希表,作为存储词频的数据结构。可以使用数组和链表的结合来实现,每个数组元素存储一个链表。 2. 读取输入的字符串。 3. 遍历字符串,依次将每个单词提取出来。可以通过空格或标点符号来隔单词。 4. 对每个单词进行哈希计算,得到哈希值。 5. 在哈希表中查找对应哈希值的位置,如果已存在则更新词频,否则插入新的节点。 6. 输出哈希表中每个单词的词频。 以下是一个简单的示例代码: ``` #include <stdio.h> #include <string.h> #include <ctype.h> // 哈希表节点 typedef struct Node { char word[100]; // 单词 int frequency; // 词频 struct Node* next; // 链表指针 } Node; #define HASH_SIZE 1000 // 哈希表大小 Node* hashTable[HASH_SIZE]; // 哈希表数组 // 计算哈希值 int hash(char* word) { int sum = 0; for (int i = 0; i < strlen(word); i++) { sum += word[i]; } return sum % HASH_SIZE; } // 在哈希表中插入或更新节点 void insertOrUpdate(char* word) { int index = hash(word); Node* node = hashTable[index]; while (node != NULL) { if (strcmp(node->word, word) == 0) { // 单词已存在,更新词频 node->frequency++; return; } node = node->next; } // 单词不存在,插入新节点 Node* newNode = (Node*) malloc(sizeof(Node)); strcpy(newNode->word, word); newNode->frequency = 1; newNode->next = hashTable[index]; hashTable[index] = newNode; } // 输出哈希表中的单词和词频 void printFreq() { for (int i = 0; i < HASH_SIZE; i++) { Node* node = hashTable[i]; while (node != NULL) { printf("%s: %d\n", node->word, node->frequency); node = node->next; } } } int main() { // 初始化哈希表 memset(hashTable, 0, sizeof(hashTable)); char input[10000]; scanf("%[^\n]", input); // 读取输入的字符串直到换行符 char* token = strtok(input, " ,.-"); // 使用空格和标点符号隔单词 while (token != NULL) { for (int i = 0; i < strlen(token); i++) { token[i] = tolower(token[i]); // 统一转为小写字母 } insertOrUpdate(token); token = strtok(NULL, " ,.-"); } // 输出词频 printFreq(); return 0; } ``` 这样,输入一段文本,程序会输出每个单词的词频。注意,此代码只是一个简单示例,没有考虑一些特殊情况,如单词超长等,需根据实际需求进行调整和完善。 ### 回答2: 题目要求使用C语言编写一个程序,统计一个给定字符串中各个单词出现的次数。下面是一个简单的C语言代码示例: ```c #include <stdio.h> #include <string.h> void wordFrequency(char *str) { int len = strlen(str); int count = 1; for (int i = 0; i < len; i++) { if (str[i] == ' ') { count++; continue; } while (str[i] != ' ' && i < len) { i++; } } printf("单词个数:%d\n", count); } int main() { char str[100]; printf("请输入字符串:"); gets(str); wordFrequency(str); return 0; } ``` 代码中的wordFrequency函数用于统计单词个数。它首先通过strlen函数获取字符串的长度,然后使用一个循环遍历字符串。在循环中,每次遇到空格符就将计数器加一,忽略其他符号。最后输出计数器的值,即为单词个数。 在主函数中,我们使用gets函数获取用户输入的字符串,并调用wordFrequency函数进行统计。最后输出结果。注意,由于使用了gets函数,输入的字符串长度不能超过100个字符。 这是一个简单的单词频率统计程序,只能统计单词的个数,并不考虑重复出现的情况。如果需要统计每个单词的具体出现次数,需要对代码进行进一步的修改和完善。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值