C语言:如何实现在txt文件中删除超链接、统计单词数量、生成单词列表 (文本流操作并解决乱码)
1、首先读取原文件内容文本流(包含中英文)
2、删除超链接
3、统计单词数量
4、去除重复单词
读取文件需要自己在文本笔记中保存一个网页,保存为txt文件
注意的是,在这个代码实现过程中,我学到的是如何避免输入内容时出现乱码的现象,第一是必须要用fprintf、fread、fwrite等 用于文本流的函数,而不能用fputc、fputs这些用于二进制文本的函数,虽然说当你内容少的时候,可能不会出现乱码情况,当你输入内容多起来的时候就不一定了。(以上只是向txt文件输入内容的时候)
所以记住,fprintf是向txt文件原原本本的输出你想要输出的东西。
读取出现乱码怎么办:网上有很多说法,你可以试试保存txt文件的时候按照其他博客大佬那样修改保存的格式,
但是我这里使用的是系统命令,
也就是在int main(){后面加上一段代码:system("mode con cp select=65001");
代码表示,将代码页转换为UTF-8,因为计算机在读取内容的时候,是用二进制的方式读取,读进去的时候自然会有乱码现象,所以我们无须在文本文件下面另存为UTC-8类型(我自己另存了也不行,读出来还是会有乱码现象),所以我最后用命令行的方式解决了这个困扰我很久的世纪难题!!!!!!!!!!!!!!最后记得输出%d或者其他%lf等等数字的时候需要改回你自己计算机的代码页,我的是936,所以在输出多少个单词的时候再次用system命令行修改代码页
system("mode con cp select=65001");
显示代码页:
其中65001代表UTF-8,输出为:
Status for device CON:
----------------------
Lines: 9001
Columns: 120
Keyboard rate: 31
Keyboard delay: 1
Code page: 65001
代码页就是DOS中显示的语言
437代表美式英语即可输出为:
Status for device CON:
----------------------
Lines: 40
Columns: 100
Keyboard rate: 31
Keyboard delay: 1
Code page: 437
936(936表示简体中文)输出:
设备状态 CON:
---------
行: 40
列: 100
键盘速度: 31
键盘延迟: 1
代码页: 936
#include<stdio.h>
#include<string.h>
#include<ctype.h>
/*
/ ********************************************** /
This is Jackson.W's Experiment report.
Time: 2022.03.05
school num: 20203005129
/ ********************************************** /
//暂时不修改原文件内容
-----------------------------
创建一个临时文件,将源文件进行扫描,超链接不扫描,操作完成后再进行临时文件内容复制到原文件中,就可以实现源文件也删除了超链接
-----------------------------
第一大功能实现:
将扫描到的字符串一个一个录入到字符串中,
(删除超链接)
创建一个临时文件,将源文件进行扫描,超链接不扫描
1,若碰到 < 符号,判断是否是超链接
2,设置一个函数,碰到的 < 的地方,在此处继续扫描下去,直到遇到 > 符号
3,记录此处的位置,继续录入字符到字符串中去
4,直到文件的末尾处
测试结果: 该文件的字符串长度:14254
第二大功能:将删除超链接后的文件内容复制到另一个文本中去
第三大功能:统计单词数目
第四大功能:去除重复单词
a) 建立一个结构数组,包含:存字符串的数组, 计算单词数量int ,定义一个字符串数组copy,用来缓存文件单词
b) 读取第一个单词,录进copy中,再与结构数组的字符串进行比较
c) 如果不同,则存进第i个数组结构的字符串
d) 如果相同,就清空copy的字符串,再进行下一次的扫描
e)
第五大功能:将单词表存进另一个txt文件
*/
typedef struct _Wordc{
char s[20];
int num;
}Wordc;//定义两百个空间,录入单词
void prt(char ch, FILE *fp);//输出文本内容
void deltxt(char ch, FILE *fp, FILE *temp);//删除超链接
void copytxt(char ch, FILE *fp, FILE *null_f);//实现两个文件的复制,第一个内容复制到另一个文件内容中去
int madeword(char *ch, FILE *fp);//实现将文件中的单词提取出来
void wordcc(Wordc *wordc, FILE *fp1, FILE *fp2, char *copy);//去除重复单词,生成单词表打印出来
void wbiao(Wordc *wordc, FILE *fp, int m);
int main()
{
int i;
system("mode con cp select=65001");
char ch;
char ch1[20], ch2[20];
//char *w[20];
FILE *fp1 = NULL;
FILE *fp2 = NULL;
char copy[20];
Wordc wordc[700];
//FILE *tmpfp = NULL;
//tmpfp = tmpfile();//临时文件,测试代码要用
/************输出原始文本内容**************/
fp1 = fopen("/tmp/shuju.txt", "r");
prt(ch, fp1);
fclose(fp1);
/**************************************/
/************删除超连接***************/
fp1 = fopen("/tmp/shuju.txt", "r");
fp2 = fopen("/tmp/new.txt", "w");
//deltxt(ch1, fp1, tmpfp);用临时文件测试,实现删除超链接
deltxt(ch, fp1, fp2);
fclose(fp1);
fclose(fp2);
/*************************************/
/***************删除超连接后,将文件复制到新的文本**************/
fp1 = fopen("/tmp/shuju.txt", "w");
fp2 = fopen("/tmp/new.txt", "r");
copytxt(ch, fp2, fp1);
fclose(fp1);
fclose(fp2);
/*************************************/
/************输出删除超链接后的内容**************/
fp1 = fopen("/tmp/shuju.txt", "r");
prt(ch, fp1);
fclose(fp1);
/**************************************/
/************统计单词数目,除去重复单词, 打印出单词相同的单词表,并且将单词表复制给新的文本里面*************/
fp1 = fopen("/tmp/new.txt", "r");
fp2 = fopen("/tmp/wordsclub.txt", "w");
wordcc(wordc, fp1, fp2, copy);
fclose(fp1);
fclose(fp2);
/**********************************************************************************************************/
/*将单词表所在文件的单词内容打印出来*/
fp2 = fopen("/tmp/wordsclub.txt", "r");
prt(ch, fp2);
fclose(fp2);
/*************************************/
// printf("\n***************\n");
// for(i = 0; i < 200; i++)
// {
// printf("%s ", wordc[i].s);
// if(i % 10 == 0)
// {
// printf("\n");
// }
// }
return 0;
}
void prt(char ch, FILE *fp)//输出文本内容
{
while(!feof(fp))
{
ch = fgetc(fp);
//fscanf(fp, "%c", &ch);
//fread(ch, 20, 1, fp);
putchar(ch);
//printf("%s", ch);
}
}
void deltxt(char ch, FILE *fp, FILE *temp)//删除超链接 ,temp为另一个文件,可为临时文件,也可为另一个文件
{
char copy[11];
//char ch;
int i;
int index;
char tcopy[11];
while(!feof(fp))
{
//ch = getc(fp);//判断是否碰到<符号
pos_1:
for(i = 0; i < 10; i++)
{
copy[i] = ' ';
tcopy[i] = ' ';
}
//copy[9] = '\0';
i = 0;
//fread(copy, 10, 1, fp);
for(i = 0; i < 10; i++)
{
copy[i] = getc(fp);//读取
if(copy[i] == '<')//当读取到<的时候 kjihi<dvs>inini<fsdgg vcgcnsfg>
{
copy[i] = '\0';//让他结束扫描,直接把字符串写进去
fprintf(temp, "%s", copy);
while(1)
{
ch = getc(fp);
while(ch == '>')
{
goto pos_1;//当遇到>结尾的时候就继续跳到read处继续扫描
}
}
//putchar(ch);//测试打印出来是否删除了超链接
//putc(ch, temp);//写到临时文件里面去
//fprintf(temp, "%s", ch);
}
else if(i == 9)//当一直没遇到<
{
copy[10] = '\0';
fprintf(temp, "%s", copy);
}
}
// else
// {
// while(ch != '>')//当还没到>符号的时候继续往下扫描
// {
// //ch = getc(fp);
// }
// }
}
}
int madeword(char *ch, FILE *fp)//实现将文件中的单词提取出来, 默认是在当前文件流中继续扫描下一个
{
char chp;
int i = 0;
char temp;
while(!feof(fp))
{
temp = getc(fp);
//ch[i] = chp;
//printf("\n*************%c*************\n", chp);
if((temp >= 65 && temp <= 90) || (temp >= 97 && temp <= 122) ) //确定是字母
{
chp = temp;
i = 0;
while(1)
{
ch[i] = chp;
printf("%c", ch[i]);
chp = getc(fp);
if(!((chp >= 65 && chp <= 90) || (chp >= 97 && chp <= 122)))
{
i++;
ch[i] = '\0';
//printf("\n%s\t", ch);
break;
}
i++;
}
break;
}
}
}
void wordcc(Wordc *wordc, FILE *fp1, FILE *fp2, char *copy)//去除重复单词,生成单词表打印出来
{
/*
typedef struct _Wordc{
char s[20];
int num;
}Wordc;//定义两百个空间,录入单词
四大功能:去除重复单词
a) 建立一个结构数组,包含:存字符串的数组, 计算单词数量int ,定义一个字符串数组copy,用来缓存文件单词
b) 读取第一个单词,录进copy中,再与结构数组的字符串进行比较
c) 如果不同,则存进第i个数组结构的字符串
d) 如果相同,就清空copy的字符串,再进行下一次的扫描
e)
*/
int i = 0,j = 0, m = 1;
int k = 0;
//copy[20] = "";
int index = 0;//当前结果数组的最大下标
char ch;//读取流的字符
int numwords = 0;
int num = 0;
int start = 0;
for (j = 0; j < 200; j++)
{
wordc[j].num = 0; //把结构体数组成员的num全部赋值为0
}
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);
for(j = 0; j < m; j++)
{
if(strcmp(copy, wordc[j].s) == 0)//表示出现过
{
wordc[j].num++;
k = 0;//表示有重复单词
break;
}
else
{
k = 1;//遍历所有元素,无影响,因为碰到上面有重复的才会break,这里即使等于1 了也不会出来,继续遍历
}
}
if(k == 1)
{
for(j = 0; j < i + 1; j++)
{
wordc[m].s[j] = copy[j];
}
wordc[m].num++;//新成员加一
m++;//移动到结构的下一个新空间
}
i = 0;
for(j = 0; j < 20; j++)
{
copy[j] = ' ';//清空copy内的字符内容
}
}
}
system("mode con cp select=936");
printf("一共有%d个不同的单词\n" , m-1);
printf("总单词数量:%d\n", numwords);
//system("mode con cp select=65001");
// for(j = 0; j < m; j++)
// {
// printf("%s\n", wordc[j].s);
// }
/**************************************************生成单词表的函数在这里**********************/
wbiao(wordc, fp2, m);
}
void wbiao(Wordc *wordc, FILE *fp, int m)
{
//system("mode con cp select=437");
int i ,j;
for(i = 0; i < m; i++)
{
//fwrite(wordc[i].s, sizeof(wordc[i].s[0]), sizeof(wordc[i].s) / sizeof(wordc[i].s[0]), fp);
fprintf(fp, "%s", wordc[i].s);//链表中已经把字符字符串化,所以直接每一个单词输出就行
fprintf(fp, " ");
if(i % 10 == 0)
{
fprintf(fp, "\n");
//putc()
}
}
}
本文来自博客园,作者:竹等寒,转载请注明原文链接。