用于存储记录过的字符数
- 格式:doc
- 大小:51.50 KB
- 文档页数:12
数据库技术中的数据字段类型选择在数据库设计和开发过程中,选择合适的数据字段类型是非常重要的。
不同的数据类型可以影响存储空间、性能、数据完整性以及可查询性等因素。
因此,在选择数据字段类型时,需要充分考虑不同方面的因素,以满足应用程序的需求。
一、字符类型字符类型是最常见的数据字段类型之一。
在数据库中,常见的字符类型包括Char、Varchar和Text等。
不同的字符类型适用于不同的应用场景。
1. Char类型Char类型用于存储固定长度的字符数据。
它占用的存储空间是固定的,不受存储的实际字符长度影响。
这在存储短字符时是比较合适的选择。
然而,当存储长度不固定的字符时,使用Char类型可能会造成存储空间的浪费。
2. Varchar类型Varchar类型用于存储长度可变的字符数据。
与Char类型不同,Varchar类型只占用实际存储的字符长度,因此在存储长字符时比较节省空间。
然而,由于需要记录字符长度,所以在写入和读取数据时会稍微慢一些。
3. Text类型Text类型用于存储非常长的文本数据,可以存储大量的字符。
相比于Varchar类型,Text类型更适用于存储超过Varchar类型最大长度限制的长文本数据。
然而,由于Text类型不存储实际的字符长度,所以在搜索和排序方面可能会稍微慢一些。
二、数值类型数值类型用于存储数值数据,包括整数类型和浮点类型。
在选择数值类型时,需要根据实际应用需求来确定合适的类型。
1. 整数类型在数据库中,常见的整数类型包括Int、BigInt和TinyInt等。
这些类型的区别在于所占的存储空间和可表示的数值范围。
通常情况下,选择最小足够表示数据的整数类型可以节省存储空间。
2. 浮点类型浮点类型用于存储小数数据。
在数据库中,常见的浮点类型包括Float和Double等。
这两种类型的区别在于所占的存储空间和精度。
Float类型适用于存储较小范围的小数,而Double类型适用于存储较大范围的小数。
oracle的varchar类型摘要:1.Oracle VARCHAR类型简介2.VARCHAR类型的存储和长度限制3.VARCHAR类型的特点和应用场景4.如何在Oracle数据库中使用VARCHAR类型5.与其他数据类型相比,VARCHAR类型的优缺点6.总结正文:【1.Oracle VARCHAR类型简介】Oracle的VARCHAR类型是一种用于存储变长字符串的数据类型。
它可以存储任意长度的字符串,并且在存储过程中不固定长度。
这意味着,VARCHAR类型可以根据实际存储的需要灵活地调整存储空间。
【2.VARCHAR类型的存储和长度限制】在Oracle数据库中,VARCHAR类型的长度限制取决于数据库的设置。
默认情况下,VARCHAR类型的长度限制为2000个字符。
然而,这个限制可以通过ALTER SESSION语句进行调整。
需要注意的是,VARCHAR类型的存储空间是固定的,当存储的字符串长度超过定义的长度时,多余的字符将被截断。
【3.VARCHAR类型的特点和应用场景】VARCHAR类型具有以下特点:1.可变长度:根据实际需求存储不同长度的字符串。
2.存储效率较高:与固定长度的字符串类型相比,VARCHAR类型在存储短字符串时具有较高的空间利用率。
3.适用于多种场景:如存储查询结果、日志记录等,尤其在处理不确定长度的数据时具有优势。
【4.如何在Oracle数据库中使用VARCHAR类型】在创建表时,可以使用VARCHAR类型定义字段。
例如:```sqlCREATE TABLE example_table (id NUMBER,description VARCHAR(2000));```此外,在SQL查询和编程中,可以使用VARCHAR类型处理数据。
例如,可以使用SELECT语句查询包含VARCHAR类型字段的表:```sqlSELECT id, description FROM example_table;```【5.与其他数据类型相比,VARCHAR类型的优缺点】优点:1.存储灵活,可根据实际需求调整长度。
图书馆管理系统数据字典1. 介绍图书馆管理系统是一个用于管理图书馆资源和服务的软件系统。
该系统涵盖了图书馆的各个方面,包括图书的分类、借阅、归还、图书馆成员管理等功能。
本文将详细介绍图书馆管理系统中使用的数据字典,包括各个数据表的结构、字段说明以及数据类型。
2. 数据表2.1 图书表(Books)字段:- 图书编号(BookID):图书的惟一标识符,采用自增长的整数类型。
- 图书名称(BookName):图书的名称,采用字符串类型。
- 作者(Author):图书的作者,采用字符串类型。
- 出版社(Publisher):图书的出版社,采用字符串类型。
- 出版日期(PublishDate):图书的出版日期,采用日期类型。
- 分类(Category):图书的分类,采用字符串类型。
- 状态(Status):图书的借阅状态,包括“可借”和“已借出”,采用字符串类型。
2.2 图书馆成员表(LibraryMembers)字段:- 成员编号(MemberID):图书馆成员的惟一标识符,采用自增长的整数类型。
- 姓名(Name):图书馆成员的姓名,采用字符串类型。
- 性别(Gender):图书馆成员的性别,采用字符串类型。
- 年龄(Age):图书馆成员的年龄,采用整数类型。
- 联系方式(Contact):图书馆成员的联系方式,采用字符串类型。
2.3 借阅记录表(BorrowRecords)字段:- 记录编号(RecordID):借阅记录的惟一标识符,采用自增长的整数类型。
- 图书编号(BookID):借阅的图书编号,采用整数类型。
- 成员编号(MemberID):借阅的图书馆成员编号,采用整数类型。
- 借阅日期(BorrowDate):借阅的日期,采用日期类型。
- 归还日期(ReturnDate):归还的日期,采用日期类型。
3. 数据类型说明- 整数类型(Integer):用于存储整数数据,如图书编号、成员编号、记录编号等。
C语言统计文件中的字符数、单词数以及总行数统计文件的字符数、单词数以及总行数,包括:每行的字符数和单词数文件的总字符数、总单词数以及总行数注意:空白字符(空格和tab缩进)不计入字符总数;单词以空格为分隔;不考虑一个单词在两行的情况;限制每行的字符数不能超过1000。
代码如下#include <stdio.h>#include <string.h>int *getCharNum(char *filename, int *totalNum);int main(){char filename[30];// totalNum[0]: 总行数totalNum[1]: 总字符数totalNum[2]: 总单词数int totalNum[3] = {0, 0, 0};printf("Input file name: ");scanf("%s", filename);if(getCharNum(filename, totalNum)){printf("Total: %d lines, %d words, %d chars\n", totalNum[0], totalNum[2], totalNum[1]);}else{printf("Error!\n");}return 0;}/*** 统计文件的字符数、单词数、行数** @param filename 文件名* @param totalNum 文件统计数据** @return 成功返回统计数据,否则返回NULL**/int *getCharNum(char *filename, int *totalNum){FILE *fp; // 指向文件的指针char buffer[1003]; //缓冲区,存储读取到的每行的内容int bufferLen; // 缓冲区中实际存储的内容的长度int i; // 当前读到缓冲区的第i个字符char c; // 读取到的字符int isLastBlank = 0; // 上个字符是否是空格int charNum = 0; // 当前行的字符数int wordNum = 0; // 当前行的单词数if( (fp=fopen(filename, "rb")) == NULL ){perror(filename);return NULL;}printf("line words chars\n");// 每次读取一行数据,保存到buffer,每行最多只能有1000个字符while(fgets(buffer, 1003, fp) != NULL){bufferLen = strlen(buffer);// 遍历缓冲区的内容for(i=0; i<bufferLen; i++){c = buffer[i];if( c==' ' || c=='\t'){ // 遇到空格!isLastBlank && wordNum++; // 如果上个字符不是空格,那么单词数加1isLastBlank = 1;}else if(c!='\n'&&c!='\r'){ // 忽略换行符charNum++; // 如果既不是换行符也不是空格,字符数加1isLastBlank = 0;}}!isLastBlank && wordNum++; // 如果最后一个字符不是空格,那么单词数加1isLastBlank = 1; // 每次换行重置为1// 一行结束,计算总字符数、总单词数、总行数totalNum[0]++; // 总行数totalNum[1] += charNum; // 总字符数totalNum[2] += wordNum; // 总单词数printf("%-7d%-7d%d\n", totalNum[0], wordNum, charNum);// 置零,重新统计下一行charNum = 0;wordNum = 0;}return totalNum;}在D盘下创建文件demo.txt,并输入如下的内容:运行程序,输出结果为:上面的程序,每次从文件中读取一行,放到缓冲区buffer,然后遍历缓冲区,统计当前行的字符和单词数。
lz77编码例题详解LZ77编码是一种无损数据压缩算法,它通过利用重复出现的数据来减少存储空间。
这种编码算法广泛应用于网络传输、数据存储和多媒体压缩等领域。
本文将详细解释LZ77编码的原理,并通过一个具体的例题加以说明。
LZ77编码的原理很简单。
算法从输入串的开头开始,依次扫描每个字符,并通过一个滑动窗口来进行匹配。
滑动窗口是一个固定大小的缓冲区,用于存储已经遍历过的字符。
当匹配到重复的字符时,算法将记录下重复字符之前的距离和重复字符个数,以此作为压缩数据的表示。
这样,在压缩数据中,只需要保存重复字符之前的距离和重复字符的个数,而不需要重复存储相同的字符。
假设输入序列为:ABABABA,滑动窗口大小为4。
算法的工作流程如下:1. 初始化滑动窗口和输出缓冲区。
初始状态下,滑动窗口为空,而输出缓冲区为一个空串。
2. 从输入串的开头开始扫描。
在此例中,我们首先扫描到字符"A"。
因为滑动窗口为空,所以直接将字符"A"添加到滑动窗口,并将其输出到缓冲区,即输出"A"。
3. 继续扫描下一个字符"B"。
此时滑动窗口为"A",并且滑动窗口中的字符与下一个字符"B"不匹配。
因此,将字符"B"添加到滑动窗口,并将其输出到缓冲区,即输出"B"。
4. 继续扫描下一个字符"A"。
此时滑动窗口为"AB",并且滑动窗口中的字符与下一个字符"A"匹配。
算法会记录下重复字符"A"之前的距离和重复字符的个数。
在这个例子中,距离为1,重复字符个数为1。
因此,将输出"<1,1>",表示重复字符之前的距离为1,重复字符个数为1。
5. 继续扫描下一个字符"B"。
返回文本字符串中的字符个数所用到的函数在计算机编程中,经常会遇到需要统计文本字符串中字符个数的情况。
为了方便实现这一功能,许多编程语言都提供了相应的函数。
下面将介绍几种常见的函数,它们可以用来返回给定文本字符串中字符的个数。
1. len()函数len()函数是Python编程语言中常用的一个函数,它可以返回给定字符串的长度,即字符串中字符的个数。
例如,对于字符串"Hello World!",使用len()函数可以得到字符串中字符的个数为12。
2. strlen()函数strlen()函数是C语言中常用的一个函数,它可以返回给定字符串的长度,即字符串中字符的个数。
例如,对于字符串"Hello World!",使用strlen()函数可以得到字符串中字符的个数为12。
3. length()函数length()函数是JavaScript编程语言中常用的一个函数,它可以返回给定字符串的长度,即字符串中字符的个数。
例如,对于字符串"Hello World!",使用length()函数可以得到字符串中字符的个数为12。
4. str.size()函数str.size()函数是C++编程语言中string类的成员函数,它可以返回给定字符串的长度,即字符串中字符的个数。
例如,对于字符串"Hello World!",使用str.size()函数可以得到字符串中字符的个数为12。
5. len()方法len()方法是Java编程语言中String类的方法,它可以返回给定字符串的长度,即字符串中字符的个数。
例如,对于字符串"Hello World!",使用len()方法可以得到字符串中字符的个数为12。
6. length()方法length()方法是JavaScript编程语言中String类的方法,它可以返回给定字符串的长度,即字符串中字符的个数。
sqlnvarchar类型和varchar类型存储中⽂字符长度
今天遇到了,随⼿记录⼀下。
sql server 存储数据⾥⾯
NVARCHAR 记录中⽂的时候是⼀个中⽂对应⼀个字符串长度,记录英⽂也是⼀个字母⼀个长度标点符号也是⼀样。
VARCHAR 记录中⽂的时候⼀个中⽂对应两个字符串长度,记录英⽂是⼀个字母长度,标点符号空格的没测。
优缺点暂时不列,记⼀下⼤致区别:
VARCHAR⽐NVARCHAR更加节省空间,但是⼀般是⽤在国外记录英⽂上⾯会⽐较好。
如果国外安装的语⾔包⾥⾯没有中⽂包⽤VARCHAR存的中⽂会变成?解决⽅案很简单在添加的时候加 ‘N (你记录的数据)’ 就能解决了
不过这个⽅法对已经录⼊的数据似乎没有办法,或许试⼀下SQL改变排序⽅式还有的救。
总体在国内⽤NVARCHAR会⽐较好,也⽐较⽅便吧。
数据库中的字符类型存储字符和汉字的数量sqlServer2012(936 简体中⽂GBK )为例:例如: varchar(10),只能存储10个英⽂字符或数字,也只能存储5个汉字; char(10),只能存储10个英⽂字符或数字,也只能存储5个汉字; nvarchar(10),即存储10个英⽂字符或数字,也能存储10个汉字; nchar(10),即存储10个英⽂字符或数字,也能存储10个汉字; varchar(max),⼤值数据类型最多可以存储2^30-1个字节的数据(varchar()、nvarchar()、varbinary())⼩结:Unicode字符集就是为了解决字符集这种不兼容的问题⽽产⽣的,它所有的字符都⽤两个字节表⽰,即英⽂字符也是⽤两个字节表⽰。
⽽前缀n就表⽰Unicode字符,⽐如nchar,nvarchar,这两种类型使⽤了Unicode字符集。
超过⼤⼩会提⽰出错。
补充说明:sql server中的Varchar和Nvarchar的区别:1. Varchar按实际字节长度存储,1个汉字1字节,1个英⽂1字节,长度介于1和8000之间,存储⼤⼩为输⼊数据的字节的实际长度2. Nvarchar按字符数量存储,不论汉字或英⽂,都是2字节,长度介于1与4000之间,存储⼤⼩是所输⼊字符个数的两倍(n前缀的,n表⽰Unicode字符,即所有字符都占两个字节)3. 从存储⽅式上,nvarchar是按字符存储的,⽽ varchar是按字节存储的4. 从存储量上考虑, varchar⽐较节省空间,因为存储⼤⼩为字节的实际长度,⽽ nvarchar是双字节存储5. 如果你做的项⽬可能涉及不同国家语⾔之间的转换,建议⽤nvarchar,因为nvarchar是使⽤Unicode编码,会减少乱码的出现⼏率6. Char/NChar固定长度数据类型,不⾜的补英⽂半⾓空格。
LEN()函数:返回给定字符串表达式的字符(⽽不是字节)个数,其中不包含尾随空格。
简述字符数据在内存中的存储形式。
字符数据在内存中的存储形式是指将字符数据存储在计算机内存中的方式。
计算机内存是用来存储数据和程序的地方,而字符数据是指由字符组成的数据。
在计算机中,字符数据是以二进制形式进行存储的。
在计算机中,每个字符都有一个对应的编码值。
最常用的字符编码是ASCII码(American Standard Code for Information Interchange),它使用一个字节(8位)来表示一个字符。
ASCII 码共定义了128个字符,包括英文字母、数字、标点符号和控制字符等。
在内存中,每个字符都被存储为一个字节。
每个字节都有一个地址,通过该地址可以访问和操作存储在该地址上的字符数据。
字符数据的存储方式可以是连续的,也可以是分散的,这取决于字符数据在内存中的存储位置和分配方式。
在连续存储方式下,字符数据按照顺序被存储在内存中的连续地址上。
例如,字符串"Hello World"可以被存储为连续的字符数据,每个字符占一个字节,依次存储在连续的内存地址上。
在分散存储方式下,字符数据被存储在内存中的不连续地址上。
这种方式下,字符数据的每个字符可以被存储在内存的任意位置上,通过指针来记录字符数据的存储位置和顺序。
例如,字符串"HelloWorld"的每个字符可以被存储在不同的内存地址上,通过指针来连接这些地址,从而形成一个完整的字符串。
除了ASCII码外,还有其他的字符编码方式,如Unicode和UTF-8等。
Unicode是一种用来表示世界上所有字符的字符集,它为每个字符分配了一个唯一的编码值。
UTF-8是一种变长的字符编码方式,它可以用来表示Unicode字符集中的所有字符。
在使用Unicode和UTF-8编码时,字符数据的存储方式与ASCII 码有所不同。
由于Unicode和UTF-8编码使用的字符集更大,所以它们需要更多的字节来表示一个字符。
timestamp 例子(二)timestamp 例子时间戳(timestamp)是一个表示特定时间的单一值或者字符串。
它经常在计算机系统中使用,用于记录事件发生的时间或者为文件或数据添加时间标记。
下面是一些关于timestamp的例子,以及对它们的详细讲解。
1. UNIX 时间戳UNIX时间戳是一种常见的时间表示方法,它是指从协调世界时(UTC)的1970年1月1日00:00:00开始所经过的秒数。
UNIX时间戳通常以整数形式存储,比如。
这个数字代表着2021年4月28日00:00:00。
2. JavaScript 时间戳在JavaScript中,可以使用()方法获取当前时间的时间戳。
这个时间戳是一个整数,表示自1970年1月1日以来的毫秒数。
例如,()可能返回,它表示从1970年1月1日 00:00:00以来到当前时间的毫秒数。
3. 数据库中的时间戳许多数据库系统都支持特定的数据类型用于存储时间戳。
例如,MySQL中有一个叫做TIMESTAMP的数据类型,用于存储日期和时间。
这个数据类型可以存储从1970年1月1日00:00:00开始的秒数,类似于UNIX时间戳。
在MySQL中,可以使用函数UNIX_TIMESTAMP()将一个具体的日期和时间转换为UNIX时间戳。
4. 文件时间戳文件系统通常会为每个文件和目录存储创建时间、修改时间和访问时间的时间戳。
这些时间戳用于记录文件的相关信息,比如创建时间可以用于确定文件的新旧程度。
不同的操作系统可能采用不同的方式来存储这些时间戳,但它们通常是以数字形式表示的。
5. API 响应中的时间戳很多API在它们的响应中包含时间戳信息。
这些时间戳可以用于记录请求成功或失败的时间,或者其他特定事件的时间。
通常,API响应中的时间戳以ISO 8601格式表示,如T02:00:00Z。
6. 日志文件中的时间戳在日志文件中,时间戳可用于标记每个事件的发生时间。
这对于排查问题和调试非常有用。
#include "stdio.h"#include "conio.h"#include "string.h"#include "stdlib.h"#include "malloc.h"typedef struct code{char c;int weight;}CODE;CODE s[128]; /*用于存储记录过的字符数*/typedef struct node{char c;int tag; /*是否有双亲的标志*/int weight;char code[100]; /*该字符的huffman编码*/struct node *parents,*lc,*rc;}NODE;NODE *head;char filename1[40]={0}; /*源文件名*/char filename2[40]={0}; /*统计结果文件名称*/char filename3[40]={0}; /*压缩文件名称*/char filename4[40]={0}; /*解压后源文件名称*/int n;/*保存统计结果保存函数*/void save(void){int i;FILE *fp;printf("\nPlease input the huffcode file path:");gets(filename2);if((fp=fopen(filename2,"wt"))==NULL){printf("Can't open creat the huffcode file!\nPlease cheak the flie!");getch();return ;}n=0;for(i=1;i<=128;i++){if(s[i].weight==0)continue;n++; /*不存在的元素不输出*/}fprintf(fp,"%d",n);s[10].c='^'; /*因为回车在输出到huffcode中后不便于后面的读取,所以用英文中几乎不出现的字符 ^ 来代替会回车*/s[32].c='~'; /*空格在读取字符时会出错,用~代替*/s[9].c=127;for(i=1;i<=128;i++){if(s[i].weight==0)continue; /*过滤权值非0字符*/fprintf(fp," %c %d",s[i].c,s[i].weight);}fclose(fp);}/*建树模块*/NODE *BuildTree(void){int min1=32767,min2=32767,i,j;NODE *p1,*p2;char cd[20];FILE *fp;if((fp=fopen(filename2,"rt"))==NULL){printf("Sorry!the code file can't be opened!\nPlease check it !");exit(0) ;}fscanf(fp,"%d",&n);head=(NODE *)malloc(2*n*sizeof(NODE));/*多申请一个空间,0号空间空留不用,构成一个结构体数组head[2*n]*/ /*n为字符的种类*/for(i=1;i<=n;i++){fscanf(fp," %c %d",&head[i].c,&head[i].weight); /* %c和%d 之前的空格不能少,因为是格式化输出的*/head[i].tag=0; /*无双亲*/head[i].parents=NULL;head[i].lc=NULL;head[i].rc=NULL;}for(i=1;i<=3;i++){ /*还原被代替的字符*/if(head[i].c==127)head[i].c=9;else if (head[i].c=='^')head[i].c='\n';else if(head[i].c=='~')head[i].c=' ';else ;}for(i=1;i<n;i++) /*n个字符操作n-1次*/{min1=min2=32767;p1=NULL;p2=NULL;for(j=1;j<n+i;j++)if((head[j].weight<min1)&&(head[j].tag==0)){min2=min1;p2=p1;min1=head[j].weight;p1=&head[j];}else if((head[j].weight<min2)&&(head[j].tag==0)){min2=head[j].weight;p2=&head[j];} /*找出了最小p1的次小的p2*/p1->tag=1;p2->tag=1;head[n+i].weight=p1->weight+p2->weight;p1->parents=&head[n+i];p2->parents=&head[n+i];head[n+i].parents=NULL;head[n+i].lc=p1;head[n+i].rc=p2;head[n+i].tag=0;}if(n==1) /*一种字符构不成huffman树,定义其代码*/{head[1].code[1]='\0';}else{for(i=1;i<=n;i++){j=19;cd[j]='\0';p1=&head[i];for(p2=p1->parents;p2!=NULL;p2=p1->parents){if(p1==p2->lc)cd[--j]='0';elsecd[--j]='1'; /*用栈来存储编码实现对其顺序的调整*/p1=p2;}strcpy(head[i].code,&cd[j]);}}fclose(fp);return head; /*申请了2n个空间,0号不用最后一个是2n -1*/}/*文件校验函数*/void CheckSymbol(void){FILE *fp,*fp1;char ch1,ch2;int num=0;if((fp=fopen(filename1,"rt"))==NULL){printf("Can't open the source file!");getch();return ;}if((fp1=fopen(filename4,"rt"))==NULL){printf("Can't open the restore file!");getch();return ;}while(feof(fp)==0||feof(fp1)==0){ch1=fgetc(fp);ch2=fgetc(fp1);if(ch1==ch2){ num++; continue; }else{printf("\nThe %d character is difficult!",num);printf("\nPlease check it!");getch();return ;}}printf("\nSucceeful!The file decoded is right!");getch();}/*统计主函数*/void CountSymbol(void){FILE *fp;char t;int i;for(i=0;i<=128;i++){s[i].c=i;s[i].weight=0;}printf("\nPlease input the file's path and file name:");getchar();gets(filename1);if((fp=fopen(filename1,"rt"))==NULL){printf("Can't open the source file!\nPlease cheak the flie!"); getch();return ;}t=0;while(feof(fp)==0) /*0时文件未结束*/{t=fgetc(fp);s[t].weight++; /*按照ASCII码表的对应位置统计权值*/}save();fclose(fp);printf("\nThe code has been saved succeful!");getch();}/*编码模块*/void Encode(NODE *head){FILE *fp,*fpc;char t,cd[20];int i;fp=fopen(filename1,"rt"); /*遍历比较得到huffman编码*/fpc=fopen("encode.txt","wt"); /*生成中间0 1 代码文件*/while(feof(fp)==0){t=fgetc(fp);for(i=1;i<=n;i++)if(t==head[i].c){strcpy(cd,head[i].code);fprintf(fpc,"%s",cd);}}fclose(fp);fclose(fpc);}/*7位压缩模块*/void Compress(void){int n=0,i=6;long num=0; /*统计0 1 个数*/unsigned char ch=0,ch1;FILE *fp,*fp1;if((fp=fopen("encode.txt","rt"))==NULL){printf("Can't open the code file!\nPlease cheak the flie!"); getch();return ;}printf("\nplease input the compressed file path and name:");getchar();gets(filename3);if((fp1=fopen(filename3,"wt"))==NULL){printf("Can't open the compressed file!\nPlease cheak the fil e!");getch();return ;}while(feof(fp)==0){num++;ch1=fgetc(fp); /*统计出了 0 1 个数*/} /*遍历文件得到字符的个数,保存在filename3文件中*/num--;rewind (fp); /*将文件指针移回文件的头*/fprintf(fp1,"%ld",num);ch1='\\';fprintf(fp1,"%c",ch1); /*注意输出的格式*/while(feof(fp)==0){ch1=fgetc(fp); /*将数字0和1转换为字符0和1*/if(ch1==255) /*因为ch1只可能是结束标志或0 、1*/ {fputc(ch,fp1);break;}ch1-=48;ch1<<=i--; /*从文件中读取字符*/ch=ch|ch1; /*与0取或将7个数字合并未一个*/n++;if(n%7==0){if(ch==7) /*屏对文件有影响的字符*/ch=128; /*7号显示不出,8号后退一个吃掉前一个字符*/else if (ch==8) /*13号显示不出,10号是换行,26号文件结束字符*/ch=129;else if (ch==9)ch=130;else if (ch==10)ch=131;else if (ch==13)ch=132;else if (ch==26)ch=133;else ;fputc(ch,fp1);n=0;i=6;ch=0; /*初始化*/}}fclose(fp1);fclose(fp);}/*解码模块*/void Decode(NODE *head,int n){FILE *fp,*fp1;char t='0'; /*随便赋初值*/NODE *p1,*p0;p1=p0=&head[2*n-1];if((fp=fopen("d:\\encode.txt","rt"))==NULL){printf("Can't open the compress file!");getch();return ;}if((fp1=fopen(filename4,"wt"))==NULL){printf("Can't open the decode file!");getch();return ;}while(feof(fp)==0){t=fgetc(fp); /*只有一个节点是构不成huffman树*/ if(t=='0'){if(p1->lc==NULL)fprintf(fp1,"%c",p1->c);else{p1=p1->lc;if(p1->lc==NULL&&p1->rc==NULL){fprintf(fp1,"%c",p1->c);p1=p0;}}}else if(t=='1'){p1=p1->rc;if(p1->rc==NULL&&p1->lc==NULL){fprintf(fp1,"%c",p1->c);p1=p0;}}}fclose(fp);fclose(fp1);}/*解7位压缩模块*/void Uncompress(void){FILE *fp,*fp1;long num;int i;unsigned char ch,exp; /*在tc环境下默认有符号,但在vc环境下默认有符号*/if((fp=fopen(filename3,"rt"))==NULL){printf("Can't open file!\nPlease cheak the flie!");getch();exit(1);}if((fp1=fopen("d:\\encode.txt","wt"))==NULL){printf("Can't open file!\nPlease cheak the flie!");getch();exit(1);}fscanf(fp,"%ld",&num); /*注意格式*/fscanf(fp,"%c",&ch); /*取出'\'*/while(feof(fp)==0) /*只读出有用字符,而且解决了中断问题!!*/{ch=fgetc(fp);if(ch==255) /*这块有问题,最后11111111时会出错!*/break;if(ch==128) /*屏蔽对文件有影响的ASCII码*/ch=7; /*7号显示不出,8号后退一个吃掉前一个字符,9号tab多时出错*/else if (ch==129) /*13号显示不出,10号是换行,26号文件结束字符*/ch=8;else if (ch==130)ch=9;else if (ch==131)ch=10;else if (ch==132)ch=13;else if (ch==133)ch=26;else ;for(i=1;i<8;i++){exp=ch; /*寄存*/exp<<=i;exp>>=7;exp+=48; /*将从文件中读出的字符中的有效数字还原成数字*/if(num!=0) /*输出的总的有效的位数够后就不进行输出*/ {num--; /*只将有效的字符输出*/fputc(exp,fp1);}}}fclose(fp1);fclose(fp);}/*压缩率计算模块*/void Rate(void){FILE *fp,*fp1;char ch=1;float num=0.0,num1=0.0;float weight,weight1,rate;fp=fopen(filename1,"rt");fp1=fopen(filename3,"rt");while(feof(fp)==0){ch=fgetc(fp); /*比较源文件和压缩后的文件*/num++;}num--; /*减去末尾结束标志*/weight=num/1024;while(feof(fp1)==0){ch=fgetc(fp1);num1++;}num1--;/*减去末尾结束标志*/weight1=num1/1024;rate=weight1/weight;printf("\nThe source file weight is %.4f Kb!",weight);printf("\nThe compressed file weight is %.4fKb!",weight1); printf("\nThe compresse rete is %.2f %!",rate*100);getch();}/*编码压缩主函数*/void EncodeSymbol(void){NODE *head=NULL;head=BuildTree(); /*得到了huffman树的首地址*/Encode(head);Compress();/* remove("d:\\encode.txt"); */ /*将中间文件删除*/printf("\nThe file has been compressed!");printf("\nIt was saved in %s",filename2);Rate();}/*解码压缩主函数*/void DecodeSymbol(void){NODE *head=NULL;printf("\nPlease input the code file path:");getchar();gets(filename2);printf("\nPlease input the compressed file path:");gets(filename3);printf("\nPlease input the restored file path:");gets(filename4);head=BuildTree();Uncompress();Decode(head,n);/* remove("d:\\encode.txt"); *//*删除中间文件*/printf("\nThe file has been restored!");printf("\nIt is saved in the %s!",filename4);getch();}/*主函数*/void main(void){int choice;do{clrscr();printf("\n\n\n\n\n\n\n");printf(" This is a huffman code \n ");printf("\n 1: Count character freque ncy");printf("\n 2: Encode the file");printf("\n 3: Decode the file");printf("\n 4: Check the result"); printf("\n 0: exit\n\n");printf("\n Please input your chose:");scanf("%d",&choice);while(choice<0||choice>4){printf(" Sorry !The choice is wrong!\n Please input it again:");scanf("%d",&choice);}switch(choice){case 1: CountSymbol(); break; /*计数模块*/case 2: EncodeSymbol(); break; /*编码模块*/case 3: DecodeSymbol(); break; /*解码模块*/case 4: CheckSymbol(); break; /*校验模块*/case 0: exit(0); /*正常退出*/}}while(1);}。