整数在计算机中存储和运算通常采用的格式是补码。
偏移码(移码)通过将补码的符号位取反得到相应的移码。正数的原码、反码、补码均相同;负数的反码是原码除符号位外各位取反,负数的补码是反码的末位+1。
ASCII码值大小关系:数字<大写字母<小写字母
A | 65 |
a | 97 |
机器周期:考虑到所有的器件中存储器的速度很慢,CPU访问一次内存所花的时间较长,因此,通常用内存中读取一个指令字的最短时间来规定CPU周期,也成为机器周期。
总线分为:
总线的性能指标——总线宽度:又称总线位宽,它是总线上同时能够传输的数据位数,通常是指数据总线的根数。总线带宽:总线的数据传输率,即单位时间内总线上可传输数据的位数,通常用每秒传送信息的字节数来衡量。
1.机器周期的同步标准是( )
(A)CPU执行指令所占用的时间 |
(B)CPU访问存储器一次所需要的时间 |
(C)CPU分析指令所需要的时间 |
(D)CPU访问寄存器一次所需要的时间 |
【答案】(B)
2.CPU芯片内部连接各元件的总线是( )
(A)系统总线 |
(B)外围总线 | (C)外部总线 | (D)内部总线 |
【答案】(D)
1.下列叙述中正确的是( )
(A)机器数补码的符号位取反即是偏移码 |
(B)机器数原码除符号位外各位取反即是反码 |
(C)机器数反码的最后(即最右边)一位上加1即是补码 |
(D)机器数原码、反码、补码均相同 |
【答案】(A)
2.计算机内部表示指令和数据应采用( )
(A)ASCII码 |
(B)二级制与八进制 |
(C)二进制、八进制、与十六进制 |
(D)二进制 |
【解析】计算机内部均使用二进制表示各种信息,但计算机在与外部沟通中会采用人们比较熟悉和方便阅读的形式。
【答案】(D)
早期计算机在输入和输出之间的时间段内是被单道程序所独占的,并且I/O设备的执行速度远远小于CPU,CPU大部分时间是闲置的。
多道批处理系统——每次往内存中输入多道程序,并引入中断技术,控制程序的并发执行,这个过程由操作系统负责管理这些程序的运行。缺点:不提供人机交互。从程序输入到输出,用户无法对计算机进行操作。
分时操作系统——计算机以时间片为单位,轮流为各个用户/作业服务。缺点:每个用户/作业都是同等级的,不能优先处理紧急任务。
实时操作系统——计算机系统接收到外部信号后及时处理,并且要在严格的时限内处理完事件。实时操作系统的主要特点就是及时性和可靠性。
1. 过程控制系统属于( )
(A)批处理系统 |
(B)实时系统 | (C)分时系统 | (D)多道程序系统系统 |
【答案】(B)
2.允许多个联机用户同时使用一台计算机系统进行计算的操作系统属于( )
(A)布式操作系统 |
(B)实时操作系统 | (C)批处理操作系统 | (D)分时操作系统 |
【答案】(D)
进程调度是按一定策略动态地把CPU分配给处于就绪队列中的某一进程并使之执行的过程。
1.当一个进程在运行过程中释放了系统资源后要调用( )
(A)撤销进程原语 |
(B)唤醒进程原语 | (C)阻塞进程原语 | (D)创建进程原语 |
【解析】
【答案】(B)
2.下列叙述中正确的是( )。
(A)进程调度也负责对内存进行分配 |
(B)进程调度负责对计算机系统中的所有系统资源进行分配 |
(C)进程调度仅负责对CPU进行分配 |
(D)进程调度也负责对外存进行分配 |
指令由操作码和地址码组成,地址码既可以是操作数也可以是操作数的地址,在寻找操作数时就面临不同的寻址情况,而操作码中既含有操作方式也含有寻址特征。
立即寻址:指令中地址码直接给出操作数,不需要去寄存器、主存或I/O设备中提取。
直接寻址:指令地址码给出操作数所在主存存储单元的地址。
隐含寻址:操作数的地址隐含在指令的操作码或者某个寄存器中。
间接寻址:地址码给出的是操作数的地址的地址。
静态地址重定位:在程序执行之前将重定位后的地址装入程序,程序必须占用连续的内存空间,且不再移动。
动态地址重定位:在程序执行期间进行,不要求程序装入固定的内存空间,在内存中允许程序再次移动位置,且可以部分地装入程序运行。
虚拟存储器管理
连续存储管理和分页、分段式存储管理技术必须为作业分配足够的内存空间,装入其全部信息,否则作业将无法运行。把作业的全部信息装入内存后,实际上并非同时使用这些信息,有些部分运行一次,有些部分暂时不用或某种条件下才使用。让作业全部信息驻留于内存是对内存资源的极大浪费,会降低内存利用率。虚拟内存器管理技术的基本思路是把内存扩大到大容量外存上,把外存空间当作内存的一部分,作业运行过程中只让当前用到的信息进入内存,其他当前未用的信息留在外存。虚拟存储器管理主要采用请求页式存储管理、请求段式存储管理及请求段页式存储管理技术实现。
1.下列叙述中错误的是( )
(A)静态地址重定位要求程序必须占用连续固定的内存空间 |
(B)动态地址重定位要求程序必须占用连续固定的内存空间 |
(C)动态地址重定位是在程序执行期间进行的 |
(D)静态地址重定位是在程序执行之前进行的 |
【答案】(B)
2.理论上计算机虚拟内存最大容量取决于( )
(A)磁盘空间的大小 |
(B)物理内存的大小 |
(C)计算机地址位数 |
(D)数据存放的实际地址 |
【解析】虚拟内存实际就是从外存的存储空间划出部分,作为内存使用,根据局部性原理将一些暂时用不上的数据放入这部分区域,所以计算机最大虚拟内存容量与CPU寻址位数有关。
【答案】(C)
3.指令中的地址码部分给出了存放操作数地址的地址的寻址方式是( )
(A)立即寻址 |
(B)直接寻址 | (C)隐含寻址 | (D)间接寻址 |
【答案】(D)
文件是指一组带标识(文件名)的具有完整逻辑意义的相关信息的集合。文件属性包括文件类型、文件名称、文件长度、文件的物理地址、文件的建立时间等。一个计算机系统中有成千上万个文件,为了便于对文件进行存取和管理,计算机系统建立文件的索引,即文件名和文件物理位置之间的映射关系,这种文件的索引称为文件目录。
1.下列不属于文件属性的是( )
(A)文件类型 |
(B)文件名称 | (C)文件内容 | (D)文件长度 |
【答案】(C)
2.在操作系统中,将文件名转换为文件存储地址的结构是( )
(A)路径名 |
(B)PCB表 | (C)文件目录 | (D)文件名 |
【答案】 (C)
I/O控制方式
程序直接控制方式(轮询):
中断驱动方式:在大量数据输入输出情况下,可能会产生大量中断,但CPU和I/O设备可并行工作
DMA(Direct Memory Access)方式:数据流向不经过CPU,数据传送单位为块(数据量变大了),每次读写只能是连续的数据块,存入内存也是连续,尽管数据流向不经过CPU,但这个过程会由DMA发中断给CPU,由CPU干预
通道控制方式 :通道是专门负责I/O的处理机,中央处理器只要发送指令给通道处理机读写操作的相关信息,通道完成整个操作后,通过中断反馈给中央处理器。
1.I/O方式中使计算机系统并行工作程度最高的是( )
(A)DMA |
(B)程序查询 | (C)程序中断 | (D)通道 |
【解析】
【答案】(D)
数据库管理系统(Database Management System,DBMS)是数据库系统的核心,其主要功能包括:①数据模式定义;②数据存取的物理构建;③数据操纵;④数据完整性、安全性的定义与检查;⑤数据库的并发控制与故障恢复;⑥数据的服务。
为了完成以上6个功能,DBMS提供了相应的数据语言:数据定义语言,数据的模式定义与数据的物理存取构建;数据操纵语言,数据的操作,包括查询与增、删、改等操作;数据控制语言,数据完整性、安全性的定义与检查以及并发控制、故障恢复等功能。
1.在数据管理技术发展的3个阶段中,数据共享最好的是( )
(A)人工管理阶段 |
(B)文件系统阶段 | (C)数据库系统阶段 | (D)3个阶段相同 |
【答案】(C)
2.关于数据库管理阶段的特点,下列说法中错误的是( )
(A)数据独立性差 |
(B)数据的共享性高,冗余度低,易扩展 |
(C)数据真正实现了结构化 |
(D)数据由DBMS统一管理和控制 |
【解析】数据库管理阶段的数据库系统的基本特点:数据集成性、数据的共享性高,冗余性低、数据独立性高、数据统一管理与控制。
【答案】(A)
3.在数据库中,产生数据不一致的根本原因是( )
(A)数据冗余 |
(B)没有严格保护数据 |
(C)未对数据进行完整性控制 |
(D)数据存储量太大 |
【解析】由于数据冗余,有时修改数据时,一部分数据修改,而另一部分没有修改,造成同一种数据有多个值,产生数据不一致。
【答案】(A)
5.数据库系统中支持安全性定义和检查的语言是( )
(A)数据控制语言 |
(B)数据定义语言 | (C)数据操纵语言 | (D)数据管理语言 |
【答案】(A)
数据模型的三要素:数据结构、数据操作、数据约束(完整性约束)。
在关系模型中有三类完整性约束:实体完整性、参照完整性和用户定义完整性。实体完整性和参照完整性是关系模型必须满足的完整性约束条件,被称作是关系的两个不变性,应该由关系系统自动支持。实体完整性要求主码唯一且不能为空,主属性不能取空值。
码(键):由一个或多个属性组成。
主键(主码):若关系中有多个候选码,则选定其中一个作为标识元组供用户使用,并称其为主键。
外键(外码):表M中的某属性集是表N的候选键或者主键,则称该属性集为表M的外键或外码。
1.下列选项中不属于数据模型三要素的是( )
(A)数据结构 |
(B)数据操作 | (C)数据删除 | (D)数据约束 |
【答案】(C)
2.关系的实体完整性要求关系中不能为空的属性是( )
(A)主键属性 |
(B)外键属性 | (C)全部属性 | (D)候选键属性 |
【答案】(A)
3.在数据库中存储的是( )
(A)数据模型 |
(B)操作信息 |
(C)数据操作 |
(D)数据以及数据之间的联系 |
【答案】(D)
4.定义学生选修课程的关系模式如下:SC(S#,Sn,C#,Cn,T#,G,Cr)(其属性分别为学号、姓名、课程号、课程名、授课老师号、成绩、学分)并且一门课程可由多个老师教授,则该关系的键是( )
(A)S#,T# |
(B)S#,C# | (C)S# | (D)C# |
【解析】键就是标识元组的属性
【答案】(B)
5.在关系模式A(S, SN, D)和B(D, CN, NM)中,关系A的主键是S,关系B的主键是D,则属性D在关系A中称为( )。
(A)主键 |
(B)外键 | (C)候选键 | (D)超键 |
【答案】(B)
数据库系统在其内部分为三级模式——外模式、概念模式(模式)和内模式。概念模式是将现实世界的逻辑关系抽象出来进行描述,所以它概括了描述对象的全部数据逻辑。而不同的外模式(用户模式)只使用了概念模式中的部分信息,可以看成是局部的。
1.在关系数据库中,描述全局数据逻辑结构的是( )。
(A)内模式 |
(B)用户模式 | (C)概念模式 | (D)物理模式 |
【答案】(C)
数据库设计过程包括需求分析(产生需求说明书)、概念结构设计(概念模型设计)、逻辑结构分析(从E-R图向关系模式转换)、数据库物理设计、数据库实施、数据库运行和维护阶段,大体上分为3个阶段:需求分析、概念设计、逻辑设计和物理设计。其设计目的是:构造最优的数据模型,建立数据库及其应用系统的过程。
整个设计过程细分下来又包括:需求分析(产生需求说明书)、概念结构设计(概念模型设计)、逻辑结构分析(从E-R图向关系模式转换)、数据物理设计、数据库实施、数据库运行和维护阶段。
概念模型设计是在信息世界进行的,而信息世界是抽象现实世界客观存在事物的逻辑得到的模型,并将世界的需求分析结果采用概念模型的方式进行描述,与计算机系统无关,概念模型有E-R模型(实体-联系)、UML模型、面向对象模型。
逻辑模型设计需要将概念模型转换成适应数据库系统处理的形式,其逻辑数据模型(数据模型)有层次模型、网状模型、关系模式、和面向对象模型。其中,在关系模式设计完成后,还要进行规范化,目的是使关系结构更加合理,消除存储异常,使数据冗余尽量小,便于插入、删除和更新等操作。
概念模型设计与计算机系统无关,概念模型有E-R模型(实体-联系)、UML模型。
外模式(子模式、用户模式):数据库用户(包括应用程序员和最终用户)使用的局部数据的逻辑结构和特征的描述。数据库用户的数据视图,是与某一应用有关的数据的逻辑表示。
模式(概念模式):是数据库系统中全局数据逻辑结构的描述,全体用户的公共视图。
内模式(存储模式、物理模式):是数据物理结构和存储方式的描述,是数据在数据库内部的表示方式。
两级映像保证了数据的独立性:外部应用程序和数据之间的相互独立性,数据的独立性又分为逻辑独立性和物理独立性,逻辑独立性是指应用程序和数据库的逻辑结构是相互独立的。数据的逻辑模式改变了,应用程序也可以不变,由外模式/模式映像的改变保证了数据的逻辑独立性。物理独立性是指用户的应用程序与存储在磁盘上的数据库中的数据是相互独立的。当数据的物理存储改变了,应用程序不用改变,由逻辑模式/内模式映像保证物理独立性。
1.数据库设计过程不包括( )。
(A)概念设计 |
(B)逻辑设计 | (C)物理设计 | (D)算法设计 |
【答案】(D)
2.数据库概念设计阶段得到的结果是( )。
(A)关系模型 |
(B)数据字典 | (C)E-R模型 | (D)物理模型 |
【答案】(C)
4.在数据库设计中,将E-R图转换成关系数据模型的过程属于( )。
(A)需求分析阶段 |
(B)概念设计阶段 | (C)逻辑设计阶段 | (D)物理设计阶段 |
【答案】(C)
联系类型的转换:不同的情况不同处理
(1)实体间联系是1:1
(2)实体间联系是1:n
(3)实体间联系是m:n,则将联系类型也转换成关系模式,其属性为两端实体类型的键加上联系类型的属性,而键为两端实体键的组合。
1.E-R图中用来表示实体的图形是( )。
(A)菱形 |
(B)三角形 | (C)矩形 | (D)椭圆形 |
【解析】E-R图中,用矩形表示实体集,椭圆表示属性,菱形表示联系。
【答案】(C)
2.图书馆管理系统中实体图书和实体借阅人之间的联系是( )
(A)N:1 |
(B)M:N | (C)1:1 | (D)1:N |
【答案】(B)
3.学校的每个社团都有一名团长,且一个同学可同时担任多个社团的团长,则实体团长和实体社团间的联系是( )
(A)一对一 |
(B)一对多 | (C)多对一 | (D)多对多 |
【答案】(B)
4.商品销售的售货单和商品之间的联系是( )
(A)多对多 |
(B)一对多 | (C)多对一 | (D)一对一 |
【解析】一张售货单可以有多种商品,一种商品可以出现在多张售货单上。
【答案】(A)
5.优化数据库系统查询性能的索引设计属于数据库设计的( )。
(A)需求分析 |
(B)概念设计 | (C)逻辑设计 | (D)物理设计 |
【解析】
【答案】(D)
6.逻辑模型是面向数据库系统的模型,下面属于逻辑模型的是( )
(A)关系模型 |
(B)谓词模型 | (C)物理模型 | (D)实体-联系模型 |
【解析】成熟并大量使用的逻辑数据模型有层次模型、网状模型、关系模型和面向对象模型。
【答案】(A)
6.将实体-联系模型转换为关系模型时,实体之间多对多联系在关系模式中的实现方式是( )。
(A)建立新的关系 |
(B)增立新的关系 | (C)增加新的关键字 | (D)建立新的实体 |
【答案】(A)
7.将数据库的结构划分为多个层次,是为了提高数据的逻辑独立性和( )
(A)安全性 |
(B)物理独立性 | (C)操作独立性 | (D)管理规范性 |
【答案】(B)
规范化
一个关系的分量是不可分的数据项,它就是规范化关系,但也只是最基本的规范化。规范化程度有6个级别,即6范式。规范化程度过低的关系可能会存在插入异常、删除异常、修改复杂、数据冗余等问题。
1个低一级范式的关系模式,通过模式分解可以转换为若干个高一级范式的关系模式集合,这个过程就称为关系模式的规范化。关系模式的规范化是通过对关系模式的分解实现的,把低一级关系模式分解为若干个高一级关系模式的方法并不唯一,只有保证分解后的关系模式通过自然连接后与原关系模式等价才有意义,这种分解称为无损连接。但无损连接,可能存在破坏函数依赖(包括完全函数依赖、部分函数依赖和传递函数依赖)的问题。根据模式分解理论算法,若要求分解既能无损又能保持函数依赖,则模式分解一定能够达到3NF。
如果一个关系模式的所有属性都是不可分的基本数据项,则该关系模式满足第一范式。
若关系模式满足1NF的条件下,每一个非主属性都完全函数依赖于key(码、键、主码),则该关系模式满足第二范式。
关系模式满足2NF的条件下,不存在非主属性对码的传递函数依赖,则该关系模式满足第三范式。
1.关系数据库规范化的目的是为了解决关系数据库中的( )。
(A)数据操作复杂的问题 |
(B)查询速度低的问题 |
(C)插入、删除异常及数据冗余问题 |
(D)数据安全性和完整性保障的问题 |
【答案】(C)
2.如果定义班级关系如下:班级(班级号,总人数,所属学院,班级学生)则使它不能满足第一范式的属性是( )。
(A)所属学院 |
(B)班级号 | (C)总人数 | (D)班级学生 |
【解析】属性“班级学生”又可以分为“学生学号”和“学生姓名”等。
【答案】(D)
3.设有课程关系模式如下:
R(C#,Cn,T,Ta)(其中C#为课程号,Cn为课程名,T为教师名,Ta为教师地址)
并且假定不同课程号可以有相同课程名,每个课程号下只有一位任课教师,但每位教师可以有多门课程。该关系模式可进一步规范化为( )。
(A)R1(C#,Cn),R2(T,Ta) |
(B)R1(C#,Cn,Ta),R2(T,Ta) |
(C)R1(C#,T),R2(T,Ta) |
(D)R1(C#,Cn,T)R2(T,Ta) |
【解析】分解后要通过自然连接等价原关系模式,那么分解出来的关系模式,一定要有公共属性,排除(A)。(C)中缺乏了Cn,也排除。剩余两个选项中,C#,Cn→T,决定不了Ta,(B)排除。
【答案】(D)
4.设有课程关系模式如下:R(C#,Cn,T,Ta)(其中C#课程号,Cn为课程名,T为教师名,Ta为教师地址)并且假定不同课程号可以有相同的课程名,每门课程只有一位任课教师,但每位教师可以有多门课程。关系R范式最高达到( )
(A)1NF |
(B)2NF | (C)3NF | (D)BCNF |
【解析】关系模式R的主属性为C#,但存在C#→T,T→Ta,存在非主属性Ta对主属性C#的传递依赖,所以关系模式R范式最高是2NF
【答案】(B)
5.定义学生选修课的关系模式如下:SC(S#,Sn,C#,Cn,G,Cr)(其属性分别为学号、姓名、课程号、成绩、学分)
该关系可进一步规范化为( )
(A)S(S#,Sn,C#,Cn,Cr), SC(S#,C#,G) |
(B)S(S#,Sn), C(C#,Cn,Cr), SC(S#,C#,G) |
(C)C(C#,Cn,Cr), SC(S#,Sn,C#,G) |
(D)S(S#,Sn), C(C#,Cn,), SC(S#,C#,Cr,G) |
【解析】SC的主码为(S#,C#),S#→Sn,C#→Cn,C#→Cr,(S#,C#)→G。存在非主属性对主属性的部分依赖,想要消除这种部分依赖,就要将其转变为单独的一个关系模式,使其部分依赖成为完全依赖,于是就有三个关系模式,S#→Sn、C#→(Cn,Cr)、(S#,C#)→G。
【答案】(B)
6.学生选修课程的关系模式为SC(S#,Sn,Sd,Sa,C#,G)(其属性分别为学号、姓名、所在系、年龄、课程号和成绩);
C(C#,Cn,P#)(其属性分别为课程号、课程名、先选课)。
关系模式中包含对主属性部分依赖的是( )。
(A)(S#,C#)→G |
(B)C#→Cn | (C)C#→P# | (D)S#→Sd |
【解析】在关系模式SC中,主属性是(S#,C#),有S#→Sd,属于对主属性的部分依赖。
【答案】(D)
7.定义学生、教师和课程的关系模式S(S#,Sn,Sd,Dc,Sa)(其属性分别为学号、姓名、所在系、所在系的系主任、年龄);C(C#,Cn,P#)(其属性分别为课程号、课程名、先修课);SC(S#,C#,G)(其属性分别为学号、课程号和成绩)。包含对非主属性部分依赖的关系是( )。
(A)C(C#,Cn,P#)和SC(S#,C#,G) |
(B)S(S#,Cn,Sd,Dc,Sa) |
(C)C(C#,Cn,P#) |
(D)SC(S#,C#,G) |
【答案】(B)
8.定义学生选修课程的关系模式如下:SC(S#,Sn,C#,Cn,G,Cr)(其属性分别为学号、姓名、课程号、课程名、成绩、学分)
则关系最高是( )
(A)2NF |
(B)1NF | (C)3NF | (D)BCNF |
【解析】该关系模式满足1NF,主码至少有2个,选择(S#,C#)。(S#,C#)→Sn,只用学号S#就能决定姓名Sn,属于部分函数依赖,不满足2NF。
【答案】(B)
9.设有课程关系模式如下:R(C#,Cn,T,Ta)(其中C#为课程号,Cn为课程名,T为教师名,Ta为教师地址)并且假定不同课程号可以有相同的课程名,每门课程只有一位任课教师,但每位教师可以有多门课程。关系R范式最高达到( )
(A)1NF |
(B)2NF | (C)3NF | (D)BCNF |
【答案】(B)
10.定义学生选修课程的关系模式如下:SC(S#,Sn,C#,Cn,G,Cr,T#)(其属性分别为学号、姓名、课程号、课程名、成绩、学分、授课教师号),假定学生和课程都会有重名,则关系最高是( )
(A)1NF |
(B)2NF | (C)3NF | (D)BCNF |
【解析】
【答案】(B)
算法复杂度包括时间复杂度和空间复杂度,算法的空间复杂度是衡量内存开销与问题规模之间的关系。例如下面的算法中,当问题规模n
void loveyou(int n) //n既可以理解为变量也可以理解为问题规模
{int i =1; //爱你的程度
while(i<=n)
{i++;
printf("I Love You %d\n",i);
}
}
仅仅只是一个占有4B的int型变量,这个内存空间并不会随着n的改变而改变,而一直是一个常量。但在下面的算法中,问题规模n决定了一维数组的长度,将会影响这个数组所占内存空间的大小。
void test(int n)
{int flag(n);
int i;
}
为降低算法的空间复杂度,应减少输入数据所占存储空间以及额外空间,通常采用压缩存储技术。
算法的特征:输入,一个算法有零个或者多个输入,零个输入就是算法本身确定了初始条件;输出,一个算法有一个或者多个输出,以反映数据加工的结果。
1.流程图是描述算法的很好的工具,流程图一般由几种基本图形组成。其中输入输出框的图形是( )。
(A)平行四边形 |
(B)长方形 | (C)椭圆形 | (D)菱形 |
【解析】
【答案】(B)
2.以下不能用于描述算法的是( )。
(A)文字叙述 |
(B)程序语句 | (C)伪代码和流程图 | (D)E-R图 |
【解析】算法的描述有伪代码、流程图、N-S结构图等方法。E-R图是实体联系图,属于数据模型,不能用于描述算法。
【答案】(B)
3.关于算法,以下叙述中错误的是( )
(A)某个算法可能会没有输入 |
(B)同一个算法对于相同的输入必须得出相同的结果 |
(C)一个算法对于某个输入的循环次数是可以事先估计出来的 |
(D)任何算法都能转换成计算机高级语言的程序,并在有限时间内运行完毕 |
【解析】
【答案】 (D)
4.下列叙述中正确的是( )
(A)算法的复杂度与问题的规模无关 |
(B)算法的优化主要通过程序的编制技巧来实现 |
(C)对数据进行压缩会降低算法的空间复杂度 |
(D)数值型算法只需考虑计算结果的可靠性 |
【答案】(C)
数据的逻辑结构
根据数据元素之间的不同关系,数据结构可分为线性和非线性,线性结构必须满足:(1)有且只有一个根节点;(2)每一个结点最多有一个前件,也最多有一个后件。不满足以上两个条件就称为非线性结构,其又分为树形结构、网状结构和集合。
顺序存储结构:逻辑上相邻数据元素在物理上也相邻。
链式存储结构:每个结点中至少包含一个指针域。只有一个指针域的称为单链表,头指针HEAD存储的是第一个元素的地址,HEAD=0,或者HEAD=NULL,称为空表。尾结点的指针域为“NULL”,作为链表结束的标志。
数据的逻辑结构的数学形式定义——数据结构是一个二元组:
B=(D,R)
其中,B表示数据结构;D是数据元素的集合;R是D上关系的集合,它反映了D中各数据元素之间的前后件关系,前后件关系也可以用一个二元组来表示。
线性链表
每个存储节点只有一个指针域,称为单链表。每个存储节点有两个指针域,一个指针域存放前件的地址,称为左指针域,另一个指针域存放后件的地址,称为右指针域,这样的链表称为双向链表。
非空循环链表
在单链表的第1个节点前增加一个表头节点,队头指针指向表头节点,最后一个节点的指针域的值由NULL改为指向表头节点,这样的链表称为循环链表。循环链表是线性结构,有且只有一个根节点,循环链表表头结点为根节点,链表的最后一个节点为叶子节点,虽然它含有一个指向表头节点的指针,但表头节点并不是它的一个后件。
栈
单链栈:top指针记录的是栈元素的下标,从[0]开始,空栈的情况下,top指针应指向-1。
带双链栈:,空栈时,top=bottom=NULL;存在1个元素时,top=bottom≠NULL。
队列
带链队列:,空队列时,front=rear=NULL;存在1个元素时,front=rear=1。
循环队列:,空队列时,front=rear=m;存在1个元素时,front=1,rear=2;当front=rear≠m时,队列可能空,也可能满,因为有元素时,front指向对头元素,rear指向队尾元素的下一个结点。而队列满的时候,rear并不指向1,而是指向m。
1.下列叙述中正确的是( )
(A)线性链表可以有多个指针域 |
(B)有两个以上指针域的链表是非线性结构 |
(C)只有一个指针域的链表一定是线性结构 |
(D)线性链表最多可以有两个指针域 |
【解析】
【答案】(A)
2.下列叙述中正确的是( )
(A)在循环队列中,队尾指针的动态变化决定队列的长度 |
(B)在循环队列中,队头指针的和队尾指针的动态变化决定队列的长度 |
(C)在带链的队列中,对头指针与队尾指针的动态变化决定队列的长度 |
(D)在带链的栈中,栈顶指针的动态变化决定栈中元素的个数 |
【解析】在链式存储结构中,由于存储单元很可能是不连续的,指针的值就是地址,不连续地址的变化反应不出来整个数据元素的情况。
【答案】(B)
3.下列叙述中正确的是( )
(A)向量是顺序存储的线性结构 |
(B)只有一个根结点核一个叶子结点的结构必是线性结构 |
(C)非线性结构只能采用链式存储结构 |
(D)所有非线性结构都能采用顺序存储结构 |
【解析】(B)选项可以是树结构(非线性结构)
【答案】(A)
4.带链队列空的条件是( )
(A)front=rear=NULL |
(B)front=-1且rear=NULL |
(C)front=NULL且rear=-1 |
(D)front=rear=-1 |
【答案】(A)
5.在带链队列中,经过一系列正常的操作后,如果front=rear,则队列中的元素个数为( )。
(A)0 |
(B)1 | (C)0或1 | (D)队列满 |
【答案】(C)
6.某带链的队列初始状态为front=rear=NULL。经过一系列正常的入队和退队操作后,front=rear=10。则队列中的元素个数为( )。
(A)0 |
(B)1 | (C)0或1 | (D)不确定 |
【答案】(B)
7.下列叙述中正确的是( )。
(A)循环队列是队列的一种顺序存储结构 |
(B)循环队列是队列的一种链式存储结构 |
(C)循环队列中的队尾指针一定大于队头指针 |
(D)循环队列中的队尾指针一定小于对头指针 |
【解析】循环队列在存储物理上和逻辑都满足相邻的条件,因此是输入顺序存储结构
【答案】(A)
8.循环队列的存储空间为Q(1:50)。经过一系列正常的入队与退队操作后,front=rear=25。后又成功地将一个元素入队,此时队列中的元素个数为( )。
(A)1 |
(B)50 | (C)26 | (D)2 |
【答案】(A)
9.循环队列的存储空间为Q(1:50)。经过一系列正常的入队与退队操作后,front=rear=25。后又成功地将一个元素退队,此时队列中的元素个数为( )。
(A)24 |
(B)49 | (C)26 | (D)0 |
【答案】(B)
度:一个节点(结点)所拥有的后件个数称为该节点的度,所有节点中最大的度称为树的度。
树的性质:(1)节点数=总度数+1;每1个度下面有1个节点,但根节点上面没有度,所以+1。
二叉树的性质:(1)只看1个度为2的结点,叶子结点一定有2个,根节点只有1个,叶子结点=度为2的结点数+1;
(2)深度为K的二叉树中,最多有个节点
排序二叉树:左子树<根<右子树,因此进行中序遍历可以得到一个递增的有序序列
满二叉树:除最后一层外,每一层上的所有节点都有两个子节点的二叉树
完全二叉树:除最后一层外,每一层上的结点数均达到最大值,在最后一层上只缺少右边的若干结点。性质:(1)最多只有一个度为1的结点;
(2)叶子结点+度为2的结点一定是奇数,利用二叉树的性质(1),叶子结点+度为2的结点=度为2的结点+1+度为2的结点=2*度为2 结点+1。结合性质(1),若完全二叉树有2k(偶数)个结点,则必有度为1的结点=1,叶子结点=k,度为2的结点=k-1。
非完全二叉树:每一层的结点散布的零零散散。
满二叉树一定是完全二叉树,完全二叉树不一定是满二叉树
1.设非空二叉树的所有子树中,其左子树的结点值均小于根节点值,而右子树上的结点值均不小于根结点值,则称该二叉树为排序二叉树。对排序二叉树的遍历结果为有序序列的是( )
(A)前序序列 |
(B)中序序列 |
(C)后序序列 |
(D)前序序列或后序序列 |
【答案】(B)
2.某颗树中共有25个结点,且只有度为3的结点和叶子结点,其中叶子结点有7个,则该树中度为3的结点数为( )
(A)7 |
(B)8 | (C)6 | (D)不存在这样的树 |
【解析】根据题目能算出度为3的结点数,但与定理所求的结点数矛盾。
【答案】(D)
交换类排序
冒泡排序:线性表中,相邻两个数据元素,当前面的元素大于后面的元素,则将它们交换,消除一个逆序。
快速排序:取一个元素K(通常取第一个元素),小于K放前面,大于K放后面。
插入类排序
简单插入排序:把n个元素看成一个有序表和无序表,开始时,有序表只包含一个元素,每次取无序表中的第一个元素插入有序表的正确位置。
选择类排序
简单选择排序:先从所有n个待排序的元素中选择最小的元素与第一个元素交换,再从剩下的n-1个元素中选出最小的元素与第2个元素交换。
堆排序:堆的概念与带有某种性质的完全二叉树有关,进一步分为大根堆或小根堆,堆排序是指在输出堆顶的最小值(最大值)后,使得剩余n-1个元素的序列重又建成一个堆,则得到n个元素的次小堆(次大堆)……,如此反复,便能得到一个有序序列。
堆排序 | |
简单选择排序 | |
简单插入排序 | |
冒泡排序 | |
快速排序 | |
希尔排序 |
1.在排序过程中,每一次数据元素的移动会产生新的逆序的排序方法是( )。
(A)快速排序 |
(B)简单插入排序 | (C)冒泡排序 | (D)以上说法均不正确 |
【解析】在数据元素的序列中,对于某个元素,如果其后存在一个元素小于它,则称之为存在一个逆序。
【答案】(A)
2.在快速排序法中,每经过一次数据交换(或移动)后( )。
(A)不会产生新的逆序 |
(B)只能消除一个逆序 |
(C)能消除多个逆序 |
(D)消除的逆序个数一定比新产生的逆序个数多 |
【解析】快速排序不是对两个相邻元素进行比较,可以实现通过一次交换而消除多个逆序,但由于均与K(基准元素)比较,也可能会产生新的逆序。
【答案】 (C)
3.下列叙述中正确的是( )
(A)快速排序法适用于顺序存储的线性表 |
(B)快速排序适用于链式存储的线性表 |
(C)链式存储的线性表不可能排序 |
(D)堆排序适用于非线性结构 |
【解析】
【答案】(A)
4.下列各组排序法中,最坏情况下比较次数相同的是( )
(A)简单选择排序与堆排序 |
(B)简单插入排序与希尔排序 |
(C)冒泡排序与快速排序 |
(D)希尔排序与堆排序 |
【答案】(C)
4.对长度为8的数组进行快速排序,最多需要的比较次数为( )。
(A)8 |
(B)28 | (C)56 | (D)64 |
【答案】(B)
5.设顺序表的长度为n。下列排序方法中,最坏情况下比较次数小于n(n-1)/2的是( )。
(A)堆排序 |
(B)快速排序 | (C)简单插入排序 | (D)冒泡排序 |
【答案】(A)
软件工程包含方法、工具和过程3个要素。方法是完成软件开发各项任务的技术手段;工具支持软件的开发、管理、文档生成;过程支持软件开发的各个环节的控制、管理。
软件危机主要表现在:软件需求的增长得不到满足,软件开发成本和进度无法控制,软件质量难以保证,软件不可维护或维护程度非常低,软件的成本不断提高,软件开发生产率的提高赶不上硬件的发展和应用需求的增长。
1.软件工程的三要素是( )。
(A)方法、工具和环境 |
(B)方法、工具和过程 | (C)方法、平台和管理 | (D)方法、工具和文档 |
【答案】(B)
2.下面描述中,不属于软件危机表现的是( )。
(A)软件开发生产率低 |
(B)软件过程不规范 | (C)软件质量难以控制 | (D)软件质量难以控制 |
【答案】(B)
需求分析方法——建立系统逻辑模型,解决“做什么”
结构化分析(Structured Analysis——SA)方法:面向数据流的SA方法、
结构化分析的工具:数据流图(Data Flow Diagram——DFD)是系统逻辑模型的图形表示,是专业人员与非专业用户之间的通信工具,其中箭头表示数据流,刻画了数据流从输入到输出的移动变化过程,能够直接支持后续系统的功能建模;数据字典(Data Dictionary——DD)是对数据流图中所有元素的定义的集合。
数据流图和数据字典共同构成系统的逻辑模型。
面向对象分析方法的工具:
需求分析结果:软件需求规格说明书
软件设计——解决“怎么做”
概要设计(总体设计)
结构化设计的工具是结构图(Structure Chart——SC),也称为程序结构图,是用来描述软件系统结构的图形工具。
术语 | 含义 |
---|---|
从属模块 | 被另一个模块调用的模块 |
原子模块 | 树中位于叶子节点的模块,也就是没有从属节点的模块 |
深度 | 表示控制的层数 |
宽度 | 最大模块数的层的控制跨度 |
扇入 | 调用一个给定模块的个数 |
详细设计
详细设计的工具:PAD图——问题分析图(Problem Analysis Diagram),用二维树型结构表示程序的控制流,易于翻译为程序代码。
程序流程图(程序框图)——
测试
测试方法:白盒测试就是看软件或者程序的内部有没有逻辑错误,数据的走向是否正确;黑盒则不注重内部,只关心合法的输入能不能得到正确的输出。黑盒测试方法和技术有等价类划分法、边界值分析法、错误推测法和因果图法。
错误推测法是一种经验和直觉推测可能错误的方法。
测试用例:是为了测试设计的数据,由测试输入数据和与之对应的预期输出结构两部分组成。
单元测试 | 也称模块测试,模块是软件设计的最小单位,单元测试是对模块进行正确性的检验,以期尽早发现各模块内部可能存在的错误。 |
集成测试 | 也称组装测试,它是对各模块按照设计要求组装成的程序进行测试,主要目的是发现与接口有关的错误(系统测试与此类似)。 |
确认测试 | 以需求规格说明书作为依据,检查软件的功能、性能及其他特征是否与用户的需求一致。 |
系统测试 | 把软件系统整体作为一个元素,与计算机硬件、支持软件、数据、人员和其他计算机系统的元素组合在一起,在实际运行环境下对计算机系统进行一些系列的集成测试和确认测试。 |
1.软件生存周期中,解决软件“怎么做”的阶段是( )。
(A)软件测试 |
(B)需求分析 | (C)软件设计 | (D)可行性研究 |
【答案】(C)
2.软件需求规格说明书的作用不包括( )
(A)软件验收的依据 |
(B)用户与开发人员对软件要做什么的共同理解 |
(C)软件设计的依据 |
(D)软件可行性研究的依据 |
【解析】软件需求规格说明书有以下几个方面的作用:便于用户、开发人员进行理解和交流;反映出用户问题的结构,可以作为软件开发工作的基础和依据;作为确认测试和验收的依据。
【答案】(D)
3.数据流图(DFD)的作用是( )
(A)支持软件系统功能建模 |
(B)支持软件系统的面向对象分析 |
(C)描述软件系统的控制流 |
(D)描述软件系统的数据结构 |
【答案】(A)
4.对数据流图(DFD)描述错误的是( )
(A)数据流图直接支持系统的数据建模 |
(B)数据流图是描述数据处理过程的工具 |
(C)数据流图是需求理解的逻辑模型的图形表示 |
(D)数据流图直接支持系统的需求建模 |
【解析】
【答案】(A)
5.违背数据流图(DFD)构造规则的是( )
(A)“数据存储”间有数据流 |
(B)“加工”应既有输入又有输出 |
(C)“数据流”应标识数据流名 |
(D)父图子图是指相邻上下两层的数据流图 |
【解析】
【答案】(A)
6.数据字典(DD)所定义的对象都包含于( )
(A)数据流图(DFD图) |
(B)程序流程图 |
(C)软件结构图 |
(D)方框图 |
【解析】
【答案】(A)
7.在软件设计中不使用的工具是( )
(A)系统结构图 |
(B)PAD图 |
(C)数据流图(DFD图) |
(D)程序流程图 |
【解析】系统结构图是对软件系统结构的总体设计的图形显示,在需求分析阶段,已经从系统开发的角度出发,把系统按功能逐次分割成层次结构,是在概要设计阶段用到的。PAD图是在详细设计阶段用到的。程序流程图是对程序流程的图形表示,在详细设计过程中用到。数据流图是结构化分析方法中使用的工具,它以图形的方式描绘数据在系统中流动和处理的过程,由于它只反应系统必须完成的逻辑功能,所以它是一种功能模型,是在可行性研究阶段用到的而非软件设计时用到。
【答案】(C)
6.在软件设计阶段不使用( )。
(A)DFD图(数据流程图) |
(B)PAD图 |
(C)程序流程图 |
(D)判定表 |
【解析】软件设计常用的工具有结构图、程序流程图、N-S图、PAD图、HIPO图、判定表、PDL。DFD(数据流程图)是需求分析阶段使用的工具。
【答案】(A)
7.对软件系统总体结构图描述正确的是( )
(A)从属模块一定是原子模块 |
(B)扇入是一个模块直接调用的其他模块数 |
(C)结构图是描述软件系统功能的 |
(D)深度等于控制的层数 |
【答案】(D)
8.某系统结构图如下图所示,该系统结构图的宽度是( )
(A)4 |
(B)5 | (C)2 | (D)1 |
【答案】(B)
8.软件测试的目的是( )
(A)避免程序中的错误 |
(B)修改程序中的错误 |
(C)发现程序中的错误 |
(D)发现和修改程序中的错误 |
【解析】 软件测试是为了发现错误而执行程序的过程,只发现错误而不改正。程序调试的任务是诊断和改正程序中的错误。
【答案】(C)
9.软件测试的实施步骤是( )。
(A)单元测试,集成测试,确认测试 |
(B)集成测试,确认测试,系统测试 |
(C)确认测试,集成测试,单元测试 |
(D)单元测试,集成测试,回归测试 |
【解析】符合测试步骤的只有(A)。
【答案】(A)
10.代码编写阶段可进行的软件测试是( )。
(A)单元测试 |
(B)集成测试 | (C)确认测试 | (D)系统测试 |
【答案】(A)
11.黑盒测试技术依据的是( )。
(A)程序的逻辑结构 |
(B)程序的物理结构 | (C)软件功能的描述 | (D)软件行为的描述 |
【答案】(C)
12.软件测试用例包括( )。
(A)输入数据和输出数据 |
(B)测试计划和测试数据 |
(C)被测程序和测试规程 |
(D)输入数据和预期输出结果 |
【答案】(D)
13.下面属于黑盒测试方法的是( )。
(A)条件覆盖 |
(B)基本路径测试 | (C)判定覆盖 | (D)错误推测法 |
【答案】(D)
结构化程序设计由3种基本控制结构组成:顺序结构、选择结构、循环结构。由这3种基本结构组成的算法结构可以解决任何复杂的问题,由它们所构成的算法称为结构化算法,由它们所构成的程序称为结构化程序。
结构化程序设计方法的重要原则是自顶向下、逐步求精、模块化及限制使用goto语句。
结构化程序设计的目的:通过设计结构良好的程序,以程序静态的良好结构保证程序动态执行的正确性,使程序易理解、易调试、易维护,以提高软件开发的效率、减少出错率。
面向对象的程序设计
对象是由描述对象属性的数据以及可以对这些数据施加的所有操作封装在一起构成的统一体。一个对象通常可由对象名(标识)、属性和操作三部分组成。
对象的主要特征:(1)抽象;(2)封装;(3)继承,指能够直接获得已有的性质和特征,不必重复定义它们,使得开发新的应用系统时,不必完全从零开始,可以继承原有的相似系统的功能;(4)多态性,消息传递是对象通信的手段,一个对象通过向另一个对象发送消息来请求其服务,对象根据所接收的消息而做出动作,同样的消息被不同的对象接收时可导致完全不同的行为。
类:具有共同属性、共同方法的对象的集合,是关于对象的抽象描述,反映属于该对象类型的所有对象的性质。
实例:一个具象对象则是其对应类的一个实例
1.结构化程序设计强调( )。
(A)程序的效率 |
(B)程序的规模 | (C)程序的易读性 | (D)程序的可复用性 |
【答案】(C)
2.以下叙述中错误的是( )。
(A)在进行模块化程序设计的时候,应首先完成每个模块的编写、调试,再集中考虑主程序的算法 |
(B)同一程序的各模块可由一组人员同时进行编写、调试,可提高编写程序的效率 |
(C)模块化的程序设计是采用自顶向下、逐步细化的原则 |
(D)程序的每个模块都可通过3种基本结构实现 |
【答案】(A)
3.以下叙述中错误的是( )。
(A)使用3种基本结构构成的程序只能解决简单问题 |
(B)结构化程序由顺序、分支、循环3种基本结构组成 |
(C)C语言是一种结构化程序设计语言 |
(D)结构化程序设计提倡模块化的设计方法 |
【答案】(A)
4.以下叙述中错误的是( )
(A)在一个程序中,每个模块均可以独立编译运行 |
(B)程序“模块化”有利于任务的分解简化 |
(C)允许对函数单独进行编译,是C语言实现“模块化”的基础 |
(D)采用模块化结构,可以提高编程效率 |
【解析】(A),在一个程序中各模块之间输入输出关系已经确定,不可能每个模块都能独立运行。
【答案】(A)
4.不属于对象构成成份的是( )。
(A)标识 |
(B)属性 | (C)方法(操作) | (D)规则 |
【答案】(D)
5.下列选项中,不是面向对象主要特征的是( )。
(A)复用 |
(B)抽象 | (C)继承 | (D)封装 |
【答案】(A)
6.下面对“对象”概念描述错误的是( )。
(A)对象不具有封装性 |
(B)对象是属性和方法的封装体 |
(C)对象间的通信是靠消息传递 |
(D)一个对象是其对应类的实例 |
【答案】(A)
1.顺序程序不具有( )。
(A)顺序性 |
(B)并发性 | (C)封闭性 | (D)可再现性 |
【解析】顺序程序具有顺序性、封闭性和可再现性的特点,使得程序设计者能够控制程序执行的过程(包括执行顺序、执行时间),对程序的中间结果和状态可以预先估计,这样可方便对程序进行测试和调试。并发程序的特点:并发性。
【答案】(B)
1.设栈的存储空间为S(1:50),初始状态为top=51。现经过一些列正常的入栈与退栈操作后,top=50,则栈中的元素个数为( )。
(A)0 |
(B)1 | (C)50 | (D)49 |
【解析】栈的存储空间为S(1:50),所指是内存地址1到50为栈,
1 |
2 |
… |
49 |
50 |
51 |
top=51,也就是指向-1的效果。
【答案】(B)
2.带链栈空的条件是( )。
(A)top=bottom=-1 |
(B)top=-1且bottom=NULL |
(C)top=NULL且bottom=-1 |
(D)top=bottom=NULL |
【答案】(D)
3.在带链栈中,经过一系列正常的操作后,如果top=bottom,则栈中的元素个数为( )。
(A)0 |
(B)1 | (C)0或1 | (D)栈满 |
【答案】(C)
1.设某棵树的度为3,其中度为3,2,1的结点个数分别为3,0,4。则该树中的叶子结点数为( )。
(A)6 |
(B)7 | (C)8 | (D)不可能有这样的树 |
【解析】树的度为3,该树有为度为3,度为2,度为1,度为0的4种结点。根据条件,假设度为0(叶子结点)的结点有n个,总结点数=3×3+2×0+1×4+0×n+1=14,另外,还有3+0+4+n=总结点数,联立方程有n=7。
【答案】(B)
2.某棵树中共有25个节点,且只有度为3的节点和叶子节点,其中叶子节点有7个,则该树中度为3的节点数为( )。
(A)不存在这样的树 |
(B)7 | (C)8 | (D)6 |
【答案】(A)
3.某二叉树有5个度为2的节点,则该二叉树中的叶子节点数是( )。
(A)10 |
(B)8 | (C)6 | (D)4 |
【答案】(C)
4.在具有2n个结点的完全二叉树中,叶子结点个数为( )。
(A)n-1 |
(B)n | (C)n+1 | (D)n/2 |
【答案】(B)
1.设顺序表的长度为40,对该表进行冒泡排序。在最坏情况下需要的比较次数为( )。
(A)40 |
(B)41 | (C)780 | (D)820 |
【答案】(C)
2.对长度为10的线性表进行冒泡排序,最坏情况下需要比较的次数为( )。
(A)9 |
(B)10 | (C)45 | (D)90 |
【答案】(C)
3.线性表的长度为n。在最坏情况下,比较次数为n-1的算法是( )。
(A)顺序查找 |
(B)同时寻找最大项与最小项 |
(C)寻找最大项 |
(D)有序表的插入 |
【答案】(C)
顺序查找 | 从第一个元素开始逐个与被查找元素比较 | n |
二分查找 | 使用时,必须满足2个条件: (1)用顺序存储结构 (2)线性表是有序表 将被查找元素与有序表中间项比较 |
1.在长度为n的顺序表中查找一个元素,假设需要查找的元素有一半的机会在表中,并且如果元素在表中,则出现在表中每个位置上的可能性是相同的。则在平均情况下需要比较的次数大约为( )
(A)n |
(B)n/2 | (C)3n/4 | (D)n/4 |
【解析】
【答案】( )
2.在长度为97的顺序有序表中作二分查找,最多需要的比较次数为( )
(A)48 |
(B)96 | (C)7 | (D)6 |
【解析】本题中,n=97,最多需要的比较次数为,,需要比较7次。
【答案】(C)
投影运算:
从关系模式R中指定属性A组成新的关系,A为R中的属性
选择运算:
从关系中R找出满足属性A=f且属性B≥60的元组
自然连接(口诀——公共属性上的等值连接):
将R和S中相同列中,值相同的属性拼接到一起
1.设有3个关系R、S和T:
则由关系R和S得到关系T的操作是( )。
(A)并 |
(B)投影 | (C)交 | (D)选择 |
【解析】交是把元素相同的元组放到一起,这过程新的关系的元组数要么相等要么变少;选择是从关系中找出给定条件的元组,元组数要么相等要么减少,投影找的是列,也就是属性。
【答案】(A)
2.有三个关系R、S和T如下图所示,则由关系R和S得到关系T的操作是( )。
(A)交 |
(B)并 | (C)差 | (D)选择 |
【解析】做差运算,会将被减关系中和减关系完全相同的元组删除,而不存在被减关系中的元组不做考虑。
【答案】(C)
3.学生选课成绩表的关系模式是SC(S#,C#,G),其中S#为学号,C#为课号,G为成绩,学号为20的学生所选课程中成绩及格的全部课号为( )。(由于公式不支持,选项中#取消)
(A) |
(B) |
(C) |
(D) |
【答案】(D)
3.定义学生选修课程的关系模式如下:
S(S#,Sn,Sd,Sa)(其属性分别为学号、姓名、所在系、年龄);
C(C#,Cn,P#)(其属性分别为课程号、课程名、先选课);
SC(S#,C#,G)(其属性分别为学号、课程号、成绩)。
检索选修了课程号为2且成绩不及格的学生的姓名的表达式是( )。(用jin代表#)
(A) |
(B) |
(C) |
(D) |
【解析】
【答案】(B)
4.定义学生选修课程的关系模式如下:
S(S#,Sn,Sd,Sa)(其属性分别为学号、姓名、所在系、年龄);
C(C#,Cn,P#)(其属性分别为课程号、课程名、先选课);
SC(S#,C#,G)(其属性分别为学号、课程号、成绩)。
检索选修课程名为“操作系统”的成绩在90分以上(含90分)的学生的姓名的表达式是( )。(用jin代表#,用CZXT代表操作系统)
(A) |
(B) |
(C) |
(D) |
【答案】(D)
5.现有表示患者和医疗的关系如下:P(P#,Pn,Pg,By),其中P#为患者编号,Pn为患者姓名,Pg为性别,By为出生日期,Tr(P#,D#,Date,Rt),其中D#为医生编号,Date为就诊日期,Rt为诊断结果。检索在1号医生处就诊且诊断结果为感冒的病人姓名的表达式是( )。(用jin代表#,ganmao代替感冒)
(A) |
(B) |
(C) |
(D) |
【答案】(A)
凡是以“#”开头的行都称为编译预处理行,每行末位不加“;”,由于没有分隔符,源文件一行只能有一条预处理命令。预处理程序负责分析和处理以“#”标志为首字符的控制行,所谓编译预处理就是在C编译程序进行编译前,由编译预处理程序对这些编译预处理命令行进行处理的过程。C语言的预处理功能主要有3种:宏替换、文件包含、条件编译,一般习惯在源文件开头书写预处理行。
(1)不带参数的宏定义形式:
#define 宏名 替换文本
在程序中使用“替换文本”代替任何一个出现“宏名”的地方
(2)带参数的宏定义形式:
#define 宏名(形参表) 替换文本
1.以下叙述中正确的是( )
(A)宏替换不占用程序的运行时间 |
(B)预处理命令行必须位于源文件的开头 |
(C)在源文件的一行上可以有多条预处理命令 |
(D)宏名必须用大写字母表示 |
【答案】(A)
标识符:由字母(大小写均可)、数字和下划线组成,且必须以字母或下划线组成。
常量分为:(1)整型常量:不带小数点的数字,八进制整型常量的开头是数字“0”,十六进制
整型常量的开头数字是“0x”;
(2)实型常量:带小数点的数字,有小数形式和指数形式两种表达形式,指数形
式中的“e”或“E”后面的阶码必须是一个整数,且“e”或“E”前面必须有数字;
(3)字符型常量
类型说明符 | 所占字节数 |
int | 4 |
double(双精度) | 8 |
变量的存储方式分为静态存储方式和动态存储方式,静态存储方式指程序运行期间分配固定的存储空间的方式,动态存储方式指程序运行期间根据需要动态分配存储空间的方式。
auto变量的关键字“auto”可以省略,在函数或复合语句内部定义变量时,没有指定存储类别,系统默认为是auto,因此只有局部变量才能声明为auto变量,特点:(1)内存分配:在动态存储区为其分配存储单元,函数或复合语句执行结束,立即释放;
(2)初值:未赋初值,变量初值不确定,如果赋初值,每次函数被调用时执行一次赋值操作;
(3)生存期:所在函数或复合语句的执行期间;
(4)作用域:从auto变量定义位置开始到函数体或符合语句结束。
static变量分为静态局部变量和静态全局变量,在函数体或复合语句内部时,称为静态局部变量,全局变量在定义时就默认为是静态的。静态变量的特点:(1)内存分配:编译时,分配在内存的静态区,整个程序运行期间,static变量占据着永久性的存储单元;
(2)初值:若定义时没赋初值,编译时,自动赋初值0,程序运行后不再赋初值。也就是说,当含有static变量的函数再次调用时,不会再对其进行赋初值,而是采用上一次调用结束时的值,如果再次赋初值,与一般变量没有区别;
(3)生存期:整个程序的执行期间
(4)作用域:所在函数或复合语句
register变量是建议编译程序将变量的值保留在CPU的寄存器内,而不占用内存单元,但仅仅是建议,由系统自己决定,所以很有可能还是会占用内存。
extern变量是扩展全局变量的作用域,例如外部程序调用,避免多个程序文件对同一个变量定义产生“重复定义”报错,特点:(1)内存分配:编译时,分配在静态存储区,程序运行结束释放。如果全局变量不在文件开头定义,其有效的作用域只限于定义处到文件结束。如果在定义点之前的函数想引用该全局变量,则应该在引用之前用关键字extern对该变量作“全局变量声明”。这时的作用域扩展到从extern声明处起,延伸到该函数末尾。
一维数组定义:
类型说明符 数组名[常量表达式]
“常量表达式”可以是整型常量、符号常量,不允许是0、负数、浮点数和变量
条件表达式的一般格式:
表达式1? 表达式2:表达式3
“表达式1”为真,计算“表达式2”,整个条件表达式的值为“表达式2”;“表达式1”为假,计算“表达式3”,同理;
if(表达式)语句中,表达式可以是关系表达式、逻辑表达式、任意数值类型(包括整型、实行、字符型等)。
多层if嵌套时,原则上else与它上面最近、未配对的if配对。
C99允许使用基类型为void的指针类型,可以定义一个基类型为void的指针变量(即void * 型变量),它不指向任何类型的数据。注意:不要把“指向void类型”理解为指向“任何的类型”的数据,而应理解为“指向空类型”或“不指向确定的类型”的数据。在将它的值赋给另一个指针变量时由系统对它进行类型转换,使之合适于被赋值的变量的类型。
1.以下关于指针的叙述正确的是( )
(A)若定义void *p;, 则p可以保存任何内存地址 |
(B)若定义int a,*p=&a;,则&a仅仅是内存地址,没有类型 |
(C)若定义char *p=“”;,则p保存的值是0 |
(D)若定义double *pd=0,则pd不是空指针 |
输出字符串函数——puts(字符数组名),遇到字符串结束标志符'\0'停止,并用‘\n’取代'\0'。
islower(x)——是小写字母吗?,是返回非0,不是返回0。
字符输入——x = getchar(),从输入缓冲区获取第1个字符,如果是回车,也看作是一个字符,并将该字符的赋值给x,x只能是字符型变量或整型变量,当x为整型变量时,x的值为输入字符对应的ASCII码值。
退出——exit()就是终止整个程序,传入的参数是程序退出时的状态码。0表示正常退出,其他表示非正常退出。
return()是终止本次函数的运行,返回上一级函数。
头文件,“stdlib.h”。函数原型为void * malloc(unsigned int size) ,其作用是在内存的动态存储区中分配一个长度为size的连续空间。形参size的类型定为符号整型(不允许为负数)。此函数的值(即“返回值”)是所分配区域的第一个字节的地址,或者说,此函数是一个指针型函数,返回的指针指向该分配域的开头位置,如:
malloc(100); //开辟100B的临时分配域,函数值为其第一个字节的地址
注意指针的基类型为void,即不指向任何类型的数据,只提供一个地址。 如果此函数未能成功地执行(例如内存空间不足),则返回空指针(NULL)。
1.设有定义和语句(假设short int型数据占2字节)
short int *pi,*pj;
pi=pj=(short *)malloc(2);
则以下叙述正确的是( )
(A)pi和pj指向了同一个short int型存储单元 |
(B)pi和pj指向了2个连续的short int型存储单元的首地址 |
(C)pi和pj分别指向了一个short int型存储单元 |
(D)pi和pj指向了2个short int型存储单元 |
【答案】(A)
在使用malloc函数申请的内存块在操作结束后,应及时使用free函数释放。
幂函数——pow(x,y)函数用来求x的y次幂,x、y及函数返回值都是double型
当底为自然对数e的时候采用exp(x)函数,x为幂
绝对值——fabs(x)返回浮点数x的绝对值
abs(x)返回整数x的绝对值
运算符 | 运算对象 | 运算结果 |
% | 整型 | 整型 |
关系运算就是将两个值进行比较,判断是否表达式是否成立。用关系运算符将两个表达式连接起来的式子称为关系表达式,基本形式如下:
表达式1 关系运算符 表达式2
“表达式1”和“表达式2”可以是常量、变量、算术表达式、关系表达式、逻辑表达式、赋值表达式及字符表达式等。关系运算的结果是一个逻辑值,只有两种可能,要么关系成立,为“真”;要么关系不成立,为“假”。C语言中用1代表“真”,用0代表“假”。
关系运算符是双目运算符,具有自左至右的结合性。例如,x的值为6,y的值为5,z的值为4,则:
n = x > y > z;
根据运算符的优先级可知,先计算关系表达式“x > y > z”的值,根据运算符的结合性可知,先计算关系表达式中的“x > y”的值为1,再计算关系表达式“1 > z”的值为0,最后将0赋予变量n。
关系运算符 | 说明 | 优先级 |
<= | 小于等于 | 优先级相同(高) |
>= | 大于等于 | |
== | 等于 | 优先级相同(低) |
大于等于 | ||
! = | 不等于 |
逻辑表达式是将关系表达式或逻辑量进行逻辑运算。
与 | && | 均为真,才为真 |
或 | || | |
非 | ! |
“a++&&b++”,当a=0,已经能判断逻辑表达式为假,不再对b++这个表达式进行执行命令,a会++,但b不会。
算术运算符 | |
关系运算符 | |
赋值运算符 |
运算符 | 含义 | 规则 | 优先级 |
---|---|---|---|
操作数>>移位数 | 右移 | 将操作数对应的二进制数向右移,低位舍弃,高位分两种情况补位:(1)无符号数,高位补0; (2)有符号数,原本为正补0,为负补1。 |
|
操作数1^操作数2 | 按位异或 | 相异取1,相同为0 | |
操作数1|操作数2 | 按位或 | “操作数1”和“操作数2”必须是整型或字符型,将操作数二进制进行按位或,有1便为1。 |
扩展运算符 | 表达式 | 等价的表达式 |
---|---|---|
&= | a&=b | a=a&b |
break是跳出本层循环,在循环体内使用,for循环不会执行表达式3,do…while不会执行while判断。
continue——只能用于循环结构中,其作用是结束本次循环,不再执行continue语句之后的语句,立即转入对循环条件的判断和执行,在for循环中,还要再执行表达式3后,再转入对循环条件的判断。
一般形式:
do
循环体
while(表达式);
字符指针定义:
char * 字符指针变量 ="字符串";
等价于
char *字符指针变量;
字符指针变量="字符串";
二维数组名也是一个地址值,当作为函数实参时,对应的形参是行指针变量,有两种形式:
函数名(数据类型(*二维数组名)[行长度])
函数名(数据类型 二维数组名[][行长度]) 列长度可省略
a+0、a+1、a+2为a[0]、a[1]、a[2]的地址,等价于*(a+i)
a[0]+1等价于a[0][1],那么也可以等价于*(a+0)+1
通过向函数传递变量的地址可以改变相应内存单元的内容。
一维数组名是一个地址值,可以把数组名传递给函数,对应的函数形参有三种形式:(1)函数名(int *指针变量);
(2)函数名(int 指针变量[]);
(3)函数名(int 指针变量[m])
二维数组名也是一个地址值,对应的函数形参为行指针变量,有三种形式:(1)函数名(int 形参名[n][m]);
(2)函数名(int (*指针变量)[m]);
(3)函数名(int 指针变量[][m])
其中列下标m绝不能省略。
文件打开函数——fopen,调用格式:
FILE * fopen("文件名","操作方式");
操作方式 | 说明 |
---|---|
r | 以只读方式打开一个文本文件(该文件已存在),位置指针指向文件头,从此处读数据。若文件不存在就会出错 |
w | 以只写方式打开一个文本文件,若该文件不存在,系统自动建立它,否则刷新此文件,位置指针指向文件头,从此处写数据 |
a | 以追加方式打开一个文本文件,指针指向文件尾 |
a+ | 以读/写方式打开一个文本文件。打开文件时,读从文件头开始,写从文件尾部追加 |
r+ | 以读/写方式打开一个文本文件。打开文件时,读写位置指针指向文件头,以覆盖方式写文件 |
w+ | 以读/写方式建立一个新的文本文件 |
rb | 以只读方式打开一个二进制文件 |
rb+ | 以读/写方式打开一个二进制文件,允许读写数据,文件必须存在 |
wb | 以只写方式打开一个二进制文件 |
wb+ | 以读/写方式打开一个新的二进制文件 |
格式化写函数——fprintf,将输出内容按格式存放到磁盘的文本文件中,调用格式:
fprintf(文件指针,格式控制字符串,输出项表);
“文件指针”指向一个文本文件;“格式控制字符串”控制输出数据的格式;“输出项表”为要输出数据的变量的地址列表
fputc(字符地址,文件指针)函数——字符写函数,将字符写入文件指向的文件
fread(buffer,size,count,fp),功能是从fp所指向的文件当前位置开始,一次读入size个字节,重复count次,并将读入的数据存放到buffer指针指向的首地址,同时,将fp位置指针向前移动size × count个字节,如果调用成功,函数返回值=count。
fwrite(buffer,size,count,fp),功能是向fp所指向的文件中文件写数据块,buffer存放将要写入数据块的首地址,从buffer开始,一次输出size个字节,重复count次;同时,将fp位置指针向前移动size × count个字节,当指针指向的位置已经有数据,将覆盖其数据。
fseek(fp,offset,origin),一般用于二进制文件,但也用于文本文件,origin用以指定位移量是以哪个位置为基准;offset表示从origin开始移动的字节数,起始点即可用标识符表示,也可用数字来表示。
origin | 数值 | 代表的具体位置 |
---|---|---|
SEEK_SET | 0 | 文件开头 |
SEEK_CUR | 1 | 文件当前位置 |
SEEK_END | 2 | 文件末尾 |
在位移量的末尾上字母L表示long型,以便在读写大于64KB的文件时不致出错。
rewind(fp)——使文件位置指针返回到文件开头。
格式化读函数——fscanf,当遇到“空格”和“回车”结束读取。
feof(fp),通过feof函数检测文件是否结束。在执行读文件操作时,如果遇到文件尾,则返回逻辑真(1),否则返回逻辑假(0)。
1.设fp为指向某二进制文件的指针,且已读到此文件末尾,则函数feof(fp)的返回值为( )。
(A)0 |
(B)'\0' | (C)非0值 | (D)NULL |
【答案】(C)
2.若fp已定义为指向某文件的指针,且没有读到该文件的末尾,则C语言函数feof(fp)的函数返回值是( )。
(A)EOF |
(B)非0 | (C)-1 | (D)0 |
【答案】(D)
C语言所有运算符中,成员运算符"."、结构指向符“->”、下标运算符“[]”和圆括号“()”的优先级最高。自增/减运算符的优先级高于“*”。综合优先级:! > 算术运算符 > 关系运算符 > &&和|| > 赋值运算符
1.算术运算符和圆括号有不同的运算优先级,对于表达式:a+b+c*(d+e),关于执行顺序,以下说法正确的是( )
(A)先执行(d+e)得r2,再执行c*r2得r3,再执行a+b得r1,最后执行r1+r3得表达式最后结果 |
(B)先执行a+b得r1,再执行(d+e)得r2,再执行c*r2得r3,最后执行r1+r3得表达式最后结果 |
(C)先执行(d+e)得r2,再执行c*r2得r3,再执行b+r3得r4,最后执行a+r4得表达式最后结果 |
(D)先执行a+b得r1,再执行r1+c得r5,再执行(d+e)得r2,最后执行r5*r2得表达式最后结果 |
【解析】
【答案】(B)
1.以下叙述中错误的是( )。
(A)C语言中的每条可执行语句和非执行语句最终都将被转换成二进制的机器指令 |
(B)C程序经过编译、连接步骤之后才能形成一个真正可执行的二进制机器指令文件 |
(C)用C语言编写的程序称为源程序,它以ASCII代码形式存放在一个文本文件中 |
(D)C语言源程序经编译后生成后缀为.obj的目标程序 |
【解析】C语言的语句分为执行语句和非执行语句,执行语句用于完成某种特定操作,非执行语句用于为程序添加注释等。源程序文件以“.c”作为扩展名,经过编译后将可执行语句转换成二进制的机器指令后,形成一个扩展名为“.obj”的二进制文件,称为目标文件。连接是将编译形成的目标文件“.obj”和库函数及其他目录文件连接,形成统一的可执行的二进制文件“.exe”。
【答案】(A)
2.我们所写的每条C语句,经过编译最终都将转换成二进制的机器指令。关于转换以下说法错误的是( )。
(A)一条C语句可能会被转换成零条机器指令 |
(B)一条C语句可能会被转换成多条机器指令 |
(C)一条C语句对应转换成一条机器指令 |
(D)某种类型和格式的C语句被转换成器指令的条数是固定的 |
【解析】一个C语句经过编译后产生若干条机器指令。
【答案】(C)
4.以下叙述正确的是( )
(A)C程序的执行是从源文件的开头,一行一行向下执行,每行都会被执行到 |
(B)对于只包含表达式语句的程序段,执行顺序与书写顺序一致 |
(C)C程序的执行一定是从主函数开始,从主函数结束 |
(D)每个C源文都应当有一个主函数 |
【解析】C语言程序的执行是从main()函数开始的,但不一定在main()函数结束,在任何其他地方可以调用exit()函数结束程序的运行。
【答案】(B)
4.C语言中double型数据占字节数为( )
(A)4 |
(B)8 | (C)12 | (D)16 |
【解析】double型数据在内存中占8个字节,float型数据占4个字节,int型数据占2个字节,char型数据占1个字节。
【答案】(B)
5.以下选项中叙述正确的是( )。
(A)函数体必须由“{”开始 |
(B)C程序必须由main语句开始 |
(C)C程序中的注释可以嵌套 |
(D)C程序中的注释必须在一行内完成 |
【解析】函数定义由两部分组成:函数头和函数体。函数头包括函数名、函数类型、函数参数名和参数类型。例如,int max(int x, int y)为函数头,max为函数名,函数类型为int,函数参数名为x,y,参数类型也为int型。用“{}”括起来的部分称为函数体,“{”表示函数体的开始,“}”表示函数体的结束。程序总是从main函数开始执行的,不是main语句。
【答案】(A)
6.以下关于注释的叙述中错误的是( )
(A)注释的边界符号“/”和“*”之间不允许加入空格 |
(B)C语言允许注释出现在程序中任意合适的地方 |
(C)注释的内容仅用于阅读,对程序的运行不起作用 |
(D)注释的边界符号“/*”和“*/”必须成对出现且可以嵌套 |
【答案】(D)
6.以下关于函数的叙述中正确的是( )
(A)函数调用必须传递实参 |
(B)函数必须要有形参 |
(C)函数必须要有返回值 |
(D)函数形参的类型与返回值的类型无关 |
【解析】函数可分为无参函数和有参函数,mian(){...}就是典型的无参函数。
【答案】(D)
7.设有函数定义:void sub(int k,char ch){…}则以下对函数sub的调用语句中,正确的是( )。
(A)sub(1,97); |
(B)sub(2,'97'); | (C)n=sub(3,'a'); | (D)sub(4,'a'); |
【解析】调用函数时,其中一个实参必须是字符型。(A)选项中97传给形参,实际上传递的是ASCII码为97的字符。在函数定义时没有返回值,(C)错。
【答案】(A)
8.以下叙述中正确的是( )。
(A)用C语言编写的程序只能放在一个程序文件中 |
(B)C程序书写格式严格,要求一行内只能写一个语句 |
(C)C程序中的注释只能出现在程序的开始位置和语句的后面 |
(D)C程序书写格式自由,一个语句可以写在多行上 |
【解析】C语言编写的程序可以放置于多个程序文件中。
【答案】(D)
9.以下叙述中错误的是( )。
(A)数值型常量有正值和负值的区分 |
(B)常量可以用一个符号名来代表 |
(C)定义符号常量必须用类型名来设定常量的类型 |
(D)常量是程序运行过程中值不能被改变的量 |
【解析】常量分为3类:整型常量、实型常量和字符型常量,其中整型常量和实型常量又称为数值型常量。字符型常量,用带有单引号的字符表示。符号常量是一种特殊的常量,其值和类型是通过符号常量的定义命令决定的,一般形式为:
#define 标识符 常量
#define 是一条预处理命令,又称为宏定义命令,其功能是把命令格式中的标识符定义为其后的常量值。
在C语言的预编译处理中,可以用符号名代表一个常量,定义时不必指定常量类型。
【答案】(C)
10.以下叙述错误的是( )
(A)若用户标识符的命名与预定义标识符相同,命名无效 |
(B)若用户标识符的命名与关键字相同,将产生编译错误 |
(C)若用户标识符的命名与预定义标识符相同,预定义标识符失去原有含义 |
(D)若用户标识符的命名与预定义标识符相同,可能引发运行错误 |
【解析】
【答案】(A)
10.下列叙述中正确的是( )
(A)空字符串不占用内存,其内存空间大小是0 |
(B)两个连续的单引号('')是合法的字符常量 |
(C)可以对字符串进行关系运算 |
(D)两个连续的双引号("")是合法的字符串常量 |
【解析】空字符串尽管不包含字符,但包括结束标识符'\0',内存空间大小是1。字符串比较不能直接用关系运算符进行正确比较,可用strcmp函数实现。(D)和(B)可以这样,理解,""至少还有一个结束标识符,但''中什么都没有
【答案】(D)
11.以下关于C语言数据类型使用的叙述中错误的是( )。
(A)若要处理如“人员信息”等含有不同类型的相关数据,应自定义结构体类型 |
(B)若要保存带有多位小数的数据,可使用双精度类型 |
(C)若只处理“真”和“假”两种逻辑值,应使用逻辑类型 |
(D)整数类型表示的自然数是准确无误差的 |
【解析】C语言中没有逻辑类型。
【答案】(C)
12.以下叙述中正确的是( )。
(A)即使不进行强制类型转换,在进行指针赋值运算时,指针变量的基类型也可以不同 |
(B)如果企图通过一个空指针来访问一个存储单元,将会得到一个出错信息 |
(C)设变量p是一个指针变量,则语句p=0;是非法的,应该使用p=NULL; |
(D)指针变量之间不能用关系运算符进行比较 |
【解析】p=0;和p=NULL;是等价的。
【答案】(B)
13.以下叙述中正确的是( )。
(A)字符串数组,是指数组中的每个元素都是一个存放字符串的一维数组 |
(B)char ca[3][5]={"A","BB","CCC"};是不合语法的 |
(C)char ca[][5]={"A","BB","CCC"};是不合语法的 |
(D)char *ca[3]={"A","BB","CCC"};是不合语法的 |
【答案】(A)
14.以下叙述中正确的是( )。
(A)只要适当地修改代码,就可以将do-while与while相互转换 |
(B)对于“for(表达式1;表达式2;表达式3)循环体”首先要计算表达式2的值,以便决定是否开始循环 |
(C)对于“for(表达式1;表达式2;表达式3)循环体”,只在个别情况下才能转换成while语句 |
(D)如果根据算法需要使用无限循环(即通常所称的“死循环”),则只能使用while语句 |
【解析】for语句最灵活,它可以完全取代while语句。
【答案】(A)
16.下列关于C语言文件的叙述中正确的是( )。
(A)文件由一系列数据依次排列组成,只能构成二进制文件 |
(B)文件由结构序列组成, 可以构成二进制文件或文本文件 |
(C)文件由数据序列组成,可以构成二进制文件或文本文件 |
(D)文件由字符序列组成,其类型只能是文本文件 |
【解析】
【答案】(C)
17.下面关于“EOF”的叙述,正确的是( )。
(A)EOF的值等于0 |
(B)EOF是在库函数文件中定义的符号常量 |
(C)文本文件和二进制文件都可以用EOF作为文件结束标志 |
(D)对于文本文件,fgetc函数读入最后一个字符时,返回值是EOF |
【解析】以EOF作为文件结束标志的文件,必须是文本文件。符号常量是指,采用宏定义将有含义的字符或字符串用数字代替,例如将chang、kuan用宏定义的形式在程序中替换成数字。fgetc只有遇到文件结束或错误时,才会返回EOF.
【答案】(B)
12.以下关于字符串的叙述中正确的是( )。
(A)空串比空格打头的字符串小 |
(B)两个字符串中的字符个数相同时才能进行字符串大小的比较 |
(C)可以用关系运算符对字符串的大小进行比较 |
(D)C语言中有字符串类型的常量和变量 |
【解析】C语言中只有字符串常量没有变量。空串表示字符数为0的串。
【答案】(A)
7.以下叙述中错误的是( )。
(A)C程序对预处理命令行的处理是在程序执行的过程中进行的 |
(B)预处理命令行的最后不能以分号表示结束 |
(C)#define MAX 是合法的宏定义命令行 |
(D)在程序中凡是以“#”开始的语句行都是预处理命令行 |
【解析】程序的执行一定是发生在链接后,以二进制的形式在计算机内部进行。而预处理发生在更早的编译前。
【答案】(A)
10.以下叙述中正确的是( )。
(A)C语言中的关键字不能作变量名,但可以作为函数名 |
(B)C标识符的长度不能任意长,最多只能包含16个字符 |
(C)标识符总是由字母、数字和下划线组成,且第一个字符不得为数字 |
(D)用户自定义的标识符必须“见名知意”,如果随意定义,则会出现编译错误 |
【解析】C语言中的关键字既不能作变量名,也不能作用户函数名。C语言中没有最大长度的限制。
【答案】(C)
11.已知大写字母“A”的ASCII码值是65,小写字母“a”的ASCII码值是97。以下不能将变量c中的大写字母转换为对应小写字母的语句是( )。
(A)c=('A'+c)%26-'a' |
(B)c=c+32 | (C)c=c-'A'+'a' | (D)c=(c-'A')%26+'a' |
【解析】小写字母比对应的大写字母的ASCII码值大32。已知变量c中的字母是大写,那么就需要将c中的字符+32就能得到对应小写字母,(B)和(C)正确。变量c中已知是大写字母,其ASCII码值。因为c-'A'的ASCII码差值不会大于26(26个字母),除以26无法整除,得到的余数就是差值,即取余数与否没有影响。
【答案】(A)
6.在C语言中,只有在使用时才占用内存单元的变量,其存储类型是( )。
(A)auto和static |
(B)extern和register |
(C)auto和register |
(D)static和register |
【答案】(C)
13.以下叙述中正确的是( )。
(A)如果函数带有参数,就不能调用自己 |
(B)所有函数均不能接受函数名作为实参传入 |
(C)函数体中的语句不能出现对自己的调用 |
(D)函数名代表该函数的入口地址 |
【解析】
【答案】(D)
16.以下叙述中错误的是( )
(A)可以给指针变量赋一个整数作为地址值 |
(B)函数可以返回地址值 |
(C)改变函数形参的值,不会改变对应实参的值 |
(D)当在程序的开头包含头文件stdio.h时,可以给指针变量赋NULL |
【解析】直接将一个整数赋给指针会报错,因为这个整数可能不是合法地址。函数的返回值可以是地址,即指针。
【答案】(A)
17.一下叙述中错误的是( )
(A)形参可以是常量、变量或表达式 |
(B)实参可以是常量、变量或表达式 |
(C)实参的类型应该与形参的类型赋值兼容 |
(D)实参的个数应与形参的个数一致 |
【解析】函数中,形参必须是变量。
【答案】(A)
18.若函数调用时的实参为变量时,以下关于函数形参和实参的叙述中正确的是( )
(A)函数的形参和实参分别占用不同的存储单元 |
(B)形参只是形式上的存在,不占用具体存储单元 |
(C)同名的实参和形参占同一存储单元 |
(D)函数的实参和其对应的形参共占同一存储单元 |
【解析】定义函数时,系统并不给形参分配存储单元。形参在函数调用时,暂时给它分配存储单元,以便存储传来的实参,在函数结束运行后,立马释放相应存储单元。
【答案】(A)
12.以下叙述中正确的是( )。
(A)结构体类型中各个成分的类型必须是一致 |
(B)结构体类型中的成分只能是C语言中预先定义的基本数据类型 |
(C)在定义结构体类型时,编译程序就为它分配了内存空间 |
(D)一个结构体类型可以由多个称为成员(或域)的成分组成 |
【解析】
【答案】(D)
结构体是一种数据类型,与系统提供的标准类型(如int、char、float、doule等)具有同等地位,只是结构体类型需要用户自己指定。
结构体类型说明就是指定结构体变量其内部形式是什么样的,由哪些数据类型组成,一般形式:
struct 结构体名
{ 数据类型1 结构成员名表1;
数据类型2 结构成员名表2;
…
数据类型n 结构成员名表n;
};
(1)结构体说明必须以“;”结尾!
(2)编译程序不会为数据类型分配存储空间,同样,结构体类型说明只是列出了该结构体的组成情况,编译程序并没有因此而分配任何存储空间。
定义链表结点结构的一般形式:
struct 结构体名
{
结构成员表
struct 结构体名 *指针变量名;
};
在定义指针变量时,“struct 结构体名”只是在说明指针变量的基类型,并不是表示指针的数据类型,“*”才是指明后面变量的数据类型是指针。
1.以下叙述中正确的是( )
(A)结构体变量中的成员可以是简单变量、数组或指针变量 |
(B)不同结构体的成员名不能相同 |
(C)结构体定义时,其成员的数据类型可以是本结构体类型 |
(D)结构体定义时,类型不同的成员项之间可以用逗号隔开 |
【答案】(A)
实型常量在C语言中又称浮点数,浮点数均为有符号浮点数。其值有两种表达形式,分别为十进制小数形式和指数形式。指数形式为:
十进制数(尾数) 阶码标识“e”或“E” 阶码(必须为数字且只能为整数,可以带符号)
阶码的表示必须为整数。
1.以下选项中不合法的标识符是( )。
(A)&a |
(B)FOR | (C)print | (D)_00 |
【解析】标识符就是一个名称,用来表示常量、变量、函数以及文件等名称。合法的标识符由字母(C语言中区分大小写)、数字和下划线组成, 并且必须以字母或下划线开头。另外,任何编程中,关键字不能作为标识符。“for”表示一个循环语句,是关键字,但是C语言中区分大小写,所以“FOR”可以作为标识符。
【答案】(A)
2.以下选项中不合法的标识符是( )。
(A)&a |
(B)FOR | (C)print | (D)_00 |
【答案】(A)
3.以下选项中能表示合法常量的是( )。
(A)1,200 |
(B)1.5E2.0 | (C)'\' | (D)"\007" |
【解析】转义字符要用单引号。
【答案】(C)
4.以下选项中可用作C程序合法实数的是( )。
(A)3.0e0.2 |
(B)1e0 | (C)E9 | (D)9.12E |
【解析】E9(阶码标志E之前无数字)和2.7E(无阶码)是不合法的实型数据。
【答案】(B)
5.以下选项中不能作为C语言合法常量的是( )。
(A)0.1e+6 |
(B)'cd' | (C)"\a" | (D)'011' |
【答案】(B)
6.C源程序中不能表示的数制是( )。
(A)十六进制 |
(B)八进制 | (C)十进制 | (D)二进制 |
【解析】程序中是根据前缀来区分各种进制数的,十进制整型常量没有前缀,八进制整型常量以0为前缀,十六进制整型常量以0X或0x作为前缀。
【答案】(D)
7.以下选项中,能用作数据常量的是( )。
(A)115L |
(B)0118 | (C)1.5e1.5 | (D)o115 |
【解析】0118表示八进制,但是不能含有8。
【答案】(D)
8.有以下定义语句,编译时会出现编译错误的是( )。
(A)char a='\x2d'; |
(B)char a='\n'; | (C)char a='a'; | (D)char a="aa"; |
【解析】字符串不能给字符变量,注意变量定义的是字符变量还是数组。
【答案】(D)
9.一下选项中,能正确进行字符串赋值的是( )。
(A)char *s="ABCDE"; |
(B)char s[5]={'A','B','C','D','E'}; |
(C)char s[4][5]={"ABCDEF"}; |
(D)char *s; gets(s); |
【解析】主要题干要求是进行字符串赋值
【答案】(A)
10.若变量已正确定义,在if(W)printf("%d\n", k);中,以下不可替代W的是( )。
(A)a<>b+c |
(B)ch=getchar() | (C)a==b+c | (D)a++ |
【解析】C语言中没有<>运算符
【答案】(A)
11.若由代数式子( )。
(A)sqrt(fabs(pow(n,x)+exp(x))) |
(B)sqrt(fabs(pow(n,x)+pow(x,e))) |
(C)sqrt(abs(n^x+e^x)) |
(D)sqrt(fabs(pow(x,n)+exp(x))) |
【答案】(A)
12.若有定义:double a=22;int i=0,k=18;,则不符合C语言规定的赋值语句是( )。
(A)i=(a + k)<=(i + k); |
(B)i = a%11; | (C)a = a++,i++; | (D)i = !a; |
【解析】模运算的对象必须为整型,否则会报错。
【答案】(B)
13.与数学表达式对应的C语言表达式是( )。
(A)(x >= y)||(y >= x) |
(B)(x >= y >= z) |
(C)(x >= y)! (y >= z) |
(D)(x >= y)&&(y >=z) |
【解析】选项B的程序执行过程是先将x >= y判断表达式的值,然后将表达式的值与z比较,看是否成立,并不能体现的关系。y小于等于x的同时,也大于等于z,应该用一个逻辑与的关系是衔接。
【答案】(B)
字符形式 | 功能 | 十进制ASCII码值 |
---|---|---|
\n | 换行 | 10 |
\t | 水平制表 (下一个Tab键的位置) |
|
\4 | ♦ | |
%% | 输出字符“%” | |
\\ | 反斜线\ | |
\' | 单引号' | |
\" | 双引号" | |
\ddd | 通过3位八进制来表示ASCII码值 | |
\xhh | 通过2位16进制数字代表1个ASCII码字符 |
1.以下叙述错误的是( )
(A)\与任何一个小写字母组合都可成为转义字符 |
(B)\与一位八进制数字组合可成为转义字符 |
(C)\x与一位十六进制数字组合可成为转义字符 |
(D)不能用\与十进制数88结合形成转义字符 |
【解析】
【答案】(A)
2.若有定义语句:
char a='\82';
(A)说明不合法 |
(B)包含1个字符 | (C)包含2个字符 | (D)包含3个字符 |
【解析】首先不是十六进制,没有“x”,那智能是八进制了,而八进制不能有“8”。
【答案】(A)
3.以下能正确定义字符串的语句是( )。
(A)char str="\x43"; |
(B)char str[]="\0"; | (C)char str=' '; | (D)char str[]={'\064'}; |
【解析】定义的是字符串,首先肯定的是双引号之正确,排除(C)、(D)。由于是字符串,不能使用字符变量,只能使用字符数组。
【答案】(B)
3.以下合法的字符常量是( )
(A)'\x6D' |
(B)'\0x41' | (C)'X51' | (D)'\068' |
【解析】想用十六进制表示转义字符,不需要使用“0x”,且正确的表示中“x”是小写。
【答案】(A)
4.有以下程序
#include
main()
{
int a=2,c=5;
printf("a=%%d,b=%%d\n",a,c);
}
程序的输出结果是( )。
(A)a=2,b=5 |
(B)a=%2,b=%5 | (C)a=%d,b=%d | (D)a=%%d,b=%%d |
【答案】(C)
3.若有定义语句:
char a='\82';
则变量a( )。
(A)说明不合法 |
(B)包含1个字符 | (C)包含2个字符 | (D)包含3个字符 |
【答案】(A)
强制类型转换的一般形式:
(类型说明符)(表达式)
需转换的表达式如果不是单个变量,则要用括号将其括起来。
1.若有以下程序段:
double x = 5.16894;
printf("%f\n", (int)(x*1000+0.5)/(double)1000);
则程序段的输出结果是( )。
(A)5.70000 |
(B)5.175000 | (C)5.169000 | (D)5.168000 |
【答案】(C)
产生随机数——rand()产生一个0~32767之间的随机数。
rand()%x表示产生一个0~x(不包括x)之间的随机数。
1.设有以下程序段:
int y;
y=rand()%30+1;
则变量y的取值范围是( )。
(A)0≤y≤30 |
(B)0<y≤30 | (C)1<y<30 | (D)1<y≤30 |
【解析】有点脑经急转弯,y的取值范围应该是1≤y≤30,答案只有不取0的(B)
【答案】(B)
C语言没有提供输入输出语句,数据的输入和输出是通过调用输入输出函数实现的。在VC环境下,如果要使用输入输出函数,应首先用编译预处理命令“#include”将头文件“stdio.h”包含到源文件中。
#include
"stdio.h"是input&output的缩写,它包含了与标准I/O库有关的变量定义和宏定义。考虑到printf函数和scanf函数的使用比较频繁,系统允许在使用这两个函数时可不加“#include”命令。
scanf函数的作用是从输入设备(键盘或系统隐含指定的输入设备)输入若干个任意类型的数据。scanf函数的调用格式如下:
scanf(格式控制串, 地址表列)
格式控制串用来指定每个输入项的输入格式。格式控制串通常是由若干个格式说明组成的,格式说明由“%”开头,后跟格式字符。地址表列需要读入的是所有变量的地址或字符串的首地址,而不是变量本身。
scanf("%d %x %c", &a,&b)
格式字符 | 说明 |
d | |
c | 输入单个字符,空格字符和转义字符都将作为有效字符输入 |
f | 输入实数,可以用小数形式或指数形式输入 |
s | 输入字符串 |
scanf函数的格式控制串由以下组成:
% + 附加格式字符 + 格式字符
附加格式字符 | 说明 |
---|---|
l | 用来输入长整型数据(可用%ld,%lo,%lx,%lu)以及double型数据(用%lf或%le) |
域宽 | 指定输入数据所占宽度(列数),域宽应为正整数 |
!!!使用时注意!!!:
(1)格式控制串内没有其他符号区分输入数据
当格式字符为“%c”时,键盘按的空格和所有的转义字符都将作为一个字符输入,这时表示一个字符输入结束应该用回车键;
输入数值数据时,输入的数值数据之间用间隔符(空格符、制表符或回车符)隔开,间隔符数量不限。
输入数据与函数要求个数不同时:(1)输入数据多于scanf函数要求个数,多于的数据将留在缓冲区作为下次输入操作的输入数据;
数据输入结束的三种情况:(1)遇到空格、回车或制表键;
(2)按指定宽度结束;
(3)遇到非法输入。
1.若有定义
int a;
float b;
double c;
程序运行时输入:
3 4 5<回车>
能把值3输入给变量a、4输入给变量b、5输入给变量c的语句是( )。
(A)scanf("%d%f%lf", &a,&b,&c); |
(B)scanf("%d%lf%lf", &a,&b,&c); |
(C)scanf("%d%f%f", &a,&b,&c); |
(D)scanf("%lf%lf%lf", &a,&b,&c); |
【答案】(A)
2.设有定义:double x;,以下选项中不能将输入数据3.14读入赋给变量x的是( )
(A)scanf("%4.2f",&x); |
(B)scanf("%lf",&x); | (C)scanf("le",&x); | (D)scanf("%4lf",&x); |
【解析】
【答案】(A)
3.若有定义语句:double x,y,*px,*py;执行了px=&x; py=&y; 之后,正确的输入语句是( )
(A)scanf("%lf %le", px,py); |
(B)scanf("%f %f" &x, &y); |
(C)scanf("%f %f", x, y); |
(D)scanf("%lf %lf", x, y); |
【解析】先不着急想格式,先看语法有无错误
【答案】(A)
6.有以下程序段:
#include
int j; float y; char name[50];
scanf("%2d%3f%s", &j, &y, name);
当执行上述程序段,从键盘上输入55566 7777abc后,y的值为( )。
(A)566.0 |
(B)55566.0 | (C)7777.0 | (D)566777.0 |
【答案】(A)
7.有以下程序段:
char name[20];
int num;
scanf("name=%s num=%d",name,&num);
当执行上述程序段,并从键盘输入:
name=Lili num=1001<回车>后,name的值为( )。
(A)name=Lili num=1001 |
(B)name=Lili |
(C)Lili num= |
(D)Lili |
【解析】这是输入字符串中空格与scanf控制串中空格判定的问题,结论:系统会优先将空格作为控制字符串的格式。
【答案】(D)
8.有以下程序:
#include
main()
{
int a1, a2; char c1, c2;
scanf("%d%c%d%c", &a1, &c1, &a2, &c2);
printf("%d,%c,%d,%c",a1,c1,a2,c2);
}
若想通过键盘输入,使得a1的值为12,a2的值为34,c1的值为字符a,c2的值为字符b,程序输出结果是:12,a,34,b 则正确的输入格式是(以下口带代表空格,
(A)12口a34口b |
(B)12口a口34口b |
(C)12,a,34,b |
(D)12a34b |
【解析】在输入多个数据时,若格式控制串中无非格式字符,则认为所有输入的字符均为有效字符。可不可以这样理解,第一个数入数据是数值,在输入缓冲区中“a”处就会结束第一个%d的数据输入,依次类推。
【答案】(D)
9.有以下程序:
#include
main()
{ char a, b, c, d;
scanf("%c%c", &a, &b);
c = getchar();
d = getchar();
printf("%c%c%c%c\n", a, b, c, d);
}
当执行程序时,按下列方式输入数据(从第1列开始,
12
34
则输出结果是( )。
(A) 12 34 |
(B) 12 |
(C) 1234 |
(D) 12 3 |
【解析】scanf函数格式字符为“%c”,每次将单个字符作为数据赋值给变量,指定的宽度就是2个字符。“1”“2”分别以字符数据赋值给a和b,输入数据满足的scanf函数的宽度要求,自动结束。由于还在输入数据,“
【答案】(D)
10.若有定义char c;int d;,程序运行时输入1、2和<回车>,能把值1输入给变量c,值2输入给变量d的输入语句是( )。
(A)scanf(%c,%d,&c,&d); |
(B)scanf(%c%d,&c,&d); |
(C)scanf(%d,%f,&c,&d); |
(D)scanf(%d%d,&c,&d); |
【解析】两个格式说明之间有一个",",则从键盘输入时,输入变量之间也应按照原样输入逗号。
【答案】(A)
11.若有定义和语句:
int a,b;
scanf("%d,%d",&a,&b);
以下选项中的输入数据,不能把值3赋给变量a、5赋给变量b的是( )。
(A)3,5,4 |
(B)3,5 | (C)3,5, | (D)3 ,5 |
【解析】3和5之间必须输入逗号,不能有其他符号。(B)选项最后肯定是个回车
【答案】(D)
printf函数的调用格式如下:
printf(格式控制串,输出表列)
printf("%d %x", a,b)
组成格式控制串的字符通常由格式说明、转义字符和按原样输出的字符3部分组成。转义字符以“\”开始,用来实现换行、跨越制表位或输出单引号、双引号等特殊字符,如"\n"实现回车换行。除以上两类字符之外,在格式串中的其他字符将按照原样输出,用来在输出结果中增加其他信息。
printf函数中格式控制的一般形式如下:
%附加格式字符 格式字符
格式字符 | 说明 |
d,i(十进制用D) | 以带符号的十进制形式输出整数(正数不输出符号) |
o | 以无符号八进制形式输出整数(不输出前导符0) |
x,X | 以无符号十六进制输出整数(不输出前导符0x) |
s | 输出字符串 当输出字符指针ps指向的字符串时,其格式为printf("%s",ps),无需添加“*” |
c(char) | 以字符形式输出,只输出一个字符 |
f | 以小数形式输出单、双精度数,隐含输出6位小数 |
在格式控制串中,还可以在%和格式符之间插入几种附加符号,用来进一步说明输出的格式。
附加格式字符 | 说明 |
字母l | 用于表示长整型整数,可加在格式符d,o,x,u前面 |
m(代表一个正整数) | 数据最小宽度 |
n(代表一个正整数) | 如果是实数,表示输出n位小数;如果是字符串,表示截取的字符个数 |
(2)输出宽度
在%和格式符之间插入一个整数用来指定输出的宽度
1)为整数指定宽度
如果指定的宽度多于数据实际宽度,则输出的数据右对齐,左端用空格补足;而当指定的宽度不足时,则按实际数据位数输出,这时指定的宽度不起作用。
2)为实数指定输出宽度
对于float或double型数据,在指定数据输出宽度的同时,也可以指定小数位的位数,指定形式如下:
%m.nf
表示数据输出总的宽度为m位,其中小数部分占n位。当数据的小数位多于指定宽度n时,截去右边多余的小数,并对截去的第一位小数做四舍五入处理;而当数据的小数位少于指定宽度n时,在小数的右边补零。
1.有以下程序
#include
main()
{
int k=33;
printf("%d,%o,%x\n",k,k,k);
}
程序的运行结果是( )。
(A)33,41,21 |
(B)33,33,33 | (C)41,33,21 | (D)33,21,41 |
【解析】八进制是3位二进制!!长点脑子吧,SB
【答案】(A)
2.设有定义:double x=5.1012;,若要求只输出x的整数部分,以下不能实现此要求的语句是( )
(A)printf("x=%2d\n",x); |
(B)printf("x=%2.0f\n",x); |
(C)printf("x=%.0f\n",x); |
(D)printf("x=%1.0lf\n",x); |
【解析】首先x是double型,用%d输出就不对。
【答案】(A)
3.设有定义语句:
double x=123.456
则语句
printf("%6.2f,%3.0f\n",x,x);
(A)123.46,123.0 |
(B)123.45,123 | (C)123.46,123 | (D)123.45,123. |
【解析】小数点0位时,输出结果没有小数点符号
【答案】(C)
5.有以下程序:
#include
main()
{
int x[3][2]={0}, i;
for(i=0;i<3;i++)scanf("%d", x[i]);
printf("%3d%3d%3d\n", x[0][0],x[0][1],x[1][0]);
}
若运行时输入:2 4 6<回车>,则输出结果为( )
(A)2 0 4 |
(B)2 0 0 | (C)2 4 0 | (D)2 4 6 |
【答案】 (A)
6.设有语句:printf("%2d\n,2010");,则以下叙述正确的是( )
(A)程序运行时输出2010 |
(B)程序运行时输出20 |
(C)程序运行时输出10 |
(D)指定的输出宽度不够,编译出错 |
【答案】(A)
strlen(数组首地址),不包括字符串结束标识符“\0”,string length的缩写。
gets(字符串数组首地址) 函数的功能是从输入缓冲区上读取一个字符串(可以包含空格),并将其存储到字符数组中。该函数的读取结束标识符是换行符,并且换行符'\n'不能作为字符串的内容存储,系统会自动用“\0”来代替。由于读取的字符串长度没有限制,需要保证字符数组有足够打的空间存放输入的字符串。
1.有以下程序:
#include
void fun(char *c)
{
while(*c)
{
if(*c>='a'&&*c<='z')
*c=*c-('a'-'A');
c++;
}
}
main()
{
char s[81];
gets(s);
fun(s);
puts(s);
}
当执行程序时从键盘上输入Hello Beijing<回车>,则程序的输出结果是( )。
(A)hello beijing |
(B)Hello Beijing |
(C)HELLO BEIJING |
(D)hELLO Beijing |
【答案】(C)
2.若有以下程序
#include
main()
{ char a[20], b[]="The sky is blue."; int i;
for(i=0;i<7;i++) scanf("%c",&b[i]);
gets(a);
printf("%s%s\n", a, b);
}
执行时若输入:(其中
Fig flower is red.
则输出结果是( )。
(A)wer is red.Fig flo is blue. |
(B)wer is red.Fig flo |
(C)wer is red.The sky is blue. |
(D)Fig flower is red.The sky is blue. |
【解析】重点记住gets()会用‘\0’替换回车“\n”
【答案】(A)
strcpy(字符数组,字符串),将“字符串”连同结束标识符一起复制给字符数组,“字符串”可以是字符串常量也可以是字符数组。
1.有以下程序(strcpy为字符串复制函数,strcat为字符串连接函数)
#include
#include
main()
{
char a[10]="abc", b[10]="012",c[10]="xyz";
strcpy(a+1,b+2);
puts(strcat(a,c+1));
}
程序运行后的输出结果是( )。
(A)a12xyz |
(B)bc2yz | (C)a2yz | (D)12yz |
strcmp(char *str1,char *str2),比较字符串str1和str2是否相同,从第一个字符开始按ASCII码大小进行比较,如果相同继续比较,直到不同或者字符串结束标识符“\0”为止。如果最后结果相同,返回0,不同,str1大于str2返回1,相反返回-1。
> | = | < |
1 | 0 | -1 |
1.若有定义语句:
char *s1="OK",*s2="ok";
以下选项中,能够输出“OK”的语句是( )。
(A)if(strcmp(s1,s2)!=0) puts(s2); |
(B)if(strcmp(s1,s2)!=0) puts(s1); |
(C)if(strcmp(s1,s2)==1) puts(s1); |
(D)if(strcmp(s1,s2)==0) puts(s1); |
【答案】(B)
strcat(字符数组,字符串),把“字符串”连接到“字符数组”中的字符串尾端,并存储于“字符数组”中,其中结束标识符将被“字符串”第一个字覆盖。Strings Catenate的缩写。
1.有以下程序(strcat函数用以连接两个字符串):
#include
#include
main()
{
char a[20]="ABCD\0EFG\0",b[]="IJK";
strcat(a,b);
printf("%s\n",a);
}
程序运行后的输出结果是( )。
(A)IJK |
(B)ABCDE\0FG\0IJK | (C)ABCDIJK | (D)EFGIJK |
【解析】当字符串中有多个“\0”时,对应函数操作以第一个“\0”为标准。
【答案】(C)
2.有以下程序
#include
#include
main()
{
char p[20]={'a','b','c','d'},q[]="abc",r[]="abcde";
strcat(p,r);
strcpy(p+strlen(q),q);
printf("%d\n",strlen(p));
}
程序运行后的输出结果是( )
(A)11 |
(B)9 | (C)6 | (D)7 |
【解析】计算strlen时,是从第一元素开始数,直到“\0”,后续有元素也不计算。
【答案】(C)
switch(表达式)
{ case 常量表达式1: 语句1;
case 常量表达式2: 语句2;
...
case 常量表达式n: 语句n;
default: 语句n+1;
}
执行过程:(1)计算表达式的值,用该值逐个与常量表达式的值比较,匹配时,执行该case的语句;没有匹配的值,执行default语句。
(2)执行完case语句后,直接执行下一个case语句,不再进行判断,为避免这种情况,通常在case语句后加break语句,跳出switch语句。
switch后面表达式的取值必须是整型或字符型,case后面必须是常量或常量表达式,且常量表达式的类型必须与switch后的表达式类型相同。
1.关于while(条件表达式)循环体,以下叙述中正确的是( )。
(A)循环体的执行次数总是比条件表达式的执行次数多一次 |
(B)条件表达式的执行次数总是比循环体的执行次数多一次 |
(C)条件表达式的执行次数与循环体的执行次数一样 |
(D)条件表达式的执行次数与循环体的执行次数无关。 |
【答案】(B)
2.若以下选项中的变量a,b,y均已正确定义并赋值,则语法正确的switch语句是( )。
(A)switch(a*a+b*b) { default : break; case 3 : y=a+b; break; case 2 : y=a-b; break; } |
(B)switch( a+b ) { case 1 : case3: y=a+b; break; case0 : case4 : y=a-b;} |
(C)switch(a+9) { case a : y=a-b; case b : y=a+b;} |
(D)switch a*b { case 10 : y=a+b; default : y=a-b; } |
【解析】(B)选项中case与数字之间没有分隔。(C)选项中,case a和case b不正确,case后面应该跟常量表达式。
【答案】(A)
1.以下程序段中的变量已正确定义:
for(i=0;i<4;i++,i++)
for(k=1;k<3;k++);
printf("*");
程序运行后的输出结果是( )。
(A)** |
(B)**** | (C)* | (D)******** |
【解析】主要是确定第一层for循环在哪儿,第二层for循环在哪儿。但这种表达容易有歧义,硬背答案吧。
【答案】(C)
2.有以下程序:
#include
main()
{
int a[4][4]={{1,4,3,2},
{8,6,5,7},
{3,7,2,5},
{4,8,6,1}};
int i,j,k,t;
for(i=0;i<4;i++)
for(j=0;j<3;j++)
for(k=j+1;k<4;k++)
if(a[j][i]>a[k][i])
{
t=a[j][i];a[j][i]=a[k][i];a[k][i]=t;
}/*按列排序*/
for(i=0;i<4;i++)
printf("%d,",a[i][i]);
}
程序运行后的输出结果是( )。
(A)1,6,2,1, |
(B)8,7,3,1 | (C)4,7,5,2, | (D)1,6,5,7, |
【解析】还是看不出每个循环结束的位置
【答案】(D)
1.有以下程序
#include
main()
{ int y = 10;
while(y--);printf("y = %d\n",y);
}
程序执行后的输出结果是( )。
(A)y = 0 |
(B)y = -1 | (C)y = 1 | (D)while构成无限循环 |
【解析】while后有个“;”,所以while循环体是个空语句。执行过程:表达式执行,y=10为真,y=9,循环体,……,y=1,循环体,y=1为真,y=0,循环体,y=0为假,y=-1,printf。
【答案】(B)
1.关于:do 循环体 while(条件表达式);
以下叙述中正确的是( )
(A)条件表达式的执行次数总是比循环体的执行次数多一次 |
(B)循环体的执行次数总是比条件表达式的执行次数多一次 |
(C)条件表达式的执行次数与循环体的执行次数一样 |
(D)条件表达式的执行次数与循环体的执行次数无关。 |
【解析】如果循环体里有break语句,遇到break会跳出整个循环而不执行条件表达式,所以条件表达式的执行次数与循环体的执行次数无关。
【答案】( )
2.关于:do 循环体 while(条件表达式);
以下叙述中正确的是( )
(A)条件表达式的执行次数总是比循环体的执行次数多一次 |
(B)循环体的执行次数总是比条件表达式的执行次数多一次 |
(C)条件表达式的执行次数与循环体的执行次数一样 |
(D)条件表达式的执行次数与循环体的执行次数无关。 |
【解析】do…while循环的执行过程是先执行一遍循环体后再执行条件表达式判断条件,直到条件不成立跳出循环,所以循环体的执行次数和条件表达式的执行次数是一致的。
【答案】( )
总结:解析都是来自未来教育,同一道题,却出现两种不同的解释,只能说尽信书,不如无书。
3.以下不构成无限循环的语句或语句组是( )。
(A)n=0; do{++n;} while(n<=0); |
(B)n=0; while(1){n++;} |
(C)while(n);{n--;} |
(D)for(n = 0,i = 1;;i++)n+=i; |
【解析】(C)中的循环体是个空语句,循环表达式在第一个分号处就结束了。(D)中的第一个分号前都是表达式1,而表达式2为空,没有判断条件,也是死循环。
【答案】(A)
3.若变量已正确定义,有以下程序段:
i = 0;
do printf("%d,",i);while(i++);
printf("%d\n",i);
其输出结果是( )。
(A)0,1 |
(B)0,0 | (C)1,1 | (D)程序进入无限循环 |
【解析】VC中会将do和while之间的语句全部当成循环体,所以不用区分“while”前面那个分号的归属。此外,do...while和while循环都是条件为真时继续循环。
【答案】(A)
指针数组是数组,每一个元素是指针变量,定义格式:
数据类型* 数组名[元素个数];
“数据类型”指明了这个数组中指针变量的基类型
等价于
(数据类型*) 数组名[元素个数]
数组指针是指向数组的指针,不仅能指向一维数组,还有二维数组,定义格式:
数据类型 (*指针变量)[元素个数]
这种定义形式表示,指针变量指向包含n个元素个数的数组
1.有以下程序
#include
main()
{
int a[3][3]={0,1,2,3,4,5,6,7,8},(*p)[3],i;
p=a;
for(i=0;i<3;i++)
{
printf("%d",(*p)[i]);
p++;
}
}
程序的运行结果是( )
【解析】定义了一个指针p,p能指向包含3个元素的数组。首先二维数组名”a“这种形式,有3种含义,一是标识符;二是二维数组的首地址;三是表示二维数组的第一个元素,即行指针。将a的地址赋值给p,p就指向了二维数组的第一个元素{0,1,2},然后在for循环中,”*p“表示p的内容,也就是{0,1,2}。由于(*p)这个整体表示的是一个行指针,在后面追加“[0]”表示其中的第一个元素。
【答案】(C)
2.在32位编译器上,设有定义
char *str1="Hello",str2[]="Hello";
则以下语句
printf("%d %d",sizeof(str1),sizeof(str2));
的输出结果是( )。
(A)5 6 |
(B)5 5 | (C)6 6 | (D)4 6 |
【解析】指针变量表述的是地址,而地址与系统的位数有关,在32位的编译器上,地址也是32位,就是4字节,所以指针变量就是4字节。VC就是32位的编译器。
【答案】(D)
3.若有以下程度段
char str[4][12]={"aa","bbb","ccccc","d"},*strp[4];
int i;
for(i=0; i<4; i++) strp[i]=str[i];
不能正确引用字符串的选项是( )。
(A)str[0] |
(B)strp | (C)strp[3] | (D)*strp |
【解析】strp数组中每一个元素都是指针,数组名strp代表第一个指针的地址,所以它属于二级地址。除了(B)选项,每一个选项的值都是字符串的首地址。
【答案】(B)
4.有以下程序段
char str[4][12]={"aaa","bbb","ccc",""ddd"}, *p[4];
int i;
for(i=0; i<4; i++)
p[i]=str[i];
(A)*p[3] |
(B)p[3] | (C)str[2] | (D)*p |
【解析】指针数组里的每个元素都是指针,而指针存放的都是字符串的首地址,(A)选项取内容符号取的是首地址的内容,也就是字符。
【答案】(A)
5.若有定义:
int w[3][5];
则以下不能正确表示该数组元素的表达式是( )。
(A)*(&w[0][0]+1) |
(B)*(*w+3) | (C)*(*(w+1)) | (D)*(w+1)[4] |
【解析】(A)选项&w[0][0]+1是取w[0][0]地址再+1。取内容运算符“*”的优先级比“+”高。(B)选项*w等价于w[0],所以*w+3表示w[0][3]的地址。(D)w+1表示行指针移动到第二行,此时[4]表示行指针再原来的基础上继续移动4个单位,但是定义的数组只有3行,(D)错误。
【答案】(D)
5.以下函数实现按每行8个输出w所指数组中的数据
#include
void fun(int *w,int n)
{
int i;
for(I=0;i
(A)if(i/8==0) printf("\n"); |
(B)if(i/8==0) continue; |
(C)if(i%8==0) printf("\n"); |
(D)if(i%8==0) continue; |
【答案】(C)
6.有以下程序
#include
void fun(char **p)
{
++p;
printf("%s\n",*p);
}
main()
{
char *a[]={"Morning","Afternoon","Evening","Night"};
fun(a);
}
程序的运行结果是( )。
(A)Afternoon |
(B)fternoon |
(C)Morning |
(D)orning |
【解析】指针数组的每个元素a[0]、a[1]…是指针,a也表示这个数组的首地址,指向的是a[0],而a[0]又是指针,当一维数组名a(首地址)作为实参传递给函数形参时,对应的形参应是指针,而a[0]又是指针,函数的形参就应该是指向指针的指针。二级指针p指向一个指针变量,这个指针变量指向的是一个char型变量,这是定义的部分。引用时,又不同,++p后,p存的是a[1]的地址(不是a[1],而是它的地址),*p就是取出a[1]这个元素(指针),再配合printf()的“%s”和字符指针特有的操作得到输出结果。
【答案】(A)
若参数为大写字母则将该对应的小写字母返回,若不是,返回原参数。
若参数为小写字母则将该对应的大写字母返回,若不是,返回原参数。
1.有以下程序,程序中库函数islower(ch)用以判断ch中的字母是否为小写字母:
#include
#include
void fun(char *p){
int i=0;
while(p[i])
{
if(p[i]==' '&&islower(p[i-1]))
p[i-1]=p[i-1]-'a'+'A';
i++;
}
}
main()
{
char s1[100]="ab cd EFG !";
fun(s1);
printf("%s\n",s1);
}
程序运行后的输出结果是( )。
(A)ab cd EFg ! |
(B)Ab Cd EFg! |
(C)ab cd EFG ! |
(D)aB cD EFG! |
【解析】i=0时,p[i-1]没有越下界的问题,因为短路,if语句内的表达式不会执行,直接跳i++。
【答案】(D)
用来检测一个字符是否是空白符,是,返回非0。一个字符是否是空白符和程序的语言环境有关,在默认情况下,空白符包括:
字符 | ASCII码 (十六进制) | 说明 (缩写) |
---|---|---|
' ' | 0x20 | 空格 (SPC) |
'\t' | 0x09 | 水平制表符 (TAB) |
'\n' | 0x0a | 换行符 (LF) |
'\v' | 0x0b | 垂直制表符 (VT) |
'\f' | 0x0c | 换页 (FF) |
'\r' | 0x0d | 回车 (CR) |
检查所传的字符是否是十进制数字字符,是,返回非0。
2.有以下程序:
#include
void fun(int *a,int *b)
{ int *c;
c=a;a=b;b=c;
}
main()
{
int x=3,y=5,*p=&x,*q=&y;
fun(p,q);printf("%d,%d,",*p,*q);
fun(&x,&y);printf("%d,%d\n",*p,*q);
}
程序运行后的输出结果是( )。
(A)3,5,3,5 |
(B)3,5,5,3 | (C)5,3,3,5 | (D)5,3,5,3 |
【解析】fun函数的功能是指针变量a、b的值,但并不能交换实参的值。p、q的值分别是x、y的地址,交换后仅仅只是形参交换,p和q的值并未改变;x、y的地址给到a、b同样也是交换形参,不改变实参的值。如果函数的形参是地址,形参是指针,函数内部对于指针的交换同样不会影响到主函数中指针的指向。
【答案】(A)
2.若有以下程序
#include
int k=7;
void f(int **s)
{int *t=&k;
*s=t;
printf("%d,%d,%d,",k,*t,**s);
}
main()
{ int i=3,*p=&i,**r=&p;
f(r);
printf("%d,%d,%d\n",i,*p,**r);
}
则程序的输出结果是
(A)3,3,3,7,7,7 |
(B)3,7,7,7,7,7 | (C)7,7,7,3,3,3 | (D)7,7,7,3,7,7 |
【解析】f函数里面对形参的操作都是通过取内容符号“*”,与上一题直接赋值不一样。s(或r)指向p,*s=t既让*s指向了t,由于*s就是p的内容(i的地址),所以也让p指向了k。
【答案】(D)
3.若有以下程序
#include
int *f(int *s,int *t)
{ int *k;
if(*s<*t){ k=s; s=t ;t=k; }
return s;
}
main()
{ int i=3,j=5,*p=&i,*q=&j,*r;
r=f(p,q);
printf("%d,%d,%d,%d,%d\n",i,j,*p,*q,*r);
}
则程序的输出结果是( )。
(A)3,5,5,3,5 |
(B)3,5,3,5,5 | (C)5,3,5,3,5 | (D)5,3,3,5,5 |
【答案】(B)
函数指针
函数名和数组名一样也是一个地址,可以将数组名(地址)赋给数组指针,对应也就有函数指针指向函数的入口地址,函数指针的定义格式:
数据类型(*指针变量名)(形参列表)
“数据类型”指函数的返回类型,“形参列表”指函数指针变量所指向的函数的形参列表
通过函数指针执行函数有2种形式:
f()、(*f)(实参)
void (*f)(void) //定义了一个函数指针变量f,可以存放函数的入口地址,而这个函数的形
//式一定和函数指针定义的形式相同
f = fun; //fun是函数名,将fun函数入口地址给到函数指针f
f(); //直接执行fun函数
(*f)(); //同样也是执行fun函数
指针函数
说明函数返回的是一个指针类型的数据,定义格式:
数据类型* 函数名(参数表)
等价于
(数据类型*)函数名(参数表)
有点类似于将函数的返回值进行强制类型转换
指针函数和函数指针在定义上的区别就是“()”,“()”的优先级>“*”。
1.若有以下说明和定义
int fun(int *c){…}
main()
{
int (*a)(int *)=fun, *b(), x[10],c;
…
}
则对函数fun的正确调用语句是( )。
(A)(*a)(&c); |
(B)a=a(x); | (C)b=*b(x); | (D)fun(b) |
【解析】函数fun接收一个int指针形参,返回int类型。main首先定义函数指针a,并将fun的入口地址赋给a。(B)x是数组的地址,通过a调用不符合fun函数的定义;(C)形式是函数的调用,但在题目中没有给出b函数的定义,也可以说b和fun没有联系;(D)在定义中可以理解b是一个指针函数,因为有int *b(),那么b就不能作为实参传给函数fun。
【答案】(A)
2.设有以下函数:
void fun(int n,char *s)
{……}
则下面对函数指针的定义和赋值均正确的是( )
(A)void (*pf)(int,char); pf=&fun; |
(B)void *pf(); pf=fun; |
(C)void *pf(); *pf=fun; |
(D)void (*pf)(int,char*); pf=fun; |
【解析】函数名才是地址入口,因此赋值时不需要括号。
【答案】(D)
1.以下程序段中,与语句:
k=a>b?(b>c?1:0):0
功能相同的是( )。
(A)if((a>b)||(b>c))k=1; else k=0; |
(B)if((a>b)&&(b>c))k=1; else k=0; |
(C)if(a<=b)k=0; else k=0; |
(D)if(a>b)k=1; else if(b>c)k=1; else k=0; |
【答案】(B)
2.有以下程序:
#include
main()
{ int a = 0,b = 0,c = 0,d = 0;
(++a||++b)? ++c:++d;
printf("%d,%d,%d,%d\n",a,b,c,d);
}
程序的运行结果是( )。
(A)1,01,0 |
(B)1,1,0,1 | (C)1,0,0,1 | (D)1,1,1,0 |
【解析】短路现象:由于++a的值为1,在||运算中,(++a||++b)的值已经为1,将跳过++b求值,程序执行完毕后,b仍为0。
【答案】(A)
3.若有以下程序
#include
main()
{ int a=1,b=2,c=3,d=4;
if((a=2)&&(b=1)) c=2;
if((c==3)||(d=-1)) a=5;
printf("%d,%d,%d,%d\n", a,b,c,d);
}
则程序的输出结果是( )。
(A)2,2,2,4 |
(B)2,1,2,-1 | (C)5,1,2,-1 | (D)1,2,3,4 |
【答案】(C)
7.有以下程序:
#include
main()
{
int a=1,b=2,c=3,x;
x(a^b)&c;
printf("%d\n",x);
}
程序的运行结果是( )。
(A)3 |
(B)1 | (C)2 | (D)0 |
【答案】(A)
1.以下叙述中错误的是( )。
(A)未经赋值的全局变量值不确定 |
(B)未经赋值的auto变量值不确定 |
(C)未经赋值的register变量值不确定 |
(D)未经赋值的静态局部变量值为0 |
【答案】(A)
2.在一个C源程序文件中所定义的全局变量,其作用域为( )。
(A)由具体定义位置和extern说明来决定范围 |
(B)所在程序的全部范围 |
(C)所在函数的全部范围 |
(D)所在文件的全部范围 |
【解析】全局变量也称外部变量,指函数外部任意位置定义的变量,其作用域是从定义变量的位置开始到本源程序文件结束,全局变量不属于任何一个函数,它可以被本源程序文件的其他函数所共用。
【答案】(A)
3.有以下程序:
#include
int a=4;
int f(int n)
{
int t=0;
static int a=5;
if(n%2){int a=6; t+=a++; }
else {int a=7; t+=a++; }
return t+a++;
}
main()
{
int s=a,i=0;
for(;i<2;i++) s+=f(i);
printf("%d\n",s);
}
程序运行后的输出结果是( )。
(A)36 |
(B)24 | (C)32 | (D)28 |
【解析】考虑是不是判断语句int a有个int才导致做不出正确答案。
【答案】(D)
4.若有以下程序
#include
int a=2;
int f(int m)
{ static int n;
n=0; n++; a++;
return n+m+a;
}
main()
{
int k;
for(k=0;k<4;k++)
printf("%d,",f(k));
}
程序运行后的输出结果是( )。
(A)4,5,6,7, |
(B)4,7,10,13, | (C)4,6,8,10 | (D)3,5,7,9, |
【解析】static变量如果定义时没赋初值,那么每次程序运行到定义static变量时都会将它赋值为0。
【答案】(C)
5.有以下程序
#include
int a=1, b=2;
void fun1(int a,int b)
{
printf("%d %d " ,a, b );}
void fun2()
{ a=3; b=4; }
main()
{
fun1(5,6); fun2();
printf("%d %d\n",a, b );
}
程序运行后的输出结果是( )。
(A)5 6 1 2 |
(B)3 4 5 6 | (C)1 2 5 6 | (D)5 6 3 4 |
【解析】在fun2中,没有再定义局部变量a、b,所以全局变量在fun2函数中发挥作用。
【答案】 (D)
总结1:自增(减)发生在该语句执行完以后,“;”代表的就是一条语句。
1.有以下程序
#include
main()
{
int a[5]={2,4,6,8,10},*p,**k;
p=a; k=&p;
printf("%d",*(p++));
printf("%d\n",**k);
}
(A)4 6 |
(B)4 4 | (C)2 2 | (D)2 4 |
【答案】(D)
2.以下不能将s所指字符串正确复制到t所指存储空间的是( )。
(A)do{*t++ = *s++; }while(*s); |
(B)for(i=0; t[i]=s[i]; i++); |
(C)while(*t=*s){t++; s++} |
(D)for(i=0, j=0; t[i++]=s[j++];); |
【解析】取内容运算符“*”优先级<自增运算符,但由于自增运算要在该语句运行完之后再执行,因此,第一步,先将*s指向的内容赋给*t,执行完后t和s都+1,也就是指向的地址+1;第二步,判断*s的内容是不是字符串结束标识符“0”,不是,继续执行循环体,直到结束标识符“0”出现,由于没有结束标识符,t所指向的字符串不完整。
【答案】(A)
3.有以下程序
#include
main()
{
int a[]=2,4,6,8},*p=a,i;
for(i=0; i<4; i++)
a[i]=*p++;
printf("%d\n",a[2]);
}
程序运行后的结果是( )。
(A)2 |
(B)8 | (C)4 | (D)6 |
【答案】(D)
4.有以下函数:
int fun(char *s)
{
char *t=s;
while(*t++);
t--;
return(t-s);
}
该函数的功能是( )。
(A)计算s所指字符串的长度 |
(B)比较两个字符串的大小 |
(C)计算s所指字符串占用内存字节的个数 |
(D)将s所指字符串复制到字符串t中 |
【解析】自增运算发生在出了while()语句以后,一开始,t指向第一个字符,取内容运算符发挥作用,判断是否为“0”,判断完毕后,在执行循环体前,t加1。由于循环体为空,找到字符串结束标识符“0”后,由于t指向“0”后一个地址,则需要减1,计算不含有“\0”的字符串长度。
【答案】(A)
5.若有以下程序段
struct st{int n; struct st *next;};
struct st a[3]={5,&a[1],7,&a[2],9,'\0'},*p;
p=&a[0];
则以下选项中值为6的表达式是( )。
(A)p->n |
(B)(*p).n | (C)p->n++ | (D)++(p->n) |
【解析】严格来说,题干有点歧义。(C)和(D)最后都为6,但(C)选项这样理解,加入(C)放在if()语句里,if(p->n++),表达式的值为5,语句执行完后n才为6。
【答案】(D)
9.有以下程序:
#include
void fun2(char a,char b)
{
printf("%c %c",a,b);
}
char a='A',b='B';
void fun1()
{
a='C';b='D';
}
main()
{
fun1();
printf("%c %c ",a,b);
fun2('E','F');
}
程序的运行结果是( )。
(A)A B E F |
(B)C D E F | (C)A B C D | (D)C D A B |
【解析】
【答案】(B)
9.有以下程序
#include
main()
{
int i=5;
do
{
if(i%3==1)
 if(i%5==2)
{printf("*%d",i);break;}
i++;
}while(i!=0);
printf("\n");
}
程序运行的结果是( )。
(A)*2*6 |
(B)*3*5 | (C)*5 | (D)*7 |
【解析】“ ”看成是换行符
【答案】 (D)
10.有以下函数:
int fun(char *x, char*y)
{
int n=0;
while((*x==*y)&&*x!='\0'){x++;y++;n++;}
return n;
}
函数的功能是( )。
(A)将y所指字符串赋给x所指存储空间 |
(B)查找x和y所指字符串中是否有'\0' |
(C)统计x和y所指字符串中最前面连续相同的字符个数 |
(D)统计x和y所指字符串中相同的字符个数 |
【解析】while循环判断式为假,不执行循环体,问题没有意义了。考虑判断式为真,当x指向的内容和y指向的内容不等时,逻辑值为0,短路现象产生,不判断后一个表达式,直接退出循环。当二者内容相等,判断后一个表达式,x的内容不是结束标识符,执行循环体。
【答案】(C)
8.有以下程序:
#include
fun(int x, int y)
{
static int m=0, i =2;
i += m+1; m = i + x + y; return m;
}
main()
{
int j =1, m = 1, k;
k=fun(j,m); printf("%d, ",k);
k=fun(j,m); printf("%d\n",k);
}
执行后的输出结果是( )。
(A)5, 11 |
(B)5, 5 | (C)11, 11 | (D)11, 5 |
【答案】(B)
9.有以下程序:
#include
int fun(int x[],int n)
{
static int sum=0,i;
for(i=0;i
程序执行后的输出结果是( )。
(A)55 |
(B)50 | (C)45 | (D)60 |
【答案】(D)
6.有以下程序:
#include
main()
{ char s[]="012xy\08s34f4w2";
int i, n = 0;
for(i = 0;s[i]!=0;i++)
if(s[i]>='0'&&s[i]<='9') n++;
printf("%d\n", n);
}
程序运行后的输出结果是( )。
(A)0 |
(B)3 | (C)7 | (D)8 |
【解析】“\0”在数组的字符单元存储形式是数值“0”,所以循环到了“\0”处,循环结束。
【答案】(B)
5.有以下程序:
#include
main()
{int s,t, A=10; double B = 6;
s = sizeof(A);t = sizeof(B);
printf("%d,%d\n",s,t);
}
在VC6.0平台上编译运行,程序运行后的输出结果是( )。
(A)10.6 |
(B)4,4 | (C)2,4 | (D)4,8 |
【答案】(D)
6.有以下程序:
#include
#include PT 3.5;
#include S(x) PT*x*x;
mian()
{
int a =1,b =2;
printf("%4.1f\n",S(a+b));
}
程序运行后的输出结果是( )。
(A)7.5 |
(B)31.5 |
(C)程序有错无输出结果 |
(D)14.0 |
【解析】先看选项再答题!!!
【答案】(C)
10.有以下程序:
#include
int fun1(double a)
{
return (int)(a*=a);
}
int fun2(double x,double y)
{
double a=0,b=0;
a=fun1(x);
b=fun1(y);
return (int)(a+b);
}
main()
{
double w;
w=fun2(1.1,2.0);
printf("%4.2f",w);
}
程序执行后输出结果是( )。
(A)0.0 |
(B)5 | (C)5.21 | (D)5.00 |
【答案】(D)
10.若有定义int x,y;,并已正确给变量赋值,则以下选项中与表达式(x-y)? (x++):(y++)中的条件表达式(x-y)等价的是( )。
(A)(x-y<0||x-y>0) |
(B)(x-y<0) |
(C)(x-y>0) |
(D)(x-y==0) |
【答案】(A)
10.
#include
void main()
{
int x=1;y=0;
if(!x)y++;
else if(x==0)
if(x)y+=2;
else y+=3;
printf("%d\n",y);
}
(A)3 |
(B)2 | (C)1 | (D)0 |
【解析】
int x=1;y=0;
if(!x)y++; //!x为0执行else if
else if(x==0) //x的值并未改变,x==0不成立,没有else与之匹配,直接执行printf
if(x)y+=2;
else y+=3; //与上面最近的if(x)匹配
printf("%d\n",y);
【答案】(D)
11.有以下程序:
#include
main()
{int a = 0,b = 0,c = 0,d = 0;
if(a = 1) b = 1; c = 2;
else d = 3;
printf("%d,%d,%d,%d\n",a,b,c,d);
}
程序输出( )。
(A)1,1,2,0 |
(B)0,0,0,3 | (C)编译有错 | (D)0,1,2,0 |
【答案】(C)
12.有以下程序:
#include
main()
{
int i,j, m = 1;
for(i=1; i<3; i++)
{for(j=3; j>0;j--)
{ if(i*j>3)break;
m*=i*j; }
}
printf("m=%d\n", m);
}
程序运行后的输出结果是( )。
(A)m = 4 |
(B)m = 2 | (C)m = 6 | (D)m = 5 |
【答案】 (C)
10.设有定义:float x;,则以下对指针变量p进行定义且赋初值的语句中正确的是( )。
(A)int *p=(float)x; |
(B)float *p=&x; |
(C)float p=&x; |
(D)float *p=1024; |
【答案】(B)
1.sizeof(double)是( )。
(A)一个整型表达式 |
(B)一个双精度型表达式 |
(C)一个不合法的表达式 |
(D)一种函数调用 |
【解析】ziseof()是C语言中的一个操作符,不是函数调用。
【答案】(A)
2.设有定义:char p[]={'1', '2', '3'}, *q = p;,以下不能计算出一个char型数据所占字节数的表达式是( )。
(A)sizeof(p) |
(B)sizeof(char) | (C)sizeof(*q) | (D)sizeof(p[0]) |
【解析】计算的是一个char型数据的字节数,(A)计算的是字符数组p所占字节数。
【答案】(A)
12.若有定义语句:
char s[10]="1234567\0\0";则strlen(s)的值是( )。
(A)7 |
(B)8 | (C)9 | (D)10 |
【答案】(A)
14.有以下程序
#include
#include
char *a = "you";
char *b = "Welcome you to Bei jing!";
main()
{ char *p;
p = b;
while(*p != *a)p++;
p += strlen(a) + 1;
printf("%s\n",p);
}
程序运行后的输出结果是( )。
(A)Beijing! |
(B)you to Beijing! |
(C)Welcome you to Beijing! |
(D)to Beijing! |
【解析】
【答案】()
13.有以下程序:
#include
#include
main()
{
char str[][20]={"One*World", "One*Dream!"},
*p = str[1];
printf("%d, ", strlen(p));
printf("%s\n",p);
}
程序运行后的输出结果是( )。
(A)10, One*Dream! |
(B)9, One*Dream! |
(C)9, One*World |
(D)10, One*World |
【解析】
【答案】(A)
1.以下语句中存在语法错误的是( )。
(A)char ss[6][20]; ss[1]="right?"; |
(B)char ss[][20]={"right?"}; |
(C)char *ss[6]; ss[1]= "right?"; |
(D)char *ss[]={"right? "}; |
【解析】“char *ss[6];”先定义了一个含有6个元素的数组ss,每个元素的类型是“char * ”,也就是,每个元素就是一个地址,ss[1]是字符基类型的地址(字符指针变量),将一个字符串直接赋给字符指针是没有问题的,(C)对。需要明确的是,(C)中ss[1]虽然同(A)中的ss[1]一样都是地址,但(C)中ss[1]是一个指针变量,而(A)中的ss[1]是数组名,是一个地址常量,不能够对其进行赋值运算,但在定义时进行初始化是可以的 。
【答案】(A)
2.有以下程序:
#include
main()
{
char s[]="abdcde";
s+=2;
printf("%d\n",s[0]);
}
执行后的结果是( )。
(A)输出字符c 的ASCII码 |
(B)程序出错 |
(C)输出字符c |
(D)输出字符a的ASCII码 |
【答案】(B)
15.以下定义语句中正确的是
(A)int a=b=0; |
(B)char A=65+1,b='b'; |
(C)float a=1,*b=&a,*c=&b; |
(D)double a=0.0;b=1.1; |
【答案】()
12.有以下程序:
#include
#include
int fun(int n)
{ int *p;
p=(int*)malloc(sizeof(int));
*p = n;
return *p;
}
main()
{ int a;
a = fun(10);
printf("%d\n", a + fun(10));
}
程序的运行结果是( )。
(A)0 |
(B)10 | (C)20 | (D)出错 |
【解析】malloc函数返回的是一个不确定类型的void指针,“(int *)”将void类型指针强制转换为int型指针,这和数据之间的强制转换语法相似。
【答案】(C)
12.有以下程序:
#include
void fun(int a[],int n)
{
int i, t;
for(i=0; i
程序运行后的输出结果是( )。
(A)321678 |
(B)876543 | (C)1098765 | (D)345678 |
【解析】函数fun的形参形式是一维数组地址,能够改变对应实参内存单元的值。
【答案】(A)
13.有以下程序:
#include
#define N 4
void fun(int a[][N],int b[])
{
int i;
for(i=0; i
程序运行后的输出结果是( )。
(A)-3,-1,1,3, |
(B)-12,-3,0,0, | (C)0,1,2,3, | (D)-3,-3,-3,-3 |
【答案】(A)
1.有以下程序:
#include
#define PT 3.5;
#define S(X) PT*X*X;
main()
{ int a =1,b =2;
printf("%4.1f\n", S(a+b));}
程序运行后的输出结果是( )。
(A)7.5 |
(B)31.5 | (C)程序有错,无输出结果 | (D)14.0 |
【答案】(C)
2.有以下程序:
#include
double f(double x);
main()
{ double a = 0;int i;
for(i<0;i<30,i +=10)
a += f((double)i);
printf("%3.0f\n",a);
}
double f(double x)
{ return x*x+1;}
程序运行后的输出结果是( )。
(A)500 |
(B)401 | (C)503 | (D)1404 |
【解析】第一次循环,a=0,i=0,返回值a=0*0+1。通过这种形式计算会更清晰。%m.nf表示数据输出总的宽度为m位,其中小数部分占n位。
【答案】(C)
3. 有以下程序:
#include
int fun1(double a)
{
return (int)(a*=a);
}
int fun2(double x,double y)
{
double a=0,b=0;
a=fun1(x);
b=fun1(y);
return (int)(a+b);
}
main()
{
double w;
w=fun2(1.1,2.0);
printf("%4.2f",w);
}
程序执行后输出结果是( )。
(A)0.0 |
(B)5 | (C)5.21 | (D)5.00 |
【答案】(D)
15.设有宏定义:
#define IsDIV(k,n)((k%n==1)?1:0)
且变量m已正确定义并赋值,则宏调用:IsDIV(m,5)&&IsDIV(m,7)
为真时所要表达的是( )。
(A)判断m是否能被5和7整除 |
(B)判断m被5和7整除是否都余1 |
(C)判断m被5或者7整除是否余1 |
(D)判断m是否能被5和7整除 |
【解析】
【答案】(B)
1.有以下程序:
#include
main()
{
unsigned char a =2, b=4, c=5, d;
d =a|b; d&=c;
printf("%d\n",d);
}
程序运行后的输出结果是( )。
(A)3 |
(B)4 | (C)5 | (D)6 |
【答案】(B)
2.有以下程序
#include
main()
{ int i=0;
i=~i;
printf("%d\n",i)
}
程序运行后的输出结果是( )。
(A)8 |
(B)0 | (C)1 | (D)-1 |
【解析】0按位取反,在计算机中的存储形式是(1111 1111)b。int在定义时就默认为是有符号号数,当把(1111 1111)b显示出来时,就认为最高位是符号位,判断其为负数,并且计算机中数据都是以补码形式存储的,负数的原码求取步骤:(1111 1111)补->(1111 1110)反。反码->原码,符号位不变,按位取反,(1000 0001)原,因此结果才为-1。
【答案】(D)
3.设有以下语句:
#int a =1, b=2, c;
c = a^(b<<2);
执行后,c的值为( )。
(A)7 |
(B)9 | (C)8 | (D)6 |
【答案】(B)
4.有以下程序:
#include
main()
{
unsigned char a = 8, c;
c = a>>3;
printf("%d\n", c);
}
程序运行后的输出结果是( )。
(A)16 |
(B)1 | (C)32 | (D)0 |
【解析】计算机无论是int还是char的基本单位都是1个字节(8位二进制),而char型无论是有符号型还是无符号都是8位,区别在于对第8位的二进制标定是数据位还是符号。unsigned char就是8位二进制全是数据位,由于采用的是ASCII编码“8”的形式输入,不用管对应的字符是什么,其二进制为(00001000)B,无符号数右移,高位直接补0。
【答案】(B)
5.有以下程序
#include
main()
{ char x=2,y=2,z;
z=(y<<1)&(x>>1);
printf("%d\n",z);
}
程序的输出结果是( )。
(A)1 |
(B)0 | (C)4 | (D)8 |
【解析】做题技巧,带入有符号数和无符号数都算一遍,结果都是一样的。
【答案】(B)
用typedef说明新类型名,且原类型名仍有效
typedef 类型名 新类型名;
为不同数据类型定义新类型名
(1)基本类型
(2)数组类型
typedef char CHARR[80];
CHARR c,d[4];
//相当于char c[80],d[4][80];
可以这样理解,这种方式在定义变量时,就是在变量后面增加[N]。
(3)指针类型
typedef int *IPOINT; IPOINT ip;
/*相当于int *ip*/
有了“*”就是用户命名的标识符是一个指针定义,前面的数据类型是指针的基类型。
1.以下叙述中正确的是( )
(A)使用typedef说明新类型名时,其格式是:typedef 新类型名 原类型名 |
(B)在程序中,允许用typedef来说明一种新的类型名 |
(C)使用typedef说明新类型名时,后面不能加分号 |
(D)在使用typedef改变原类型的名称后,只能使用新的类型名 |
【解析】C语言中,语句必须以分号结束,所以空语句表示为“;”,不是空行。
【答案】(D)
2.若有定义:
typedef char T[10]; T *a;
上述定义中a的类型与下面选项中完全相同的是( )。
(A)char a[10]; |
(B)char (*a)[10]; | (C)char *a; | (D)char *a[10]; |
【解析】通过这种方式定义了一个指针数组。
【答案】(D)
3.若有定义
typedef int *T[10]; T a;
则以下选项与上述定义中a的类型完全相同的是( )
(A)int *a[10]; |
(B)int (*a)[10]; | (C)int a[10]; | (D)int (*a[10])(); |
【答案】(A)
4.有以下程序:
#include
#include
typedef struct{ char name[9]; char sex;
int score[2];}STU;
STU f(STU a)
{
STU b={"Zhao", 'm', 85, 90};
int i;
strcpy( a.name, b.name);
a.sex=b.sex;
for(i=0;i<2;i++) a.score[i]=b.score[i];
reture a;
}
main ()
{
STU c={"Qian","f", 95, 92}, d;
d=f(c);
printf("%s,%c,%d,%d ", d.name, d.sex
d.score[0], d.score[1]);
printf("%s,%c,%d,%d\n", c.name, c.sex,
c.score[0], c.score[1]);
}
程序运行后的输出结果是( )。
(A)Zhao,m,85,90, Qian,f,95,92 |
(B)Zhao,m85,90, Zhao,m,85,90 |
(C)Qian,f,95,92, Qian,f,95,92 |
(D)Qian,f,95,92, Zhao,m,85,90 |
【答案】 (A)
4.有以下程序:
#include
#include
#include
struct stu{
char *name,gender;
int score;
};
main ()
{
struct stu a={NULL,'m',290}, b;
a.name=(char *)malloc(10);
strcpy(a.name,"Zhao");
b = a; b.gender = 'f'; b.score = 350;
strcpy(b.name,"Qian");
printf("%s,%c,%d,", a.name, a.gender, a.score);
printf("%s,%c,%d\n", b.name, b.gender, b.score);
}
程序运行后的输出结果是( )。
(A)Zhao,m,290,Zhao,f,350 |
(B)Zhao,m,290,Qian,f,350 |
(C)Qian,f,350,Qian,f,350 |
(D)Qian,m,290,Qian,f,350 |
【解析】把a赋值给b,在处理指针变量name的时候,是将a.name的值给指针变量b.name,也就是说,实际上,a和b指向同一个地址,将”Qian“赋值给b.name也就会改动b.name所指向的地址的内容。
【答案】 (D)
16.有以下程序段:
struct st
{ int x; int *y; }*pt;
int a[] ={1,2}, b[] ={3,4};
struct st c[2] ={10,a,20,b};
pt =c;
以下选项中表达式的值为11的是( )。
(A)++pt ->x |
(B)pt ->x | (C)*pt ->y | (D)(pt++) ->x |
【解析】c有2个元素,每个元素都是含有int x和int *y的结构体变量,“10”和“a”分别表示c[0]的int x和int *y,“a”后面没有“[ ]”表示地址,所以c[0].y是数组a的地址,也是a[0]元素的地址。pt指向c的第一个元素,那么pt->x为10,++pt ->为11。pt->y指向c的第一个元素的第二个结构体成员指针型变量y,而a的地址给到了y,*pt->y就是指向了y里面地址的内容,也就是“1”。
【答案】(C)
16.有以下程序:
#include
struct S{int n; int a[20];};
void f(struct S *p)
{
int i, j, t;
for(i=0; in-1; i++)
for(j=i+1; jn;j++)
if(p->a[i]>p->a[j])
{t=p->a[i]; p->a[i]=p->a[j]; p->a[j]=t;}
}
main()
{
int i; struct S s={10,{2,3,1,6,8,7,5,4,10,9}};
f(&s);
for(i=0; i
程序运行后的输出结果是( )。
【解析】可以思考一下,是哪种排序方法
【答案】(C)
17.有以下程序:
#include
int add(int a, int b){return(a+b); }
main()
{
int k, (*f)(), a=5,b=10;
f=add;
…
}
则以下函数调用语句错误的是( )。
(A)k=f(a, b); |
(B)k=add(a, b); |
(C)k=(*f)(a, b); |
(D)k=*f(a, b); |
【解析】“int (*f)()”定义了一个无参函数指针变量f,
【答案】(D)
16.有以下程序:
#include
typedef struct{int b,p; }A;
void f(A c) /* 注意:c是结构变量名*/
{
int j;
c.b +=1; c.p +=2;
}
main()
{
int i;
A a={1,2};
f(a);
printf("%d, %d\n", a.b, a.p);
}
程序运行后的输出结果是( )。
(A)2,4 |
(B)1,2 | (C)1,4 | (D)2,3 |
【解析】结构体的声明和定义是第4种方式,只不过将声明和定义变量两个部分拆开了。“A”就是一种结构体数据类型,“A a”就是在定义一个结构体变量a,和“int x”是一样的。“f(A c)”函数的形参也是对应的结构体变量,但是这种方式只是实参的值传递给了形参,不会改变实参的值。
【答案】(B)
16.若有以下程序:
#include
main()
{ char c1,c2;
c1 = 'C'+'8'-'3';c2 = '9'-'0';
printf("%c %d\n",c1,c2);
}
则程序的输出结果是( )。
(A)H '9' |
(B)H 9 |
(C)F '9' |
(D)表达式不合法,输出无定值 |
【解析】不用记'0'的ASCII码值是48,因为码值也是连续的,'8'和'3'之间的ASCII码差值也是5,‘C’往后面数5位就是c1。
【答案】(B)
17.有以下程序:
#include
main()
{ int i;
FILE* fp;
for (i =0;i<3;i++)
{ fp = fopen("res.txt","w");
fputc('K'+i,fp);
fclose(fp);
}
}
程序运行后,在当前目录下会生成一个res.txt文件,其内容是( )。
(A)EOF |
(B)M | (C)KLM | (D)L |
【解析】
【答案】(B)
2、以下程序依次把终端输入的字符存放到f文件中,用#作为结束输入的标志,则在横线处应填入的选项是( )。
#include
main()
{ FILE *p;char ch;
fp=fopen("fname","w");
while((ch = getchar()) != '#')
fputc(_______);
fclose(fp);
}
(A)ch,"fname" |
(B)fp,ch | (C)ch | (D)ch,fp |
【答案】(D)
文件指针,实际上是指向一个结构体类型的指针变量,这个结构体种包含有诸如:缓冲区的地址、在缓冲区种当前存取的字符的位置等信息。
1.下面说法正确的是( )
(A)文件指针变量的值是文件当前正在处理的字节地址 |
(B)文件指针变量的值是文件中包含的字符个数 |
(C)文件指针的类型是一种指针类型 |
(D)文件指针的类型是结构体类型 |
【解析】文件指针变量的值是文件所在的地址。
【答案】(C)
2.下面选项中关于“文件指针”概念的叙述正确的是( )。
(A)文件指针是程序中用FILE定义的指针变量 |
(B)文件指针就是文件位置指针,表示当前读写数据的位置 |
(C)文件指针指向文件在计算机中的存储位置 |
(D)把文件指针传给fscanf函数,就可以向文本文件中写入任意的字符 |
【解析】
【答案】(A)
3.假设文件指针fp已定义,执行语句fp=fopen("file","w");后,以下针对文本文件file操作叙述中正确的是( )。
(A)只能写不能读 |
(B)写操作结束后可以从头开始读 |
(C)可以在原有内容后追加写 |
(D)可以随意读和写 |
【答案】(A)
由于一次文件操作涉及到的函数操作多,单独将文件相关的真题作为一个章节。
1.有以下程序段:
FILE *fp;
if((fp = fopen("text.txt","w"))==NULL)
{ printf("不能打开文件!");
exit(0);}
else
printf("成功打开文件!");
若指定test.txt不存在,且无其他异常,则以下叙述中错误的是( )。
(A)输出“不能打开文件!” |
(B)输出“成功打开文件!” |
(C)系统将按指定文件名新建文件 |
(D)系统将为写操作建立文本文件 |
【答案】(A)
4.有以下程序:
#include
main()
{
FILE *fp;
int k,n,a[6]={1,2,3,4,5,6};
fp=fopen("d2.dat","w");
fprintf(fp,"%d%d%d\n",a[0],a[1],a[2]);
fprintf(fp,"%d%d%d\n",a[3],a[4],a[5]);
fclose(fp);
fp=fopen("d2.dat","r");
fscanf(fp,"%d%d",&k,&n);
printf("%d %d\n",k,n);
fclose(fp);
}
程序运行后的输出结果是( )。
(A)1 2 |
(B)1 4 | (C)123 4 | (D)123 456 |
【解析】fscanf()和sancf()在用法上没有区别,输入数值数据时同样需要注意,“\n”将作为结束标识符,所以k=123,n=456。
【答案】(D)
5.有以下程序:
#include
main()
{
FILE *fp; int a[10]={1,2,3}, i, n;
fp=fopen("d1.dat","w");
for(i=0;i<3;i++)fprintf(fp,"%d", a[i]);
fprintf(fp,"\n");
fclose(fp);
fp=fopen("d1.dat"."r");
fscanf(fp,"%d", &n);
fclose(fp);
printf("%d\n",n);
}
程序的运行结果是( )。
(A)321 |
(B)12300 | (C)1 | (D)123 |
【答案】(D)
6.有以下程序
#include
main()
{
FILE *f;
f=fopen("filea.txt","w");
fprintf(f,"abc");
fclose(f);
}
若文本文件filea.txt中原有内容为:hello,则运行以上程序后,文件filea.txt中的内容为
(A)abclo |
(B)abc | (C)helloabc | (D)abchello |
【解析】fprintf之所以被称之为格式化写函数,就是因为在写之前会将文件指针后面的内容格式化掉。
【答案】(B)
8.读取二进制文件的函数调用形式为:fread(buffer,zize,count,fp);,其中buffer代表的是( )。
(A)一个内存块的字节数 |
(B)一个整型变量,代表待读取的数据的字节数 |
(C)一个文件指针,指向待读取的文件 |
(D)一个内存块的首地址,代表读入数据存放的地址 |
【答案】(D)
9.有以下程序:
#include
main()
{ File *pf;
char *s1 ="China", *s2 ="Beijing";
pf=fopen("abc.dat","wb+");
fwrite(s2,7,1,pf);
rewind(pf);/*文件位置指针回到文件开头*/
fwrite(s1,5,1,pf);
fclose(pf);
}
以上程序执行后abc.dat文件的内容是( )。
(A)China |
(B)Chinang | (C)ChinaBeijing | (D)BeijingChina |
【答案】(B)
10.有以下程序:
#include
main()
{
FILE *fp;
int a[10]={1,2,3,0,0},i;
fp=fopen("da.dat","wb");
fwrite(a,sizeof(int),5,fp);
fwrite(a,sizeof(int),5,fp);
fclose(fp);
fp=fopen("da.dat","rb");
fread(a,sizeof(int),10,fp);
fclose(fp);
for(i=0;i<10;i++)
printf("%d",a[i]);
}
程序的运行结果是( )。
(A)1,2,3,0,0,0,0,0,0,0, |
(B)1,2,3,1,2,3,0,0,0,0, |
(C)123,0,0,0,0,123,0,0,0,0, |
(D)1,2,3,0,0,1,2,3,0,0, |
【解析】fwrite()是一次写入4B,一个int占4B,也就是每个元素占4B,所以,第一次写入的是12300,文件指针指向下一个位置,第二次写入12300,da.dat里的内容为1230012300。读的时候,a是首地址,因此会进行覆盖。
【答案】(D)
13.若有以下程序
#include
main()
{ FILE *fp;
int i,a[6]={1,2,3,4,5,6},k;
fp=fopen("data.dat","w+");
for(i=0;i<6;i++)
{ fseek(fp,0L,0);fprintf(fp,"%d\n",a[i]);}
rewind(fp);
fscanf(fp,"%d",&k);
fclose(fp);
printf("%d\n",k);
}
则程序的输出结果是( )。
(A)123456 |
(B)1 | (C)6 | (D)21 |
【解析】
【答案】(C)
结构体变量定义分为4种方式,尤其要注意“;”的使用位置:(1)先说明类型,再定义变量
struct 结构体名 变量名表;
(2)声明类型同时定义变量
struct 结构体名
{ 数据类型1 结构成员名表1;
数据类型2 结构成员名表2;
…
数据类型n 结构成员名表n;
}变量名表;
(3)直接定义结构体类型变量
struct
{ 数据类型1 结构成员名表1;
数据类型2 结构成员名表2;
…
数据类型n 结构成员名表n;
}变量名表;
(4)使用typedef说明一个结构体类型名,再用新类型名定义变量
typedef struct
{ 数据类型1 结构成员名表1;
数据类型2 结构成员名表2;
…
数据类型n 结构成员名表n;
}新数据类型名;
新数据类型名 变量名表;
结构体变量的引用
(1)结构体变量名.成员名
(2)结构体指针变量名->成员名
(3)(*指针变量名).成员名
1.下面结构体的定义语句中,错误的是( )
(A)struct ord {int x; int y; int z; }struct ord a; |
(B)struct ord {int x; int y; int z; };struct ord a; |
(C)struct ord {int x; int y; int z; } a; |
(D)struct {int x; int y; int z;} a; |
【答案】(A)
2.一下结构体说明和变量定义中,正确的是( )
(A)typedef struct abc{int n; double m;}ABC; |
(B)struct abc {int n;double m};struct abc; |
(C)struct ABC {int n; double m;}struct ABC x,y; |
(D)struct abc{int n;double m;}; abc x,y; |
【解析】(B)和(C)选项分别在“m”和“}”后面少个“;”(D)选项不存在这种定义结构体变量的方式。
【答案】(A)
3.设有定义:
设有定义:
typedef struct data1{int x,y;} data2;
typedef struct {float x,y;} data3;
则以下不能作为类型名使用的是( )
(A)data1 |
(B)data2 | (C)data3 | (D)struct data1 |
【答案】(A)
4.若有以下语句:
typedef struct S
{ int g; char h;}T;
以下叙述中正确的是( )。
(A)可用S定义结构体变量 |
(B)可用T定义结构体变量 |
(C)S是struct类型的变量 |
(D)T是struct S类型的变量 |
【解析】T为结构体类型。
【答案】(B)
1.设有如下的说明和定义
struct{
int a;
char *s;
}x,*p=&x;
x.a=4;
x.s="hello";
则以下叙述中正确的是( )。
(A)(p++)->a与p++->a都是合语法的表达式,但二者不等价 |
(B)语句++p->a;的效果是使p增1 |
(C)语句++p->a;的效果是使成员a增1 |
(D)语句*p->s++;等价于(*p)->s++ |
【解析】首先"->"的优先级是高于自增运算符的,但p++->a是不合法的。++p->a首先应该是p->a相结合,所以先指向成员a,然后再++。而对于*p->s++,“->”优先级最高,所以先p->s,指向了字符指针变量,然后“++”优先级高于“*”,所以在语句执行完了以后,应该是指针s指向了字符“e”,该语句执行的结果,就是将字符“h”提取出来。
【答案】(C)
无论采不采用typedef区定义结构体,指针域的定义应采用原始结构体变量定义的形式。
1.为了建立如图所示的存储结构(即每个结点含两个域,data是数据域,next是指向结点的指针域),则在【】处应填入的选项是
Struct link{ char data; 【】 }node;
(A)link next; |
(B)struct link *next; | (C)link *next; | (D)struct link next; |
【答案】(B)
2.程序中已构成如下图所示的不带头结点的单向链表结构,指针变量s、p、q均已正确定义,并用于指向链表结点,指针变量s总是作为指针指向链表的第一个结点。
若有以下程序段:
q=s;s=s->next;p=s;
while(p->next)p=p->next;
p->next=q;q->next=NULL;
该程序段实现的功能是( )。
(A)删除尾结点 |
(B)尾结点成为首结点 |
(C)删除首结点 |
(D)首结点成为尾结点 |
【解析】首先是指针q,通过语句p=s使q指向a结点,指针s指向了它的下一个结点b,指针p也指向b结点。然后通过while循环,指针p指向链表的最后一个元素。通过语句p->next=q改变最后一个元素的指向,并将第一个元素q的next赋值为NULL值,所以实现的效果是使首结点成为尾结点。
【答案】(D)