热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

c语言初始化指针指向结构体数组,详解C++中的指针结构体数组以及指向结构体变量的指针...

C结构体数组一个结构体变量中可以存放一组数据(如一个学生的学号、姓名、成绩等数据)。如果有10个学生的数据需要参加运算,显然应该用数组,这就是结构体数组

C++结构体数组

一个结构体变量中可以存放一组数据(如一个学生的学号、姓名、成绩等数据)。如果有10个学生的数据需要参加运算,显然应该用数组,这就是结构体数组。结构体数组与以前介绍过的数值型数组的不同之处在于:每个数组元素都是一个结构体类型的数据,它们都分别包括各个成员项。

定义结构体数组和定义结构体变量的方法相仿,定义结构体数组时只需声明其为数组即可。如:

struct Student //声明结构体类型Student

{

int num;

char name[20];

char sex;

int age;

float score;

char addr[30];

};

Student stu[3]; //定义Student类型的数组stu

也可以直接定义一个结构体数组,如:

struct Student

{

int num;

char name[20];

char sex;

int age;

float score;

char addr[30];

}stu[3];

struct

{

int num;

char name[20];

char sex;

int age;

float score;

char addr[30];

}stu[3];

结构体数组的初始化与其他类型的数组一样,对结构体数组可以初始化。如:

struct Student

{

int num;

char name[20];

char sex;

int age;

float score;

char addr[30];

}stu[3]={

{10101,″Li Lin″, ′M′, 18,87.5, ″103 Beijing Road″},

{10102,″Zhang Fun″,′M′,19,99, ″130 Shanghai Road″},

{10104,″Wang Min″,′F′, 20,78.5, ″1010 Zhongshan Road″}

};

定义数组stu时,也可以不指定元素个数,即写成以下形式:

stu[ ]={{…},{…},{…}};

编译时,系统会根据给出初值的结构体常量的个数来确定数组元素的个数。一个结构体常量应包括结构体中全部成员的值。

当然,数组的初始化也可以用以下形式:

Student stu[ ]={{…},{…},{…}}; //已事先声明了结构体类型Student

由上可以看到,结构体数组初始化的一般形式是在所定义的数组名的后面加上 ={初值表列};

结构体数组应用举例

下面举一个简单的例子来说明结构体数组的定义和引用。

【例】对候选人得票的统计程序。设有3个候选人,最终只能有1人当选为领导。今有10个人参加投票,从键盘先后输入这10个人所投的候选人的名字,要求最后输出这3个候选人的得票结果。

可以定义一个候选人结构体数组,包括3个元素,在每个元素中存放有关的数据。程序如下:

#include

using namespace std;

struct Person //声明结构体类型Person

{

char name[20];

int count;

};

int main( )

{

//定义Person类型的数组,内容为3个候选人的姓名和当前的得票数

Person leader[3]={"Li",0,"Zhang",0,"Fun",0};

int i,j;

char leader_name[20]; //leader_name为投票人所选的人的姓名

for(i=0;i<10;i++)

{

cin>>leader_name; //先后输入10张票上所写的姓名

for(j=0;j<3;j++) //将票上姓名与3个候选人的姓名比较

//如果与某一候选人的姓名相同,就给他加一票

if(strcmp(leader_name,leader[j].name)==0) leader[j].count++;

}

cout<

for(i=0;i<3;i++) //输出3个候选人的姓名与最后得票数

{

cout<

}

return 0;

}

运行情况如下:

Zhang↙ (每次输入一个候选人的姓名)

Li↙

Fun↙

Li↙

Zhang↙

Li↙

Zhang↙

Li↙

Fun↙

Wang↙

Li:4 (输出3个候选人的姓名与最后得票数)

Zhang:3

Fun:2

程序定义一个全局的结构体数组leader,它有3个元素,每一元素包含两个成员,即name(姓名)和count(得票数)。在定义数组时使之初始化,使3位候选人的票数都先置零。

在这个例子中,也可以不用字符数组而用string方法的字符串变量来存放姓名数据,程序可修改如下:

#include

#include

using namespace std;

struct Person

{

string name;//成员name为字符串变量

int count;

};

int main( )

{

Person leader[3]={"Li",0,"Zhang",0,"Fun",0};

int i,j;

string leader_name;// leader_name为字符串变量

for(i=0;i<10;i++)

{

cin>>leader_name;

for(j=0;j<3;j++)

if(leader_name==leader[j].name) leader[j].count++//用“==”进行比较

}

cout<

for(i=0;i<3;i++)

{

cout<

}

return 0;

}

运行情况与前相同。显然后一个程序节省内存空间,使用更方便,易读性更好。但是 有些C++系统不能对包含string成员的结构体变量初始化,需要作一些修改才能运行, 读者可上机试一下。

C++指向结构体变量的指针

一个结构体变量的指针就是该变量所占据的内存段的起始地址。可以设一个指针变量,用来指向一个结构体变量,此时该指针变量的值是结构体变量的起始地址。指针变量也可以用来指向结构体数组中的元素。

通过指向结构体变量的指针引用结构体变量中的成员

下面通过一个简单例子来说明指向结构体变量的指针变量的应用。

【例】指向结构体变量的指针的应用。

#include

#include

using namespace std;

int main( )

{

struct Student//声明结构体类型student

{

int num;

string name;

char sex;

float score;

};

Student stu;//定义Student类型的变量stu

Student *p=&stu;//定义p为指向Student类型数据的指针变量并指向stu

stu.num=10301;//对stu中的成员赋值

stu.name="Wang Fun";//对string变量可以直接赋值

stu.sex=&#39;f&#39;;

stu.score=89.5;

cout<

stu.score<

cout<

num<

return 0;

}

程序运行结果如下:

10301 Wang Fun f 89.5 (通过结构体变量名引用成员)

10301 Wang Fun f 89.5 (通过指针引用结构体变量中的成员)

两个cout语句输出的结果是相同的。

为了使用方便和使之直观,C++提供了指向结构体变量的运算符->,例如p->num表示指针p当前指向的结构体变量中的成员num。

p->num 和(*p).num等价。

同样

p->name等价于(*p).name。

也就是说,以下3种形式等价:

结构体变量.成员名。如stu.num。

(*p).成员名。如(*p).num。

p->成员名。如p->num。

“->”称为指向运算符。

请分析以下几种运算:

p->n 得到p指向的结构体变量中的成员n的值。

p->n++ 得到p指向的结构体变量中的成员n的值,用完该值后使它加1。

++p->n 得到p指向的结构体变量中的成员n的值,并使之加1,然后再使用它。

用结构体变量和指向结构体变量的指针构成链表

链表是一种常见的重要的数据结构。下图表示最简单的一种链表(单向链表)的结构。

链表有一个“头指针”变量,图中以head表示,它存放一个地址。该地址指向一个元素。链表中的每一个元素称为“结点”,每个结点都应包括两个部分:

一是用户需要用的实际数据,

二是下一个结点的地址。

可以看到链表中各元素在内存中的存储单元可以是不连续的。要找某一元素,可以先找到上一个元素,根据它提供的下一元素地址找到下一个元素。

可以看到,这种链表的数据结构,必须利用结构体变量和指针才能实现。

可以声明一个结构体类型,包含两种成员,一种是用户需要用的实际数据,另一种是用来存放下一结点地址的指针变量。

例如,可以设计这样一个结构体类型:

struct Student

{

int num;

float score;

Student *next; //next指向Student结构体变量

};

其中成员num和score是用户需要用到的数据,相当于图7.8结点中的A, B, C, D。next是指针类型的成员,它指向Student类型数据(就是next所在的结构体类型)。用这种方法就可以建立链表。见图。

图中每一个结点都属于Student类型,在它的成员next中存放下一个结点的地址,程序设计者不必知道各结点的具体地址,只要保证能将下一个结点的地址放到前一结点的成员next中即可。

下面通过一个例子来说明如何建立和输出一个简单链表。

【例】建立一个如图所示的简单链表,它由3个学生数据的结点组成。输出各结点中的数据。

#define NULL 0

#include

using namespace std;

struct Student

{

long num;

float score;

struct Student *next;

};

int main( )

{

Student a,b,c,*head,*p;

a. num=31001;

a.score=89.5; //对结点a的num和score成员赋值

b. num=31003;

b.score=90; //对结点b的num和score成员赋值

c. num=31007;

c.score=85; //对结点c的num和score成员赋值

head=&a; //将结点a的起始地址赋给头指针head

a.next=&b; //将结点b的起始地址赋给a结点的next成员

b.next=&c; //将结点c的起始地址赋给b结点的next成员

c.next=NULL; //结点的next成员不存放其他结点地址

p=head; //使p指针指向a结点

do

{

cout

p=p->next; //使p指向下一个结点

} while (p!=NULL); //输出完c结点后p的值为NULL

return 0;

}

本例是比较简单的,所有结点(结构体变量)都是在程序中定义的,不是临时开辟的,也不能用完后释放,这种链表称为静态链表。对各结点既可以通过上一个结点的next指针去访问,也可以直接通过结构体变量名a, b, c去访问。

动态链表则是指各结点是可以随时插入和删除的,这些结点并没有变量名,只能先找到上一个结点,才能根据它提供的下一结点的地址找到下一个结点。只有提供第一个结点的地址,即头指针head,才能访问整个链表。如同一条铁链一样,一环扣一环,中间是不能断开的。

建立动态链表,要用到后面介绍的动态分配内存的运算符new和动态撤销内存的运算符delete。



推荐阅读
  • c语言\n不换行,c语言printf不换行
    本文目录一览:1、C语言不换行输入2、c语言的 ... [详细]
  • C语言判断正整数能否被整除的程序
    本文介绍了使用C语言编写的判断正整数能否被整除的程序,包括输入一个三位正整数,判断是否能被3整除且至少包含数字3的方法。同时还介绍了使用qsort函数进行快速排序的算法。 ... [详细]
  • 本文介绍了为什么要使用多进程处理TCP服务端,多进程的好处包括可靠性高和处理大量数据时速度快。然而,多进程不能共享进程空间,因此有一些变量不能共享。文章还提供了使用多进程实现TCP服务端的代码,并对代码进行了详细注释。 ... [详细]
  • 本文介绍了解决二叉树层序创建问题的方法。通过使用队列结构体和二叉树结构体,实现了入队和出队操作,并提供了判断队列是否为空的函数。详细介绍了解决该问题的步骤和流程。 ... [详细]
  • 本文介绍了C函数ispunct()的用法及示例代码。ispunct()函数用于检查传递的字符是否是标点符号,如果是标点符号则返回非零值,否则返回零。示例代码演示了如何使用ispunct()函数来判断字符是否为标点符号。 ... [详细]
  • 动态规划算法的基本步骤及最长递增子序列问题详解
    本文详细介绍了动态规划算法的基本步骤,包括划分阶段、选择状态、决策和状态转移方程,并以最长递增子序列问题为例进行了详细解析。动态规划算法的有效性依赖于问题本身所具有的最优子结构性质和子问题重叠性质。通过将子问题的解保存在一个表中,在以后尽可能多地利用这些子问题的解,从而提高算法的效率。 ... [详细]
  • 李逍遥寻找仙药的迷阵之旅
    本文讲述了少年李逍遥为了救治婶婶的病情,前往仙灵岛寻找仙药的故事。他需要穿越一个由M×N个方格组成的迷阵,有些方格内有怪物,有些方格是安全的。李逍遥需要避开有怪物的方格,并经过最少的方格,找到仙药。在寻找的过程中,他还会遇到神秘人物。本文提供了一个迷阵样例及李逍遥找到仙药的路线。 ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • 本文介绍了在Windows系统上使用C语言命令行参数启动程序并传递参数的方法,包括接收参数程序的代码和bat文件的编写方法,同时给出了程序运行的结果。 ... [详细]
  • 本文介绍了使用哈夫曼树实现文件压缩和解压的方法。首先对数据结构课程设计中的代码进行了分析,包括使用时间调用、常量定义和统计文件中各个字符时相关的结构体。然后讨论了哈夫曼树的实现原理和算法。最后介绍了文件压缩和解压的具体步骤,包括字符统计、构建哈夫曼树、生成编码表、编码和解码过程。通过实例演示了文件压缩和解压的效果。本文的内容对于理解哈夫曼树的实现原理和应用具有一定的参考价值。 ... [详细]
  • 本文介绍了GTK+中的GObject对象系统,该系统是基于GLib和C语言完成的面向对象的框架,提供了灵活、可扩展且易于映射到其他语言的特性。其中最重要的是GType,它是GLib运行时类型认证和管理系统的基础,通过注册和管理基本数据类型、用户定义对象和界面类型来实现对象的继承。文章详细解释了GObject系统中对象的三个部分:唯一的ID标识、类结构和实例结构。 ... [详细]
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • Go语言实现堆排序的详细教程
    本文主要介绍了Go语言实现堆排序的详细教程,包括大根堆的定义和完全二叉树的概念。通过图解和算法描述,详细介绍了堆排序的实现过程。堆排序是一种效率很高的排序算法,时间复杂度为O(nlgn)。阅读本文大约需要15分钟。 ... [详细]
  • 本文介绍了Codeforces Round #321 (Div. 2)比赛中的问题Kefa and Dishes,通过状压和spfa算法解决了这个问题。给定一个有向图,求在不超过m步的情况下,能获得的最大权值和。点不能重复走。文章详细介绍了问题的题意、解题思路和代码实现。 ... [详细]
author-avatar
呦呦嘉宾
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有