数据类型研究及在数据流读取中的应用

2015-07-24 11:27夏显鄂
电脑知识与技术 2015年14期
关键词:数据类型数据流

夏显鄂

摘要:为了提高数据流检验效率,论述了C语言中整型、实型、数组、结构体等各种数据类型的具体内容,在内存中的存储形式,和大小端字节序的判断及转换方法。应用数据类型的性质,提出了不需要重复编译的数据流读取应用,描述了用户操作接口,文件读取基本开发流程,阐述了在一维和多维数组,或者在结构体文件等情况下进行解析等关键技术,取得了较好的使用效果,同样适用于网络数据流。

关键词:数据类型;大小端字节序;数据流;词法分析;编译

中图分类号:TP312 文献标识码:A 文章编号:1009-3044(2015)14-0001-03

Abstract: To improve efficiency of testing data stream, concrete content of data type in C language is discussed, for example integer, real, array, struct etc. Data type store in memory, judgment and convert method of big-little endian byte order are depicted. With data type property, application of reading data stream without compiling repeatedly is presented. Users operation interface, main develop procedure of reading file, key technology of one dimension and many dimension array resolution, or struct file analysis are described. Take effect better in practice and apply to network data stream.

Key words: data type; big-little endian byte order; data stream; lexical analysis; compile

著名计算机科学家尼古拉斯.沃斯(Niklaus Wirth)提出一个公式:数据结构+算法=程序。程序主要包括两方面的内容:

1)数据的描述。程序中数据的类型和数据的组织形式(数据结构)。

2)操作的描述。操作步骤(算法)。

数据是操作的对象,操作是对数据进行加工处理,得到期望结果。算法处理的对象是数据,数据以某种特定形式存在,如整数、实数、字符等。不同数据之间还存在某些联系,如字符数组由若干字符组成等等。数据结构是指数据的组织形式,如数组就是一种数据结构。处理同一类问题,如果数据结构不同,算法也会不同,而数据结构正是以数据类型的形式出现的。

1研究内容

1.1数据类型

C语言中数据有常量和变量之分。程序中用到的所有数据都需要指定数据类型,包括基本类型,构造类型,指针类型和空类型。其中基本类型有整型、字符型、实型。构造类型是由基本类型的数据按一定规则组成的,包括数组类型、结构体类型、共用体类型,和枚举类型。这些数据类型能构成更复杂的数据结构,例如指针和结构体可以构成栈、树、图等复杂的数据结构。

1.1.1整型

整型数据在内存中是以二进制形式存放的,任何整形类型的对象x的底层二进制都是这样的,假设有n位存储空间,dn-1dn-2…d2d1d0,其中每一个d为0或者1。对x计算等价的十进制数值,与x是有符号类型还是无符号类型相关。

1.1.2字符型

字符常量是用单引号括起来的一个字符。字符常量只能是单个字符,不能是字符串。转义字符是以斜线“\”开头,后跟一个或几个字符,具有特定的含义。

字符变量用来存放字符常量,只能存放一个字符,是将字符相应的ASCII码放到存储单元中,它的存储形式与整数的存储形式类似,所以一个字符数据既能以字符形式输出,也能以整数形式输出。

1.1.3 实型

实型数据又称为浮点型数据。实型数据的存储方式是按照指数形式存储。实型数据被分成小数部分和指数部分,分别存放。指数部分采用规范化的指数形式。

1.1.4数组类型

数组是有序数据的集合。数组中的每一个元素都属于同一个数据类型,用一个统一的数组名和下标来唯一地确定数组中的元素。或者说,数组是一组连续的内存单元,这些内存单元具有相同的大小,每一个单元被称为数组元素或者数组项。

一个数组可以分解为多个数组元素,这些数组元素可以是基本数据类型或是构造类型,或是指针类型。因此按数组元素的类型不同,数组又可分为数值数组、字符数组、指针数组、结构体数组等各种类别。其中,字符串作为字符数组存放,字符串结束标志以字符‘\0代表。系统对字符串常量自动加一个‘\0结束符,作为一维数组。

数组中各元素有先后顺序,它们在内存中按照这个先后顺序连续存放在一起。

1.1.5结构体类型

在一个组合项中包含若干个类型不同或者相同的数据项,这样的一种数据类型称为结构体类型。根据不同的编译器,内存存储会有所不同,在存储结构体时会按照内存对齐进行相关处理,用户可以通过预处理命令#pragma pack(n), n=1,2,4,8,16来改变对齐系统。

1.1.6共用体类型

几种不同类型的变量存放到同一段内存单元中,也就是使用覆盖技术,几个变量互相覆盖。这种使几个不同的变量共占同一段内存的结构,称为共用体,也称之为联合体。共用体变量的地址和它的成员的地址都是同一地址,共用体的长度以成员长度中最大的为准。

1.1.7枚举类型

如果一个变量只有几种可能的值,可以定义为枚举类型。“枚举”是指将变量的值一一列举出来,变量的值只限于列举出来的值的范围。定义枚举类型后,可以声明该枚举类型的变量,然后使用该变量存储枚举元素的数值,以防止用户提供无效值,使代码更加清晰。

1.1.8指针类型

变量的指针就是变量的地址。存放变量地址的变量是指针变量,用来指向另一个变量。C语言规定所有变量在使用前都需要定义和指定类型,并按此分配内存单元,而指针变量是专门用来存放地址的,需要定义为指针类型,其基类型用来指定该指针变量指向的变量的类型。

1.1.9空类型

用void定义空类型,或者称为无类型。一般不要求返回函数值的函数,定义为void类型,保证正确调用,减少程序出错。函数的参数如果是任意类型指针,应声明为void *类型 。

1.2大小端字节序

因为在计算机系统中,以字节为单位,每个地址单元都对应着一个字节,一个字节为8bit。C语言中除了8bit的char之外,还有16bit的short型,32bit的long型等。对于位数大于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,就存在如何将多个字节安排的问题,所以就有了大端存储模式和小端存储模式。

大端模式,是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中,地址由小向大增加,而数据从高位向低位放;

小段模式,是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中,高地址部分权值高,低地址部分权值低。

判断计算机的大小端字节序,可以使用共用体方法。

因为endian共用体只有一片内存,所有成员共享此片内存区域,并且大小为最大的成员所占的空间,所以endian共用体内存为2个字节。

先给短整形变量sh赋值为1,用字符型的变量c从共享内存中取数据,只能取得低字节数据。如果是小端字节序,内存中存放数据为0x0001,c取得的数据是0x01,打印结果是1,如果是大端字节序,内存中存放数据为0x0100,c取得的数据是0x00,打印结果是0。

2.1 需求描述

在开发人员进行系统开发时,经常遇到这样的情况,需要查看二进制数据流信息,通常采用的方法是,显示二进制数据转换后的十六进制数据,选取若干位,利用计算器进行换算,得到可读的十进制。或者通过编程实现读取该数据流,每次进行重复编译,再打印得到结果。有没有一种方法可以实现选择数据流,得到直接可读的结果呢?这样就可以大幅地提高调试效率。以32位机器,文件数据流为例,开发了应用。

首先进行用户界面设计,输入将要读取的数据流文件名和读取位置、变量名、类型,进行读取,显示结果。其中输入位置、变量名和类型的部分如图2。

2.2基本流程。

处理界面列表,以结构体方式存储列表{int 位移量,char[…] 变量名,char[…] 类型名},建立结构体数组。

2.2.1打开文件

使用fopen函数。

FILE *fp=fopen(文件名,使用文件方式);

文件名为要读取的二进制流文件。

使用文件方式为读取二进制型。

2.2.2文件定位

使用fseek函数,改变文件的位置指针。

fseek(文件类型指针,位移量,起始点)

“起始点”选择“文件开始”。

“位移量”指以“起始点”为基点,向前移动的字节数。这里填写用户界面表格中的起始位置+位移量。

2.2.3读文件,并取得数据。

使用fread函数。

fread(buffer,size,count,fp);

buffer:是一个指针,这里是读入数据的存放地址。size:要读取的字节数。

count:要进行读写多少个size字节的数据项。

fp:文件。

根据列表结构体的位置和类型,读取相应长度的字节数据,放入相应类型变量的地址。如果是char型数据读取1个字节,如果是short 型读取2个字节……等等,使用sizeof(数据类型)函数,即可得到数据类型字节数量,由 if…else…语句完成字段类型判断和数据读取,并转变成字符串数据,使用sprintf()函数。

char str[...]={0};

sprintf(str,”%d”,…);

将字符串与前面定义的列表结构体数组对应打印,即可得到用户界面列表的数值结果。

2.2.4关闭文件

使用fclose函数关闭文件。

fclose(文件指针)

2.3关键技术

大小端字节序。在用户界面表格中增加一列“大小端”,用户指明数据流大小端字节序,否则按照计算机的大小端字节序进行解析。

数组。针对于数组的解决方案,同样需要在用户界面表格中增加一列数组长度字段。如果是一维数组,可以采用循环方式处理,在变量名后面注明下标,按顺序处理数组长度的数据。如果是多维数组,需要记录维数,并且记录每一维度的数组长度,之后采用递归算法,打印出变量下标,和顺序处理多维数组的数据。

结构体文本文件。如果有结构体文本文件,不再需要输入用户界面表格,只要在用户界面上添加一处输入结构体文件的编辑框,选择结构体文件,就可以进行,但需要对结构体文件进行词法分析,从左至右逐个字符地对文件进行扫描,识别出单词符号,包括:

1)关键字,例如typedef,define,struct,int等。

2)标识符,如变量名,数组名等

3)常数,各种类型的常数,如2,5等

4)运算符,如+,-等

5)界符,如逗点,分号,括号等。

按照结构体文件解析结构体,需要处理以下内容:

1)将注释屏蔽 。

2)将“define”宏定义内容进行代换。

3)将“typedef”声明的类型进行代换。

4)包括“#include”所包含的文件内容,一起进行解析。

5)结构体中出现结构体变量内容,采用递归算法解析。

将解析的结构体文件内容按照类似用户界面表格样式的结构体数组存储,进行顺序读取数据流。注意文件结构体的对齐方式与数据流一致。

3 结束语

不进行重复再编译的,应用数据类型进行读取,除了读取文件数据流,也可以应用于实时读取网络传输的数据流,进行校验,同时也能将例如数字文本转换成整型或实型数据用于网络数据流发送检验。本应用大幅提高了调试效率,缩短了时间,可用于开发和测试等诸多实践中。本应用没有涉及共用体内容,将在下一步工作中继续完善。

参考文献:

[1] 谭浩强. C程序设计[M]. 北京: 清华大学出版社, 2010.

[2] JASMIN B, MARK S.闫锋欣, 张雪敏, 张君施, 等译 C++ Qt设计模式[M]. 北京: 电子工业出版社, 2012.

[3] 肖军模. 程序设计语言编译方法[M]. 大连: 大连理工大学出版社, 2000.

[4] 张素琴. 编译原理[M]. 北京: 清华大学出版社, 2012.

[5] 陈火旺. 程序设计语言编译原理[M]. 北京: 国防工业出版社, 2000.

[6] 梁建军. C语言数据类型转换的探讨[J]. 电脑知识与技术, 2010, 6(23): 6485-6487.

[7] 董鑫正. C语言教学中函数参数传递问题探讨[J]. 电脑知识与技术, 2010, 8(7): 1688-1689, 1701.

[8] 陈辉, 周自立. 嵌入式系统实验关于大小端转换方法的探讨[J]. 实验室研究与探索, 2008, 27(5): 66-67, 91.

猜你喜欢
数据类型数据流
详谈Java中的基本数据类型与引用数据类型
汽车维修数据流基础(上)
如何理解数据结构中的抽象数据类型
汽车维修数据流基础(下)
一种提高TCP与UDP数据流公平性的拥塞控制机制
S7—400PLC系统时间设置方法及在炼钢厂中的应用
基于数据流的结构化功能安全分析方法
基于数据流聚类的多目标跟踪算法
基于自定义XML数据类型的研究
VB语言的教学方法探讨