第八章 结构体与共用体
1.选择题
(1)若已经定义“struct stu{int a,b; }student;”,则下列输入语句中正确的是(D)。
A.scanf("%d", &a);
B.scanf("%d",&student);
C.scanf("%d", &stu.a);
D.scanf("%d",&student.a);
A中,应通过结构体使用;B中,输出为结构体的地址;C中,stu为结构体类型名;D正确。
(2)已知学生记录描述为:
struct student
{ int no;
char name[20];
char sex;
struct
{ int year;
int month;
int day;
}birth;
};
struct student s;
设变量s中的“生日”是“1984年11月11日”,下列对“生日”的正确赋值方式是(D)。设变量s中的“生日”是“1984年11月11日”,下列对“生日”的正确赋值方式是(D)。
A.year=1984;
month=11;
day=11;
B.birth.year=1984;
birth.month=11;
birth.day=11;
C.s.year=1984;
s.month=11;
s.day=11;
D.s.birth.year=1984;
s.birth.month=11;
s.birth.day=11;
通过s来访问其成员结构体birth,继而赋值各个成员。
(3)当定义一个结构体变量时系统分配给它的内存是(A)。
A.各成员所需内存的总和
B.结构中第一个成员所需内存量
C.成员中占内存量最大者所需的容量
D.结构体中最后一个成员所需内存量
A正确。C为共用体。
(4)设有以下说明语句:
struct stu
{ int a;
float b;
} stutype;
则以下叙述中不正确的是(C)。
A.struct是结构体类型的关键字
B.struct stu是用户定义的结构体类型
C.stutype是用户定义的结构体类型名
D.a和b都是结构体成员名
C中,stutype为结构体变量名,C错误。
(5)以下对结构体变量stul中成员age的非法引用是(B)。
struct student
{ int age;
int num;
} stul, *p;
p=&stul;
A.stul.age
B.student.age
C.p->age
D.(*p).age
B中,不可用结构体类型名来实现引用,B错误。
(6)以下程序的运行结果是(D)。
int main(void)
{
struct date
{
int year, month, day;
} today;
printf("%d\n",sizeof(struct date) );
}
A.6
B.8
C.10
D.12
int一般为4字节,该结构体有三个int成员,故结构体所占内存大小为12,D正确。
(7)根据下面的定义,能打印出字母M的语句是(C)。
struct person
{ char name[9];
int age;
};
struct person class1[10]={"John",17,"Paul",19,"Mary",18,"adam",16};
A.printf("%c\n",class1[3].name[0]);
B.printf("%c\n",class1[3].name[1]);
C.printf("%c\n",class1[2].name[0]);
D.printf("%c\n",class1[2].name);
C正确,'M'即class1[2].name[0]处。
(8)若有以下程序段:
struct dent
{
int n;
int *m;
};
int a=1,b=2,c=3;
struct dent s[3]={{101,&a},{102,&b},{103,&c}};
int main(void)
{ struct dent *p;
p=s;
…
}
则以下表达式的值为2的是(D)。
A.(p++)->m
B.*(p++)->m
C.(*p).m
D.*(++p)->m
*p指向结构体s[0],b=2,s[1].m储存b的地址,需通过s[1]来访问。D正确。
(9)设有以下语句:
struct st
{
int n;
struct st *next;
};
struct st a[3]={5, &a[1], 7, &a[2], 9, '\0' }, *p;
p=&a[0];
则以下输出值为6的是(D)。
A.printf("%d\n",p++->n);
B.printf("%d\n",p->n++);
C.printf("%d\n",(*p).n++);
D.printf("%d\n",++p->n);
A中,->优先级大于++,且++先参与运算,结果为5;B中,先参与运算后++,值为5;C同B,值为5;D正确。
(10)若有以下说明和语句:
struct student
{ int age;
int num;
};
struct student stu[3]={{1001,20},{1002,19},{1003,21}};
struct student *p;
p=stu;
则下面表达式中的值为1002的是(B)。
A.(p++)->num
B.(++p)->age
C.(*p).num
D.(*p++).age
A选项值为1001;B选项值为1002;C选项值为20;D选项值为1001。
(11)当说明一个共用体变量时系统分配给它的内存是(C)。
A.各成员所需内存量的总和
B.第一个成员所需内存量
C.成员中占内存量最大者所需内存量
D.最后一个成员所需内存量
A选项为结构体内存。
(12)设有如下程序段,则vu.a的值为(D)。
union u
{ int a;
int b;
float c;
} vu;
vu.a=1; vu.b=2; vu.c=3;
A.1
B.2
C.3
D.A、B、C都不是
共用体变量只能存放它所包含的一个成员,代码中即vu.c = 3,vu.a值不确定。
(13)以下程序的运行结果是(B)。
#include<stdio.h>
int main(void)
{
union { long a; int b; char c; } m;
printf("%d\n", sizeof(m));
}
A.2
B.4
C.6
D.8
共用体内存大小为成员单独所用内存空间最大值。long大小为4。
(14)若已经定义“typedef struct stu{ int a, b; }student;”,则下列叙述中正确的是(C)。
A.stu是结构体变量
B.student是结构体变量
C.student是结构体类型名
D.a和b是结构体型变量
使用typedef给stu取新类型名,stu、student都是结构体类型名,a、b是结构体成员名。
(15)若有结构类型定义“typedef struct test{ int x, y[2];}TEST;”,则以下声明中正确的是(A)。
A.struct test x;
B.structx;
C.test x;
D.struct TEST x;
struct test x;和TEST x;都是正确的声明,A正确。
2.填空题
(1)设有以下说明语句:
struct stu
{ int a;
float b;
}stutype;
则struct是定义结构体类型的关键字、struct stu是用户定义的结构体类型名 、stutype是用户定义的结构体类型变量、a和b是结构体成员名。
(2)“.”称为 成员 运算符,“->”称为 指向 运算符。
"."应用于实际的对象。"->"与一个指向对象的指针一起使用。
(3)以下程序用来输出结构体变量stu所占存储单元的字节数。
struct student
{
int num;
char name[20];
float score;
}stu;
int main(void)
{ printf("stu size:%d\n",sizeof( stu ));
}
表示结构体student的值均可。
(4)对下列结构体类型变量m中的成员x的三种引用方式为:
m.x 、 (*p).x 和 p->x 。
struct student
{ int x ;
float y ;
} m,*p=&m;
(5)函数findbook的功能是:在有n个元素的数组s中查找名为a的书,若找到,函数返回数组下标,否则,函数返回-1,请填空。
struct data
{ int id;
char name[20];
double price;
} book[100];
int findbook(struct data s[], int n, char a[])
{ int i;
for(i=0;i<n;i++)
if( strcmp(s[i].name, a)== 0 ) return i;
return -1 ;
}
比较数组元素s[i]和a是否一致,一致即找到,返回下标。找不到则返回-1。
(6)若有以下定义:
struct person
{
char name[9];
int age;
};
struct person c[10] = { {"John",17 },{"Paul",19},{"Mary",18 },{"Adam",16 } };
则语句“printf("%s",c[3].name);”的输出是 Adam 。
c[3]即{"Adam",16},其name成员即"Adam"。
(7)假定建立了如下图所示的链表结构,指针p、q分别指向相邻的两个结点,则将r所指结点插入p、q所指结点之间的C语句是 r->next=p->next; 和 p->next=r; 。
结点r先存入结点q的地址,结点p再存入结点r地址,以保持链表连续。
(8)若有以下程序段,则语句“printf("%d\n",sizeof(test));”的输出是 32 。
typedef struct
{ long a[2];
int b[4];
char c[8];
}ABC;
ABC test;
test为结构体ABC变量,其大小即所有成员所用内存空间和,8+16+8。
(9)下列程序的运行结果为: 21 。
#include<stdio.h>
int main(void)
{
struct cmplx
{
int x;
int y;
} cnum[2] = { 1,3,2,7 };
printf("%d\n", cnum[0].y / cnum[0].x * cnum[1].y);
return 0;
}
cnum[2]为结构体cmplx的数组,cnum[0] 为{1, 3},cnum[1] 为{2, 7},3/1*7,值为21。
(10)下列程序运行时若输入:3 101 wang 102 huang 103 liu,则其运行结果为:
102,huang
103,liu
101,wang 。
#include<stdio.h>
#include<string.h>
struct worker
{
int num;
char name[20];
};
int main(void)
{
struct worker per[10], t;
int n, i, j;
scanf("%d", &n);
for (i = 0; i < n; i++)
scanf("%d%s", &per[i].num, per[i].name);
for (i = 0; i < n - 1; i++)
for (j = 0; j < n - 1 - i; j++)
if (strcmp(per[j].name, per[j + 1].name) > 0)
{
t = per[j];
per[j] = per[j + 1];
per[j + 1] = t;
}
for (i = 0; i < n; i++)
printf("%d,%s\n", per[i].num, per[i].name);
return 0;
}
代码意在先读取要输入的结构体的数量,再读取对结构体成员的赋值。对结构体数组per[10]按成员name的大小利用冒泡排序思想进行顺序排序,再换行输出数组。"huang"<"liu"<"wang"。
3.编程题
(1)用结构体变量表示平面上的一个点(横坐标和纵坐标),输入两个点,求两点之间的距离。
#include <stdio.h>
#include <math.h>
struct point
{//记录点坐标(x, y)
float x, y;
};
int main(void)
{
struct point a, b;
printf("输入点a:");
scanf("%f,%f", &a.x, &a.y);
printf("输入点b:");
scanf("%f,%f", &b.x, &b.y);
printf("两点距离:%f", sqrt(pow((a.x-b.x), 2) + pow((a.y - b.y), 2)));
// pow() 返回 x 的 y 次幂。
}
(2)已知一个无符号的整数占用了4个字节的内存空间,现欲从低位存储地址开始,将其每个字节作为独立的一个ASCII码字符输出,试用共用体实现。例如:十六进制数0x44434241,则输出:ABCD
#include <stdio.h>
union MyUnion
{
unsigned n;
char c[4];
};
int main(void)
{
union MyUnion u;
scanf("%x", &u.n);
printf("%c%c%c%c%c", u.c[0], u.c[1], u.c[2], u.c[3]);//以字节为单位,将值输出到数组
}
(3)用结构体变量表示复数(实部和虚部),输入两个复数,求两复数的和与积。注意:若两个复数相加或乘积时虚部为0时,只输出实部。
设复数定义为:A=a+bi
则复数的加法定义为:
(a+bi)+(c+di)=(a+b)+(b+d)i
复数的乘法定义为:
(a+bi)*(c+di)=(ac-bd)+(ad+bc)i
#include <stdio.h>
typedef struct
{
int r;//实部
int i;//虚部
} complex;
void i(int image)
{//虚部为0时不输出0i
if (image != 0)
{
printf("%di", image);
}
}
void f(int real, int image)
{//根据real是否为0划分
if (real == 0)
{
if (image == 0)
{
printf("0");//实部虚部都为0则输出"0"
}
else
i(image);
}
else
{
printf("%d", real);
if (image > 0)
printf("+");//只在虚部大于0时加'+'
i(image);
}
}
int main(void)
{
complex c1, c2;
int real, image;
printf("输入第一个数的实部和虚部:");
scanf_s("%d %d", &c1.r, &c1.i);
printf("输入第二个数的实部和虚部:");
scanf_s("%d %d", &c2.r, &c2.i);//读取两个复数
real = c1.r + c2.r;
image = c1.i + c2.i;
//计算复数和
printf("复数和:");
f(real, image);
real = c1.r * c2.r - c1.i * c2.i;
image = c1.r * c2.i + c2.r * c1.i;
printf("\n");
//计算复数积
printf("复数积:");
f(real, image);
return 0;
}
如有错误不足之处,恳请批评指正。
题目来源:C程序设计教程与实验(第3版) 吉顺如主编
答案参照微信公众号:程序设计及信息技术学习平台