问题描还 文学研究人员需要统计某篇英文小说中某些形容词的出现次数和位置。试写--个实现这--目标的 文字统计系统,称为“文学研究助手”。 基本要求 英文小说存于一个文本文件中。待统计的词汇集合要一次输 入完毕,即统计工作必须在程序的一 次运行之后就全部完成。程序的输出结果是每个词的出现次数和出现位置的行号,格式自行设计。 测试数据 以源程序模拟英文小说,编程语言保留字集作为待统计的词汇集。 实现提示 设小说非空且以文件形式存放,其中的词汇一律不跨行。这样,每读入-行,就统计每个词在这 行中的出现次数和出现位置的行号,后者可以用链表存储。若某行中出现了不止一-次,不必存多个相 同的行号。数据结构采用二维链表,单词结点链接成一个链表,每个单词的行号组成- -个链表,单词 结占作为行号链表的头结占。用c语言
时间: 2024-02-18 08:03:09 浏览: 139
统计文本文件中一段英文中某个单词出现的次数及其出现的位置
4星 · 用户满意度95%
实现这个文学研究助手可以分为以下几个步骤:
1. 读入小说文本文件,将其存储到内存中。
2. 读入待统计的词汇集合,将其存储到内存中。
3. 逐行扫描小说文本,统计每个词汇在该行中的出现次数和出现位置的行号,并将结果存储到相应的数据结构中。
4. 输出每个词汇的出现次数和出现位置的行号。
下面是一个可能的实现:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_WORD_LEN 50 // 定义单词的最大长度
#define MAX_LINE_LEN 1000 // 定义行的最大长度
// 定义单词节点
typedef struct word_node {
char word[MAX_WORD_LEN]; // 单词
struct line_node *lines; // 行号链表
struct word_node *next; // 下一个单词
} word_node;
// 定义行号节点
typedef struct line_node {
int line_num; // 行号
struct line_node *next; // 下一个行号
} line_node;
// 统计单词出现次数和出现位置的函数
void count_words(char *filename, char **words, int num_words, word_node **word_list) {
FILE *fp;
char line[MAX_LINE_LEN];
int line_num = 0; // 记录当前行号
// 打开文件
fp = fopen(filename, "r");
if (fp == NULL) {
printf("Error opening file.\n");
exit(1);
}
// 逐行扫描文件
while (fgets(line, MAX_LINE_LEN, fp) != NULL) {
line_num++;
// 将行末的换行符去掉
if (line[strlen(line)-1] == '\n') {
line[strlen(line)-1] = '\0';
}
// 统计单词在该行中的出现次数和出现位置的行号
char *token = strtok(line, " ");
while (token != NULL) {
for (int i = 0; i < num_words; i++) {
if (strcmp(token, words[i]) == 0) {
// 找到了一个待统计的单词
word_node *word_ptr = *word_list;
word_node *prev_word_ptr = NULL;
while (word_ptr != NULL && strcmp(word_ptr->word, token) != 0) {
prev_word_ptr = word_ptr;
word_ptr = word_ptr->next;
}
if (word_ptr == NULL) {
// 没有找到该单词,需要创建新的单词节点并插入到单词链表中
word_ptr = (word_node *) malloc(sizeof(word_node));
strcpy(word_ptr->word, token);
word_ptr->lines = NULL;
word_ptr->next = NULL;
if (prev_word_ptr == NULL) {
// 插入到单词链表的头部
*word_list = word_ptr;
} else {
// 插入到单词链表的中间或尾部
prev_word_ptr->next = word_ptr;
}
}
// 将行号插入到该单词的行号链表中
line_node *line_ptr = word_ptr->lines;
line_node *prev_line_ptr = NULL;
while (line_ptr != NULL && line_ptr->line_num != line_num) {
prev_line_ptr = line_ptr;
line_ptr = line_ptr->next;
}
if (line_ptr == NULL) {
// 没有找到该行号,需要创建新的行号节点并插入到行号链表中
line_ptr = (line_node *) malloc(sizeof(line_node));
line_ptr->line_num = line_num;
line_ptr->next = NULL;
if (prev_line_ptr == NULL) {
// 插入到行号链表的头部
word_ptr->lines = line_ptr;
} else {
// 插入到行号链表的中间或尾部
prev_line_ptr->next = line_ptr;
}
}
}
}
token = strtok(NULL, " ");
}
}
// 关闭文件
fclose(fp);
}
// 输出单词出现次数和出现位置的函数
void print_words(word_node *word_list) {
word_node *word_ptr = word_list;
while (word_ptr != NULL) {
printf("%s: ", word_ptr->word);
line_node *line_ptr = word_ptr->lines;
while (line_ptr != NULL) {
printf("%d ", line_ptr->line_num);
line_ptr = line_ptr->next;
}
printf("(%d)\n", line_ptr == NULL ? 0 : 1); // 输出出现次数
word_ptr = word_ptr->next;
}
}
int main() {
char *filename = "novel.txt";
char *words[] = {"int", "char", "float", "double", "if", "else", "while", "for", "switch", "case", "break", "continue", "return"};
int num_words = sizeof(words) / sizeof(char *);
word_node *word_list = NULL;
count_words(filename, words, num_words, &word_list);
print_words(word_list);
return 0;
}
```
在这个程序中,我们定义了两个数据结构:单词节点和行号节点。单词节点包含单词本身、行号链表以及指向下一个单词的指针;行号节点包含行号本身以及指向下一个行号的指针。
在统计单词出现次数和出现位置时,我们使用了一个二维链表的结构,即单词节点链接成一个链表,每个单词的行号组成一个链表,单词节点作为行号链表的头节点。这样可以方便地统计每个单词在哪些行出现过,并输出出现次数和出现位置的行号。
阅读全文