C语言:生成单词列表----使用单链表实现

解决之前用结构体数组导致内存过剩问题,使用动态分配内存优化单词列表。

txt文本内容不允许出现其他字符形式,这个仅限于判断在txt网页文件已经删除了超链接等,文本里面只允许出现单词才能进行判断和进行单词统计去重。

删除超链接和不可视化内容的代码可参考我以前的这篇博客,只需要把结构体修改一下,和传入的参数修改一下就可以正常使用了。

删除超链接--点击博客

#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<stdbool.h>
#include<stdlib.h>
/*
	/ ********************************************** /
		This is Jackson.W's Experiment report. 
		Time: 2022.03.05
		school num: 20203005129
	/ ********************************************** /
*/
struct Wordc{
	char s[20];
	int num;
	struct Wordc *next; 
}; 


void wordcc(struct Wordc **wordc, FILE *fp1, FILE *fp2);//去除重复单词,生成单词表打印出来

void wbiao(struct Wordc *wordc, FILE *fp, int m);

void Release_room(struct Wordc **wordc);//释放分配动态分配后的空间 

int main()
{
	int i;
	system("mode con cp select=65001");
	char ch;
	char ch1[20], ch2[20];
	FILE *fp1 = NULL;
	FILE *fp2 = NULL;
	struct Wordc *wordc_huohu = NULL;

/*火狐:统计单词数目,除去重复单词, 打印出单词相同的单词表,并且将单词表复制给新的文本里面***/

	fp1 = fopen("D:/new_huohu.txt", "r");
	fp2 = fopen("D:/wordsclub_huohu.txt", "w");
	wordcc(&wordc_huohu, fp1, fp2);
	fclose(fp1); 
	fclose(fp2);	
/****************************************************************/ 

	Release_room(&wordc_huohu); 
	return 0;
}


void wordcc(struct Wordc **wordc_delive, FILE *fp1, FILE *fp2)//去除重复单词,生成单词表打印出来 
{
	
	int i = 0,j = 0, m = 0;
	int index = 0;//当前结果数组的最大下标
	char ch;//读取流的字符 
	char copy[51];
	int numwords =  0; 
	int num = 0;
	int start = 0;
	
	struct Wordc *Head_W = NULL;//下面会存放结构体的头部地址 
	struct Wordc *temp_H = NULL;
	while(!feof(fp1))
	{
		ch = fgetc(fp1);
		if(isalpha(ch))
		{
		start = 1;//标志进来过这个语句,所以已经有一个字母开头,下面就可以利用这个条件进行判断
		if(isupper(ch))
		{
			ch = tolower(ch);
		 } 
		copy[i++] = ch;
	}
	else if(!isalpha(ch) && start == 1)//符合条件就开始搜索是否有相同单词 
	{
		copy[i] = '\0';//添加\0 变成字符串之后方便比较和其他操作 
		numwords++;
		start = 0;
		//printf("%s*******88\n", copy);
		Head_W = *wordc_delive;//让指针指向单链表头,方便下面从头遍历其他单词 
		for(j = 0; j < m; j++)//判断重复单词 
		{
			if(Head_W == NULL) 
			{
				k = 1;
				break;
			}
			
			if(strcmp(copy, Head_W->s) == 0) 
			{
				Head_W->num++;
				k = 0;//表示有重复单词 
				break;
			 }
			 else
			 { 
			 	k = 1;//遍历所有元素,无影响,因为碰到上面有重复的才会break,这里即使等于1 了也不会出来,继续遍历 
			  }
			 Head_W = Head_W->next;
		  }	
		if(k == 1)//表示有新单词 
		{
			
			//这里需要动态分配一个新空间 ,然后让新空间节点指向头部地址 
			struct Wordc *newRoom = (struct Wordc*)malloc(sizeof(struct Wordc)), *temp_Room;
			if(*wordc_delive == NULL)//若还没有单词在链表中,就直接让新空间的next指向NULL 
			{
				*wordc_delive = newRoom;
				newRoom->next = NULL;
			}
			else 
			{
				temp_H = *wordc_delive;
				while(temp_H->next != NULL)
				{
					temp_H = temp_H->next;//找到尾部 
				}
				temp_H->next = newRoom;
				newRoom->next = NULL;//尾插法 
			}
			for(j = 0; j < i + 1; j++)
			{
				newRoom->s[j] = copy[j];//用新空间进行赋值单词字符 
			}
			newRoom->num++;//新成员加一
			m++;//记录单词数量 
		  } 
		  i = 0;
		  for(j = 0; j < 50; j++)
		  {
		  	copy[j] = ' ';//清空copy内的字符内容 
		  }  
		   
		 } 
	} 
	system("mode con cp select=936");
	printf("一共有%d个不同的单词\n" , m-1);
	printf("总单词数量:%d\n", numwords);
	
	/*****************生成单词表的函数在这里**********************/	
	wbiao(*wordc_delive, fp2, m); 
}

void wbiao(struct Wordc *wordc, FILE *fp, int m)//将单词表写进文件里面 
{	
	//system("mode con cp select=437");
	int i ,j;
	for(i = 0; i < m; i++)
	{
		fprintf(fp, "%s", wordc->s);//链表中已经把字符字符串化,所以直接每一个单词输出就行 
		fprintf(fp, " ");
		if(wordc->next != NULL) wordc = wordc->next; 
		if(i % 10 == 0)
		{
			fprintf(fp, "\n");
			
		}
	}
	
	
	
 } 


void Release_room(struct Wordc **wordc)//释放分配动态分配后的空间 
{
	struct Wordc *temp;
	while(1)
	{
		if(*wordc != NULL)
		{
			temp = *wordc;
			*wordc = (*wordc)->next;
			free(temp);
			
		}
	}
}


posted @ 2022-04-07 13:53  竹等寒  阅读(9)  评论(0编辑  收藏  举报  来源