Linux C语言程序设计(四)——枚举与结构体

原创 2015年07月09日 20:37:29

1、结构体

        结构体不同于我们之前了解到的基本数据类型,结构体数据类型是一种复合数据类型,它可以包括一些基本的数据类型。

        复合数据类型一方面可以从整体上当作一个数据使用,另一方面也可以分别访问它的各组成单元,复合数据类型的这种两面性提供了一种数据抽象。如果学习过java这样的面向对象的语言,会对结构体这样的抽象数据结构了解得比较深刻。比如,如果我们在二维坐标系上有一个点,那么如何描述这个点呢?很显然,它有横坐标和纵坐标,我们使用x和y表示。比如(5,2)就表示横轴为5,纵轴为2。换到我们的程序语言中,单纯的整形或者浮点型这样的单一数据结构已经无法满足需求,我们需要寻找另外的一种方式。

那么这个时候,我们的结构体就用上了,我们可以使用如下的数据结构:

struct point_struct {
	double x, y;
};

point_struct 表示的是点这个对象名称,这里我们称之为结构体对象名称。其中的x和y分别代表横纵坐标,如果我们想声明两个点a、b,那么我们会使用如下的代码:

struct point_struct a,b;

我们来看一段实例代码,如下:

#include <stdio.h>
int main(void)
{
	struct point_struct { double x, y; } z;
	double x = 3.0;
	z.x = x;
	z.y = 4.0;
	if (z.y < 0){
		printf("z=%f%fi\n", z.x, z.y);
	}else{
		printf("z=%f+%fi\n", z.x, z.y);
	}
	return 0;
}

2、数据抽象

数据抽象是一个比较难解释的概念,我们上文讲到如何使用结构体描述一个点,这里我们将介绍,如何使用结构体来抽象一个函数。

我们知道,在C语言中,前辈先人为我们封装了很多不同的函数库,其中数学函数库是非常大的一类,我们也经常使用。比如我们要做两个数的加减乘除,就可以找到相应的函数来计算,而不必再手动造轮子。但是学习要究其原理,我们今天就来手动造一个加减乘除的轮子。

如上,我们应该先描述一个点,我们暂且将两个数放在一起称之为点,与上文一致,不再描述。我们定义一些函数,加减乘除,举例加法的函数如下:

double addFunc(struct point_struct num){
	return num.x + num.y;
}

如上,我们传递一个结构体数据类型给这个addFunc函数,使用它的x点和y点数值进行相加,然后返回给调用者。我们测试一下:

#include <stdio.h>
int main(void)
{
	struct point_struct { double x, y; } z;
	
	z.x = 3.0;
	z.y = 4.0;

	printf("z=%f\n", addFunc(z));

	return 0;
}


3、枚举标志

        在上文中,我们使用了两次结构体这样的概念,一次是点,一次是类似点(两个是相互独立的数字)。那么,既然这个数据结构可以同时适用于两种不同的应用场景,我们能不能将之合并使用,而用一个标志位来进行一定的区分呢?答案是肯定的。

        于是这里就引入我们的枚举类型,如下:

enum coordinate_type { POINT, NUM };
struct complex_struct {
	enum coordinate_type t;
	double a, b;
};

        enum关键字的作用和struct关键字类似,把coordinate_type这个标识符定义为一个Tag,只不过struct complex_struct表示一个结构体类型,而enum coordinate_type表示一个枚举类型。

        枚举类型的成员是常量,它们的值编译器自动分配,例如定义了上面的枚举类型之后, RECTANGULAR就表示常量0, POLAR就表示常量1。


有一点需要注意,结构体的成员名和变量名不在同一命名空间,但枚举的成员名和变量名却在同一命名空间,所以会出现命名冲突。如下的命名就是不合法的:

int main(void)
{
	enum coordinate_type { RECTANGULAR = 1, POLAR };
	int RECTANGULAR;
	printf("%d %d\n", RECTANGULAR, POLAR);
	return 0;
}

4、嵌套结构体

        结构体也是一种递归定义:结构体由数据类型定义,因为结构体的成员具有数据类型,而数据类型由结构体定义,因为结构体本身也是一种数据类型。换句话说,结构体也可以嵌套。例如我们在复数的基础上定义复平面上的线段:

struct Segment {
	struct complex_struct start;
	struct complex_struct end;
};

嵌套结构体可以嵌套地初始化。例如:

struct Segment s = {{ 1.0, 2.0 }, { 4.0, 6.0 }};

《C语言及程序设计》实践项目——初练结构体

返回:贺老师课程教学链接【项目1-复数结构体】编写一个程序,首先定义一个复数数据类型,即结构类型。然后按照复数的运算规则进行计算,并按照复数表示的格式进行输出,请将程序补充完整。#include s...

《C语言及程序设计》实践参考——复数结构体

返回:贺老师课程教学链接【项目1-复数结构体】编写一个程序,首先定义一个复数数据类型,即结构类型。然后按照复数的运算规则进行计算,并按照复数表示的格式进行输出,请将程序补充完整。#include s...

《C语言及程序设计》实践参考——点结构体

返回:贺老师课程教学链接【项目3-点结构体】下面定义了一个表示平面上一点的结构体类型:struct Point { float x; //横坐标 float y; //纵坐...

《C语言及程序设计》实践项目——结构体应用

返回:贺老师课程教学链接【项目1-学生成绩统计】 每位同学的信息学号、姓名、C、高数、英语成绩。定义一个学生成绩的结构体数组,其中的数据成员包括学号(char num[13])、姓名(name)、三...

Linux C语言程序设计(一)——常量、变量和表达式

1、Hello World 好像每一次都要用Hello World开始一门语言的学习,好吧,给出一个例子,如下: #include int main(){ printf("this is Hello...
  • ljtyzhr
  • ljtyzhr
  • 2015年07月06日 14:45
  • 769

Linux C语言程序设计(十七)——Socket编程的基础解析

1、socket概念 socket这个词可以表示很多概念: 1)在TCP/IP协议中, “IP地址+TCP或UDP端口号”唯一标识网络通讯中的一个进程, “IP地址+端口号”就称为socket。 2)...
  • ljtyzhr
  • ljtyzhr
  • 2015年09月05日 15:06
  • 493

Linux C语言程序设计(十四)——文件系统与I/O

1、C标准I/O库函数 先看看C标准I/O库函数是如何用系统调用实现的。 fopen(3) 调用open(2)打开指定的文件,返回一个文件描述符(就是一个int类型的编号),分配一个FILE结构...
  • ljtyzhr
  • ljtyzhr
  • 2015年08月30日 22:27
  • 613

Linux C语言程序设计(九)——gdb调试

1、单步执行 add_range函数从low加到high,在main函数中首先从1加到10,把结果保存下来,然后从1加到100,再把结果保存下来。 #include int add_range(...
  • ljtyzhr
  • ljtyzhr
  • 2015年07月28日 15:12
  • 290

Linux C语言程序设计(七)——栈与队列

1、数据结构         数据结构( Data Structure) 是数据的组织方式。程序中用到的数据都不是孤立的,而是有相互联系的,根据访问数据的需求不同,同样的数据可以有多种不同的组织方式。...
  • ljtyzhr
  • ljtyzhr
  • 2015年07月22日 16:24
  • 415

Linux C语言程序设计(五)——数组基本概念与解析

1、数组基本概念         和结构体类似,数组( Array) 也是一种复合数据类型,它由一系列相同类型的元素( Element) 组成。数组元素的存储空间是相邻的,数组中的元素可以是基本数据...
  • ljtyzhr
  • ljtyzhr
  • 2015年07月12日 16:19
  • 316
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Linux C语言程序设计(四)——枚举与结构体
举报原因:
原因补充:

(最多只允许输入30个字)