前言

本博客最终会完成以下的任务

使用顺序存储的循环队列实现下面功能:
将文档中每个单词的最后三个字母保存到一个新文档中,并打印在
屏幕上。例如,原文档中有这样一句话“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语言:顺序存储循环队列#保存文件中单词的最后三个字母的更多相关文章

  1. C语言数据结构-循环队列的实现-初始化、销毁、清空、长度、队列头元素、插入、删除、显示操作

    1.数据结构-循环队列的实现-C语言 #define MAXSIZE 100 //循环队列的存储结构 typedef struct { int* base; //基地址 int _front; //头 ...

  2. C语言实现循环队列

    今日在处理数据存储的问题中,数据占用的空间较大,在询问之下,提及循环队列. 没有学习过的我,想想就是头大,只能慢慢从网上找资料,一个字母一个字母的敲,最后,还是慢慢的对队列有了一些理解 对于循环队列有 ...

  3. C语言实现循环队列的初始化&进队&出队&读取队头元素&判空-2

    /*顺序表实现队列的一系列操作(设置flag标志不损失数组空间)*/ #include<stdio.h> #include<stdlib.h> #define Queue_Si ...

  4. [C 语言基础] 如何调用不同文件中的函数

    很多时候需要将实现不同功能的函数或者与某个模块有关的函数写在一个文件里.这样有两个好处: 1. 方便以后调用:以后需要用到这个模块,或者这类函数,直接将相关文件复制过去,再稍微修改一下就能应用于不同场 ...

  5. 学c语言做练习之​统计文件中字符的个数

    统计文件中字符的个数(采用命令行参数) #include<stdio.h> #include<stdlib.h> int main(int argc, char *argv[] ...

  6. C语言实现 循环队列

    #include <stdio.h>#include <stdlib.h>#include <stdbool.h> typedef struct queue{ in ...

  7. Android 自定义View及其在布局文件中的使用示例(三):结合Android 4.4.2_r1源码分析onMeasure过程

    转载请注明出处 http://www.cnblogs.com/crashmaker/p/3549365.html From crash_coder linguowu linguowu0622@gami ...

  8. 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 ...

  9. Flex读取txt文件中的内容(三)

    Flex读取txt文件中的内容 1.设计源码 LoadTxt.mxml: <?xml version="1.0" encoding="utf-8"?> ...

  10. C语言如何在两个文件中访问同一个全局变量

    方法一: 不使用头文件. 1.c 中 int var; 2.c 中 extern int var; 方法二: 使用头文件. 1.c 中 int var; 不必添加#include "1.h& ...

随机推荐

  1. Python企业面试题1 —— 基础篇

    1. b.B.KB.MB.GB的关系? b ---- 位(bit) B ---- 字节(一个字节等于8位) 1 B = 8 bit 1 KB = 1024 B 1 MB = 1024 KB 1 GB ...

  2. OpenHarmony定义扩展组件样式:@Extend装饰器

      在前文的示例中,可以使用@Styles用于样式的扩展,在@Styles的基础上,我们提供了@Extend,用于扩展原生组件样式. 说明: 从API version 9开始,该装饰器支持在ArkTS ...

  3. C# 介绍、应用领域、入门、语法、输出和注释详解

    什么是 C#? C#(发音为"C-Sharp")是一种由 Microsoft 创建的面向对象的编程语言,运行在 .NET Framework 上.源于 C 家族,与流行的语言如 C ...

  4. Java基础知识:面试官必问的问题

    数据类型 基本类型 byte/8 char/16 short/16 int/32 float/32 long/64 double/64 boolean/~ boolean 只有两个值:true.fal ...

  5. 十城百校联动!HDC.Together 2023 HarmonyOS学生公开课与千余名校园学子见证鸿蒙力量

      8月6日,HDC.Together2023 HarmonyOS学生公开课在东莞松山湖举办.有来自清华大学.北京大学.哈尔滨工业大学等全国百余所高校,千余名学生开发者齐聚会场,与华为高级技术专家.生 ...

  6. HDC2022 开发者亮点抢先看,线上线下精彩活动等你探索!

    原文:https://mp.weixin.qq.com/s/A2sfpPKBvF6zwinbUsgwiw,点击链接查看更多技术内容.

  7. sql 语句系列(闰年)[八百章之第十九章]

    前言 判断闰年还是挺有用的. mysql select DAY(LAST_DAY(DATE_ADD(CURRENT_DATE,INTERVAL -DAYOFYEAR(CURRENT_DATE)+1+3 ...

  8. EMQX + PolarDB-X 一站式 IoT 数据解决方案

    简介: 本文整理自 EMQX 产品经理李国伟,在PolarDB开源社区中关于EMQX与PolarDB-X构建一站式IoT数据解决方案的分享.本篇内容主要分为四个部分:1. IoT数据特性 2. EMQ ...

  9. [GPT] 同为 nodejs 库的 Puppeteer 和 cheerio 的区别是什么

    Puppeteer 和 cheerio 是两个完全不同的库,用途和功能也截然不同. Puppeteer 是一个 Node.js 库,它使用 Chrome 或 Chromium 浏览器作为渲染引擎,通过 ...

  10. [FAQ] Git远程仓库想把目录大写改为小写,windows本地不识别的的处理

      通过四步操作: 1. 先把忽略大小写设为false,即区分大小写git config core.ignorecase false 2. 拷贝出来备份那几个大写的目录,随后分支上操作删除,提交到远程 ...