结构数组

 

  结构与数组的关系有两重:其一是在结构中使用数组类型作为结构的一个成员;其二是用结构类型作为数组元素的基类型构成数组。前者在前面的例题中已多次见到;后者是本节要讨论的内容。
  结构数组是一个数组,其数组中的每一个基本元素都是结构类型。说明结构数组的方法是:先定义一个结构,然后用结构类型说明一个数组变量。
例如:为记录100个人的基本情况。可以说明一个有100个元素的数组。每个元素的基类型为一个结构,在说明数组时可以写成:
struct person man[100];
man就是有100个元素的结构数组,数组的每个元素为person型结构。
要访问结构数组中的具体结构,必须遵守数组使用的规定,按数组名及其下标进行访问,要访问结构数组中某个具体结构下的成员,又要遵守有关访问结构成员的规定,使用"."访问运算符和成员名。访问结构数组成员的一般格式是:
结构数组名[下标].成员名
同一般的数组一样,结构数组中每个元素的起始下标从0开始,数组名称表示该结构数组的存储首地址。结构数组存放在一连续的内存区域中,它所占内存数目为结构类型的大小乘以数组元素的个数。结构数组man在内存中的存储如图11-3所示:


  例如,我们要将数组man中的3号元素赋值为:"Fangjin",'M',1963,9,13,就可以使用下列语句:
  strcpy(man[3].name, "Fangjin");
man[3].sex='M';
  man[3].birthday.year=1963;
man[3].birthday.month=9;
man[3].birthday.day=13; /* 为结构数组中一个元素的各个成员赋值 */
为了将"Fangjin"改为"Fangjun",修改其中的字母'i',可以使用下列语句,为结构数组中一个元素的数组成员中的一个字符赋值。
 man[3].name[5]='u';
  利用有3个元素的结构数组,可以很方便地改写例11-3.C,请读者自己编写。


例11-4:分析运行结果。
struct s
{ int x;
int *y; /* y: 结构中的成员是指向整型的指针 */
} ;
int data[5]={ 10, 20, 30, 40, 50 }; /* data: 整型数组 */
struct s array[5] =
{ 100, &data[0], 200, &data[1], 300, &data[2], 400, &data[3], 500, &data[4]
}; /* array: 结构数组,初始化 */
#include "stdio.h"
main ( )
{ int i=0; /* 说明变量i并赋初值 */
struct s s_var; /* s_ver: 一般的结构变量 */
s_var=array[0]; /* 将结构数组的array[0]整体赋给s_var */
printf ("%d/n", s_var.x); /* 按照结构变量的方式引用结构的成员 */
printf ("%d/n", *s_var.y);
printf ("For array:/n"); /* 以下是按结构数组元素方式引用结构成员 */
printf ("%d/n", array[i].x);
printf ("%d/n", *array[i].y);
printf ("%d/n", ++array[i].x);
printf ("%d/n", ++ *array[i].y);
printf ("%d/n", array[++i].x);
printf ("%d/n", *++array[i].y);
printf ("%d/n", (*array[i].y)++);
printf ("%d/n", *(array[i].y++));
printf ("%d/n", *array[i].y++);
printf ("%d/n", * array[i].y);
}
程序中说明了一个结构数组array,结构数组array的每个元素有两个成员,其一为整型x,其二为指向整型的指针y。结构数组array的初始化后的状态如图11-4所示。

 

程序各个printf语句中对数组操作的含义如下:
s_var.x /* 取s_var的成员x的值,输出 100 */
*s_var.y /* 取s_var的成员指针y所指的内容,输出 10 */
array[i].x /* 取array[i]的x的值,输出 100 */
*array[i].y /* 取array[i]的指针y所指的内容,输出10 */
++array[i].x /* 取array[i]的x的值,x加1后输出 101 */
++*array[i].y /* 取array[i]的指针y所指的内容,y的内容加1后输出11 */
array[++i].x /* i先加1后取array[i]的x的值,输出 200 */
*++array[i].y /* 将array[i]的指针y先加1后再取y所指的内容,输出30 */
(*array[i].y)++ /* 取array[i]的指针y的内容,输出30后,y的内容再加1 */
*(array[i].y++) /* 取array[i]的指针y的内容,输出31后,指针y再加1 */
*array[i].y++ /* 同上,由于运算的结合性隐含了括号,输出 40 */
*array[i].y /* 输出 50 */
程序运行结束时,结构数组array的状态如图11-5所示。

例11-5:简单的密码加密程序。其加密过程是先定义一张字母加密对照表。
将需要加密的一行文字输入加密程序,程序根据加密表中的对应关系,可以很简单地将输入的文字加密输出,对于表中未出现的字符则不加密。
可以定义一个结构来表示加密表。结构table中的成员input存入输入的字符,成员output保存加密后对应的字符。

#include "stdio.h"
struct table /* 定义结构table */
{ char input; /* 成员input存输入的字符 */
char output; /* 成员output存输出的字符
};
struct table translate[ ]= /* 说明外部的结构数组translate并初始化 */
{ 'a', 'd', 'b', 'w', 'c', 'k', 'd', '; ', 'e', 'i',
'i', 'a', 'k', 'b', ';', 'c', 'w', 'e' }; /* 建立加密对照表 */
main( )
{ char ch;
int str_long, i;
str_long = sizeof(translate)/sizeof(struct table); /* 计算数组元素个数 */
while ( (ch=getchar( )) != '/n')
{ for ( i=0; translate[i].input!=ch && i<str_long; i++) ;
if (i<str_long)
putchar(translate[i].output); /* 对表中的字符加密输出 */
else putchar (ch); /* 对其它字符原样输出 */
}
}


  语句"struct table translate[]={...}"有三个作用,一是说明了一个外部的结构数组translate;二是表示数组的大小由后面给出的初始化数据决定,三是对结构数组进行初始化。在程序中给出了数组初始化数据,所以结构数组translate有9个元素。
程序中语句"str_long = sizeof(translate)/sizeof(struct table);"是用sizeof运算计算结构数组translate中元素的数目。sizeof(translate)求出数组translate所占用的字节总数,sizeof(struct table)求出数组中每个元素所占用的字节总数。
运行程序时,从键盘逐个读取输入的字符存入变量ch中,将ch的值与结构translate中的input比较,如果是要加密的字符,则输入加密后的字符output,否则ch原样输出。


例11-6:有N个小孩围成一圈并依次编号,教师指定从第M个小孩开始报数,当报到第S个小孩时,即令其出列,然后再从下一个孩子起从1开始继续报数,数到第s个小孩又令其出列,这样直到所有的孩子都依次出列。求小孩出列的顺序。这就是约瑟夫问题。
由于问题中的小孩围成一个圈,因而启发我们用一个环形链来表示。我们用结构数组构成一个环形链。结构名为child。数组名为link。nextp的含义是排在当前这个孩子后面的下一个孩子的序号。由nextp可构成一个环型链,no是孩子的序号。这样就可以从第M个小孩开始沿着nextp连成的闭合链不断计数S次,输出对应的no表示让他出列。

#include "stdio.h"
struct child /* 定义结构child */
{ int nextp; /* 排在后面下一个位置上的孩子的序号 */
int no; /* 孩子的序号 */
} link [100]; /* 说明结构数组link */
main( )
{ int i, n, s, y, k, m, count=0; /* count为输出计数器 */
printf ("/nTell me how many children are there ?");
scanf ("%3d", &n);
printf ("/nFrom which to count ?");
scanf ("%3d", &m);
printf ("/nHow many shall I count ?");
scanf ("%3d", &s);
for ( i=1; i<=n; i++ ) /* 根据孩子总数n建立一个环 */
{ if ( i==n )
link[i].nextp=1; /* 若是最后一个,则他的下一个是第一个人 */
else link[i].nextp=i+1; /* 否则,第i个人的下一个为第i+1个人 */
link[i].no=i; /* 为第i个孩子建立序号 */
}
printf ("/nStand out :/n");
if ( m>=i ) k=n;
else k=m-1; /* k定位在应开始计数的孩子的前一个人上 */
while (count != n)
{ for (i=0; i!=s; ) /* s个孩子报数 */
{ k = link[k].nextp; /* 取下一个孩子 */
if ( link[k].no != 0 ) ++i; /* 若序号不为0表示没出列,则计数 */
}
printf ("%7d", link[k].no); /* 输出出列的孩子序号 */
link[k].no = 0; /* 将出列孩子的序号清为0 */
if ( ++count % 10 == 0) printf ("/n");
}
}


程序中首先输入小孩总数n,报数起始位置m和需要出列的计数步长s,然后由总数n初始化结构数组link。为了程序中处理的方便,link数组从下标1开始使用,下标为0的元素不用,由于数组说明长度为100,所以输入的n值不能大于99。
变量k记录下一次需要计数的数组下标,初始化时,变量k的值在要开始报数的小孩的前一个位置。在while循环中,使用count作为出列小孩计数器,对于已出列的小孩,将no清为0,变量i是报数计数器,当link[k].no不为0时,才操作++i。语句"k=link[k].nextp;"的含义是将下一个孩子所在数组中的下标位置送入变量k中。
运行程序,输入n=35、m=5、s=3,可得到如下结果:
7 10 13 16 19 22 25 28 31 34
2 5 9 14 18 23 27 32 1 6
12 20 26 33 4 15 24 35 11 29
8 30 21 3 17
本例完全可以用一维数组实现,请读者自己编写程序。

                                          

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值