C语言:顺序存储循环队列#保存文件中单词的最后三个字母
前言
本博客最终会完成以下的任务
使用顺序存储的循环队列实现下面功能:
将文档中每个单词的最后三个字母保存到一个新文档中,并打印在
屏幕上。例如,原文档中有这样一句话“Near the ancient water town
of Wuzhen”,保存完则为“ear the ent ter own of hen”。
全局变量和结构体代码
/*单词顺序表*/
typedef struct _Elem{
char *word;//存放单词
int lenth;
int front;
int rear;
}Elem;
typedef struct _Elemlink{
Elem *array;//动态定义数组
int link_len;//数组长度
}Elemlink;
Elemlink *L1 = NULL;
#define MAXSIZE 3//一保存个单词后面的几个字母的最大数量
四个任务
①计算文件中的单词数量
该操作是为了分配空间,事先一次性分配完所需要的空间。
计算完成后该函数会返回一个int数值,该数值就是单词数量,所以利用这个返回值进行空间分配。
count_to_words函数中的这个isalpha()函数是在ctype.h头文件中的,所以在使用的时候要记得包含该头文件。
isalpha()函数是判断该字符是否为字母
代码思想: 这比较简单,其实就是遇到字母就开始录入,当遇到不是字母形式的或者遇到空间就代表该单词结束录入,数组移动下一个空间,然后等待再次遇到字母形式的字符就开始重复上述操作。
fp1 = fopen("D:/D/F.txt", "r");
F_link_len = count_to_words(fp1);//统计单词表 接收单词数量
L1->array = (Elem*)malloc(sizeof(Elem)*F_link_len+1);
/*分配顺序单词表空间
,+1 是防止空间越界,
所以多给一个空间位置进行存储
,不会造成什么影响*/
fclose(fp1);
//计算文件中单词数函数
int count_to_words(FILE *fp) //统计删除后的单词个数
{
char ch;
int nums = 0;
while(!feof(fp))
{
ch = getc(fp);
if(isalpha(ch))
{
nums++;
while(1)
{
ch = getc(fp);
if(!isalpha(ch)) break;
/*当完成录入一个单词后进入到这里
是为了找到下一个字母形式开头的内容才退出循环。*/
}
}
}
return nums;
}
②保存单词最后三个字母到链表中
使用顺序存储的循环队列实现
如果不理解循环队列的话可以移步到我另一篇博客进行学习喔!里面讲的很详细,一定要耐心看完,都是本尊的心血和全部的学习总结出来的。
->顺序存储的循环队列——点击博客<-
代码里面也有很多注释,你也可以选择去尝试着看注释理解一下我想要表达的意思
void SqQueue_Save_Three_ch(Elemlink **Sqlink, FILE *fp) //先进先出,f出,r进
{
char ch;
int index = 0;
bool open = false;
int i;
Elemlink *temp = (*Sqlink);
Elemlink *malloc_Sq = (*Sqlink);
for(i = 0; i < F_link_len; i++)
{//分配每个单词的空间,用最大长度的单词空间分配就能存下所有的
malloc_Sq->array[i].word = (char*)malloc(sizeof(char)*MAXSIZE);
malloc_Sq->array[i].rear = 0;
malloc_Sq->array[i].front = 0;
malloc_Sq->array[i].lenth = 0;
}
while(!feof(fp))
{
ch = fgetc(fp);
if(ch != ' ' && isalpha(ch))
{
open = true;
//第二个判断条件也很重要,因为第一个进来的时候,肯定是rear = front的,所以要用lenth判断是否已经录入了一个
if((temp->array[index].rear)%MAXSIZE == (temp->array[index].front)%MAXSIZE && temp->array[index].lenth!=0)
temp->array[index].front = (temp->array[index].front+1)%MAXSIZE;
/*顺序真的很重要,我靠,上下两部分调开顺序,结果完全不一样,
必须要先判断是否移动尾指针才进行录入,
否则的话,
1、假设还没满队
若你是先录入,再移动指针的话,你不能保证移动后,
尾部指针到最后录完之后,会把尾部指针置空了一个
2、假设已经满队了,且录入完成,没有元素进入
可能会导致头部指针往后移动了一个,但是没有尾部没有录入,
这时候会导致头部变成了第二个元素,而尾部变成了第一个元素*/
temp->array[index].word[temp->array[index].rear] = ch;
temp->array[index].rear = (temp->array[index].rear + 1)%MAXSIZE;
/*过程是:先判断是否加一后和头部指针相同了,
如果相同了,首先把头部指针往前移动,
然后再把尾部指针回到刚刚头部指针腾出来的位置,这样就实现了队列排序*/
if(temp->array[index].lenth < MAXSIZE)
{
temp->array[index].lenth++;
}
}
if(open == true && ch == ' ')
{
open = false;
index++;
}
}
}
③将链表的内容导出到另一个文件中
长话短说,这里录入尽量用fprintf,虽然本博客讲的是英文单词,我希望以后你想向文件输入中文信息的时候不会出现乱码的错误,所以我推荐大家使用fprintf来操作,同样的你想读取文件中某些中文信息的时候也要使用fscanf,这都是文本文件操作所使用的函数。
想要了解为什么或者会实战了解一下可以移步我另一篇博客喔。
为什么删除超链接要是用fprintf…点击博客
导出内容的函数代码如下:
void SaveFile_Sq_Three_ch(Elemlink *Sqlink, FILE *fp)
{
int i, j, count = 0;
for(i = 0; i < F_link_len; i++)
{
for(j = 0; j < Sqlink->array[i].lenth; j++)//Sqlink->array[i].lenth
{
fprintf(fp,"%c", Sqlink->array[i].word[Sqlink->array[i].front]);
Sqlink->array[i].front = (Sqlink->array[i].front+1)%MAXSIZE;
}
fprintf(fp,"\t");
count++;
if(count%10==0)
{
count = 0;
fprintf(fp,"\n");
}
}
}
④将新文件的内容打印到屏幕中
这个就很简单啦,第三步中说到,我们在读取中文信息的时候一定要用fscanf,这里我们用的是单词作为例子,不包含中文符号,所以这里博主就偷个懒哈哈哈, 直接用fgetc函数。
代码如下:
void PF_Three_ch_File(FILE *fp)
{
char ch;
int i = 0;
while(!feof(fp))
{
ch = fgetc(fp);
if(ch != ' ' && ch != '\n')
{
putchar(ch);
break;
}
}
while(!feof(fp))
{
ch = fgetc(fp);
putchar(ch);
}
}
@完整代码@
#include<stdio.h>
#include<stdbool.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>
/*单词顺序表*/
typedef struct _Elem{
char *word;//存放单词
int lenth;
int front;
int rear;
}Elem;
typedef struct _Elemlink{
Elem *array;//动态定义数组
int link_len;//数组长度
}Elemlink;
Elemlink *L1 = NULL;
#define MAXSIZE 3//一保存个单词后面的几个字母的最大数量
int F_link_len;
int count_to_words(FILE *fp);
void SqQueue_Save_Three_ch(Elemlink **Sqlink, FILE *fp);
void SaveFile_Sq_Three_ch(Elemlink *Sqlink, FILE *fp);
void PF_Three_ch_File(FILE *fp);
int main()
{
FILE *fp1;
L1 = (Elemlink*)malloc(sizeof(Elemlink));//建立一个顺序表的空间 ,地址是全局变量,出了函数后也不会被释放
fp1 = fopen("D:/D/F.txt", "r");
F_link_len = count_to_words(fp1);//统计单词表 接收单词数量
L1->array = (Elem*)malloc(sizeof(Elem)*F_link_len+1);//分配顺序单词表空间
fclose(fp1);
fp1 = fopen("D:/D/F.txt", "r");
SqQueue_Save_Three_ch(&L1, fp1);
fclose(fp1);
fp1 = fopen("D:/D/F_Threech.txt", "w");
SaveFile_Sq_Three_ch(L1, fp1);
fclose(fp1);
fp1 = fopen("D:/D/F_Threech.txt", "r");
PF_Three_ch_File(fp1);
fclose(fp1);
return 0;
}
int count_to_words(FILE *fp) //统计删除后的单词个数
{
char ch;
int nums = 0;
while(!feof(fp))
{
ch = getc(fp);
if(isalpha(ch))
{
nums++;
while(1)
{
ch = getc(fp);
if(!isalpha(ch)) break;
/*当完成录入一个单词后进入到这里
是为了找到下一个字母形式开头的内容才退出循环。*/
}
}
}
return nums;
}
void SqQueue_Save_Three_ch(Elemlink **Sqlink, FILE *fp) //先进先出,f出,r进
{
char ch;
int index = 0;
bool open = false;
int i;
Elemlink *temp = (*Sqlink);
Elemlink *malloc_Sq = (*Sqlink);
for(i = 0; i < F_link_len; i++)
{//分配每个单词的空间,用最大长度的单词空间分配就能存下所有的
malloc_Sq->array[i].word = (char*)malloc(sizeof(char)*MAXSIZE);
malloc_Sq->array[i].rear = 0;
malloc_Sq->array[i].front = 0;
malloc_Sq->array[i].lenth = 0;
}
while(!feof(fp))
{
ch = fgetc(fp);
if(ch != ' ' && isalpha(ch))
{
open = true;
//第二个判断条件也很重要,因为第一个进来的时候,肯定是rear = front的,所以要用lenth判断是否已经录入了一个
if((temp->array[index].rear)%MAXSIZE == (temp->array[index].front)%MAXSIZE && temp->array[index].lenth!=0)
temp->array[index].front = (temp->array[index].front+1)%MAXSIZE;
/*顺序真的很重要,我靠,上下两部分调开顺序,结果完全不一样,
必须要先判断是否移动尾指针才进行录入,
否则的话,
1、假设还没满队
若你是先录入,再移动指针的话,你不能保证移动后,
尾部指针到最后录完之后,会把尾部指针置空了一个
2、假设已经满队了,且录入完成,没有元素进入
可能会导致头部指针往后移动了一个,但是没有尾部没有录入,
这时候会导致头部变成了第二个元素,而尾部变成了第一个元素*/
temp->array[index].word[temp->array[index].rear] = ch;
temp->array[index].rear = (temp->array[index].rear + 1)%MAXSIZE;
/*过程是:先判断是否加一后和头部指针相同了,
如果相同了,首先把头部指针往前移动,
然后再把尾部指针回到刚刚头部指针腾出来的位置,这样就实现了队列排序*/
if(temp->array[index].lenth < MAXSIZE)
{
temp->array[index].lenth++;
}
}
if(open == true && ch == ' ')
{
open = false;
index++;
}
}
}
void SaveFile_Sq_Three_ch(Elemlink *Sqlink, FILE *fp)
{
int i, j, count = 0;
for(i = 0; i < F_link_len; i++)
{
for(j = 0; j < Sqlink->array[i].lenth; j++)//Sqlink->array[i].lenth
{
fprintf(fp,"%c", Sqlink->array[i].word[Sqlink->array[i].front]);
Sqlink->array[i].front = (Sqlink->array[i].front+1)%MAXSIZE;
}
fprintf(fp,"\t");
count++;
if(count%10==0)
{
count = 0;
fprintf(fp,"\n");
}
}
}
void PF_Three_ch_File(FILE *fp)
{
char ch;
int i = 0;
while(!feof(fp))
{
ch = fgetc(fp);
if(ch != ' ' && ch != '\n')
{
putchar(ch);
break;
}
}
while(!feof(fp))
{
ch = fgetc(fp);
putchar(ch);
}
}
C语言:顺序存储循环队列#保存文件中单词的最后三个字母的更多相关文章
- C语言数据结构-循环队列的实现-初始化、销毁、清空、长度、队列头元素、插入、删除、显示操作
1.数据结构-循环队列的实现-C语言 #define MAXSIZE 100 //循环队列的存储结构 typedef struct { int* base; //基地址 int _front; //头 ...
- C语言实现循环队列
今日在处理数据存储的问题中,数据占用的空间较大,在询问之下,提及循环队列. 没有学习过的我,想想就是头大,只能慢慢从网上找资料,一个字母一个字母的敲,最后,还是慢慢的对队列有了一些理解 对于循环队列有 ...
- C语言实现循环队列的初始化&进队&出队&读取队头元素&判空-2
/*顺序表实现队列的一系列操作(设置flag标志不损失数组空间)*/ #include<stdio.h> #include<stdlib.h> #define Queue_Si ...
- [C 语言基础] 如何调用不同文件中的函数
很多时候需要将实现不同功能的函数或者与某个模块有关的函数写在一个文件里.这样有两个好处: 1. 方便以后调用:以后需要用到这个模块,或者这类函数,直接将相关文件复制过去,再稍微修改一下就能应用于不同场 ...
- 学c语言做练习之统计文件中字符的个数
统计文件中字符的个数(采用命令行参数) #include<stdio.h> #include<stdlib.h> int main(int argc, char *argv[] ...
- C语言实现 循环队列
#include <stdio.h>#include <stdlib.h>#include <stdbool.h> typedef struct queue{ in ...
- Android 自定义View及其在布局文件中的使用示例(三):结合Android 4.4.2_r1源码分析onMeasure过程
转载请注明出处 http://www.cnblogs.com/crashmaker/p/3549365.html From crash_coder linguowu linguowu0622@gami ...
- c程序设计语言_习题1-13_统计输入中单词的长度,并且根据不同长度出现的次数绘制相应的直方图
Write a program to print a histogram of the lengths of words in its input. It is easy to draw the hi ...
- Flex读取txt文件中的内容(三)
Flex读取txt文件中的内容 1.设计源码 LoadTxt.mxml: <?xml version="1.0" encoding="utf-8"?> ...
- C语言如何在两个文件中访问同一个全局变量
方法一: 不使用头文件. 1.c 中 int var; 2.c 中 extern int var; 方法二: 使用头文件. 1.c 中 int var; 不必添加#include "1.h& ...
随机推荐
- #Tarjan#洛谷 5676 [GZOI2017]小z玩游戏
题目 分析 可能玩两次也就是形成环即是Tarjan缩点后在同一个强连通分量 如果按照游戏连边数量将达到\(O(n^2)\),当中其实有很多边可以共用, 考虑\(i\)连向\(i\)的倍数,以及有趣程度 ...
- Windows Terminal的资料
Windows Terminal是微软Windows平台难得好用的工具. 由于工作内容的原因,需要打开多个CMD窗口.多个git bash窗口,并且在多个窗口间切换,因此命令行窗口支持多TAB的特性, ...
- Native Drawing开发指导,实现HarmonyOS基本图形和字体的绘制
场景介绍 Native Drawing模块提供了一系列的接口用于基本图形和字体的绘制.常见的应用场景举例: ● 2D图形绘制. ● 文本绘制. 接口说明 接口名 描述 OH_Drawing_Bit ...
- Centos8安装docker-ce
一.安装步骤 1.安装yum-utils yum install -y yum-utils 2.配置阿里源 yum-config-manager --add-repo http://mirrors.a ...
- 整理k8s————k8s prod相关[三]
前言 简单整理k8s prod. 正文 prod 有两种: 自主式prod 控制器管理的prod 在Kubernetes中,最小的管理元素不是一个个独立的容器,而是Pod,Pod是最小的,管理,创建, ...
- redis命令和lua实现分布式锁
Redis分布式锁关键 SETNX 语法: SETNX key value 如果key不存在,则存储(key:value)值,返回1 如果key已经不存在,则不执行操作,返回0 因为这个命令的性质,多 ...
- kubernetes集群最新版安装
原文地址:https://haiyux.cc/2022/09/21/k8s-install/ 虚拟机准备 我这里准备了三台虚拟机,分别部署一个master和两个node,操作系统位ubuntu 20. ...
- Dapr Outbox 执行流程
Dapr Outbox 是1.12中的功能. 本文只介绍Dapr Outbox 执行流程,Dapr Outbox基本用法请阅读官方文档 .本文中appID=order-processor,topic= ...
- HarmonyOS NEXT应用开发之下拉刷新与上滑加载案例
介绍 本示例介绍使用第三方库的PullToRefresh组件实现列表的下拉刷新数据和上滑加载后续数据. 效果图预览 使用说明 进入页面,下拉列表触发刷新数据事件,等待数据刷新完成. 上滑列表到底部,触 ...
- HarmonyOS NEXT应用开发之Axios获取解析网络数据
介绍 本示例介绍使用第三方库的Axios获取GBK格式的网络数据时,通过util实现GBK转换UTF-8格式.该场景多用于需要转换编码格式的应用. 效果图预览 使用说明 直接进入页面就可获取GBK格式 ...