简述结构化程序设计、面向对象程序设计的概念及其区别

(1)结构化程序设计
结构化程序设计的基本思想是采用自顶向下、逐步细化的设计方法和单入单出的控制结构。其理念是将大型程序分解成小型、便于管理的任务。如果其中的一项任务仍然过大,则将它分解为更小的任务。这一过程将一直持续下去,直到将程序划分为小型的,易于编写的模块。

*这种设计方式有着显著的一些问题:
程序难以管理、数据修改存在问题、程序可重用性差、用户要求难以在系统分析阶段准确定义,致使系统在交付使用时产生许多问题。
用系统开发每个阶段的成果来进行控制,不能适应事物变化的要求。
这种问题的根源在于数据和数据的处理不能分离。
(2)面向对象程序设计
面向对象(ObjectOriented )是认识事务的一种方法,是一种以对象为中心的思维方式面向将系统看成通过交互作用来完成特定功能的对象的集合。每个对象用自己的方法来管理数据。也就是说只有对象内部的代码能够操作对象内部的数据。
*面向对象的基本特征
1、抽象2、封装3、继承4、多态5、继承和多态  (3)面向对象程序设计优缺点
面向对象编程的优点:
易维护、质量高、效率高、易扩展

面向对象编程的缺点:运行效率会下降10%左右

  • 16
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
1、简述java语言的特点? Java语言是目前使用最为广泛的网络编程语言之一 〔1分〕 具有面向对象 〔1分〕 与平台无关性 〔1分〕 多线程性 〔1分〕 动态性等特点 〔1分〕 2、 简述Java程序的开发过程 1 使用一个文字编辑器,编写源文件。 〔1分〕 2 使用java编译器,编译源文件得到字节码文件。 〔2分〕 3 运行java程序,分两种java应用程序必须通过java解释器来解释执行,java小应用程序 必须使用解释器和浏览器运行程序。 〔2分〕 3、 java源文件的命名规则是什么? 如果源文件中有多个类,那么只能有一个类是public类 〔1分〕 如果有一个类是public类,源文件的名字必须与这个类的名字完全相同,扩展名是java 〔2分〕 如果源文件没有public类,源文件的名字只要和某个类的名字相同,并且扩展名是java 〔2分〕 4、 怎样区分应用程序和小应用程序? 一个java应用程序必须且只有一个类含有main方法,这个类称为应用程序的主类,其ma in方法必须被说明为public static void 〔1分〕 一个Java Applet小应用程序不再需要main方法,但必须有一个类扩展了Applet类,即它是Applet 类的主类。 〔2.5分〕 5、 Java中共有哪些基本数据类型? 基本类型共有8种,分四类分别是 〔1分〕 逻辑型 〔1分〕 字符型 〔1分〕 整型 〔1分〕 浮点型 〔1分〕 6、 Java中数据类型分别用什么符号来表示? 逻辑型用boolean 表示 〔1分〕 字符型用char表示 〔1分〕 整型共有4种分别是 byte、short、long、int 〔2分〕 浮点型共两种float和double 〔1分〕 7、 简答标示符的概念及定义原则 标示符是用来标识类名、变量名、方法名、类型名等有效字符序列。 〔2.5分〕 Java语言规定标示符由字母、下划线、美元符号和数字组成,并且第一个字符不能是数 字,及java中的关键字不能用作标示符。 〔2.5分〕 8、 简答什么是强制类型转换及转换格式 当把一种数据类型变量的值赋给另一种数据类型时会用到数据转换。当把在内存中占字 节数较少的变量的值赋给占字节较多的变量时,系统自动完成数据类型的转换 〔2.5分〕 格式 数据类型名 变量名或表达式 〔2.5分〕 9、 简答表达式++x和x++的区别 ++x表示在使用x之前,先使x的值加1 〔2.5分〕 x++表示在使用x之后,使x的值加1 〔2.5分〕 10、 Java中常用的运算符按功能分有哪些 Java运算符按功能分6种,具体如下 〔1分〕 算术运算符、关系运算符、逻辑运算符 〔2分〕 位运算符、赋值运算符、条件运算符 〔2分〕 11、 Java中结构化程序设计有哪三种基本流程及分别对应java中那些语句 结构化程序设计有顺序、分支、循环三种基本流程 〔2分〕 java中的分支语句包括if语句、switch语句 〔1分〕 循环语句包括while语句、do-while语句、for语句 〔1分〕 其他如对象、变量定义语句、赋值语句、方法调用语句等都是顺序语句。 〔1分〕 12、 在一个循环中使用break和continue语句有什么不同的效果? 在循环中使用break语句将使循环终止,流程跳转到break语句所在的循环外面的第一个 语句继续执行 〔2.5分〕 在循环中使用continue语句将提前结束本次循环,流程跳转到continue语句所在循环的 第一个语句继续执行 〔2.5分〕 13、 package语句与import语句分别作用是什么? package语句作为java源程序的第一条语句,指明该源文件定义的类所在的包。 〔2.5分 〕 import语句作用是为了能使用java提供的类,可以使用import语句来引入所需要的类。 〔2.5分〕 14、 简述编程语言的几个发展阶段 1 面向机器语言 〔1分〕 2 面向过程语言 〔1分〕 3 结构化程序设计阶段 〔1分〕 4 面向对象编程 〔1分〕 15、 什么是类及类的实现包括什么 类是组成java程序的基本要素 〔1分〕 类封装了一类对象的状态和方法 〔1分〕 类是用来定义对象的模板 〔1分〕 类的实现包括两部分 类声明和类体 〔1分〕 16、 什么是方法重载 方法重载是指,一个类中可以有多个方法具有相同的名字和类型 〔2分〕 但这些方法的参数必须不同〔1分〕 或者是参数个数不同,或者是参数类型不同〔1分〕 17、 什么是构造方法 构造方法是一种特殊方法 〔1分〕 它的名字必须与它所在的类的名字完全相同 〔1分〕 并且不返回任何数据类型,即它是void型 〔1分〕 18、 什么是实例变量和类变量及他们的区别 用修饰符static
第1章 驱动程序开发环境 <br>第2章 测试驱动程序<br>第一部分 一般内核模式<br>第1章Windows 2000和WDM驱动程序<br>第2章 分层的I/O、IRP和I/O对象<br>第3章 系统定义的对象和对驱动程序的支持<br>第4章 驱动程序基本结构<br>第5章DriverEntry 和 Reinitialize 例程<br>第6章Dispatch例程<br>第7章StartIo和队列管理例程<br>第8章 中断服务例程<br>第9章 DpcForIsr例程和CustomDpc例程<br>第10章SynchCritSection例程<br>第11章AdapterControl和ControllerControl例程<br>第12章Cancel例程<br>第13章IoCompletion例程<br>第14章IoTimer和CustomTimerDpc例程<br>第15章Unload例程<br>第16章 常见的驱动程序设计问题<br><br>第1部分 图形驱动程序<br>第2部分 显示器及视频微端口驱动程序<br>第3部分 打印机驱动程序及假脱机打印部件<br><br>第五卷 网络驱动程序设计指南 1<br>第一部分 网络驱动程序 2<br>第一章 网络驱动程序设计指南的向导 3<br>第二章 内核模式驱动程序的网络结构 6<br>2.1 Windows 2000 网络结构和OSI模型 6<br>2.2 NDIS驱动程序 7<br>2.2.1 NDIS微端口驱动程序 7<br>2.2.2 NDIS中间层驱动程序 8<br>2.2.3 NDIS协议驱动程序 9<br>2.3 TDI驱动程序 9<br>2.4 网络驱动程序环境 9<br>2.4.1 无连接环境的网络驱动程序 10<br>2.4.2 面向连接环境下的网络驱动程序 10<br>2.4.3 WAN网络驱动程序的环境 11<br>第三章 网络驱动程序编程要点 13<br>3.1 可移植性 13<br>3.2 多处理器支持 13<br>3.3 IRQL 14<br>3.4 同步和指示 14<br>3.5 包结构 16<br>3.6 使用共享内存 17<br>3.7 异步I/O和完成函数 17<br>第二部分 微端口NIC驱动程序 19<br>第一章 NDIS NIC微端口驱动程序 20<br>1.1 NIC微端口驱动程序类型 20<br>1.2 网络接口卡支持 20<br>1.3 微端口驱动程序代码的重要特征 22<br>1.3.1 MiniportXxx函数 22<br>1.3.2 与NDIS库链接 22<br>1.3.3 微端口适配器环境 22<br>1.3.4 VC环境 23<br>1.3.5 网络OID 23<br>1.4 驱动程序例子 24<br>第二章 NIC微端口操作和函数概要 25<br>2.1 NIC微端口操作 25<br>2.1.1 初始化NDIS库和注册微端口驱动程序 25<br>2.1.2 注册网络接口卡 25<br>2.1.3 对查询和设置微端口信息作出响应 26<br>2.1.4 产生,激活,去活,和删除虚连接 26<br>2.1.5 发送数据 27<br>2.1.5.1 多包发送 27<br>2.1.5.2 单包发送 28<br>2.1.6 指示和传递接收的数据 28<br>2.1.6.1 多包接收 29<br>2.1.6.2 单包接收 29<br>2.1.7 指示状态 30<br>2.1.8 复位网络接口卡 30<br>2.1.9 终止一个微端口NIC驱动程序 30<br>2.2 微端口上层函数 30<br>2.2.1 无连接微端口的上层函数 31<br>2.2.2 面向连接微端口的上层函数 32<br>2.3 由微端口调用的NDIS函数 33<br>2.3.1 NDIS提供的初始化和注册函数 34<br>2.3.2 NDIS提供的硬件设置函数 35<br>2.3.3 NDIS提供的I/O端口函数 36<br>2.3.4 NDIS数据的与DMA相关的函数 37<br>2.3.5 NDIS提供的中断处理函数 38<br>2.3.6 NDIS提供的同步函数 38<br>2.3.7 NDIS提供的状态函数 39<br>2.3.8 NDIS为无连接微端口提供的发送和接收函数 39<br>2.3.9 NDIS为面向连接微端口提供的发送和接收函数 40<br>2.3.10 NDIS提供的带外数据宏 41<br>2.3.11 NDIS提供的包和缓存处理函数 41<br>2.3.12 NDIS提供的支持函数 43<br>2.3.13 NDIS提供的媒体相关宏 46<br>第三章 NIC微端口驱动程序入口点和初始化 47<br>3.1 NDIS微端口驱动程序入口函数 47<br>3.1.1 初始化包裹 47<br>3.1.2 注册微端口 48<br>3.1.2.1 指定NDIS版本号 48<br>3.1.2.2 注册MiniportXxx函数 48<br>3.1.2.3 为中断支持的注册处理程序 50<br>3.1.2.4 为无连接微端口选择一个发送函数 51<br>3.1.2.5 为无连接微端口选择接收函数 51<br>3.1.2.6 注册一个分配完成处理程序 52<br>3.1.2.7 注册一个挂起检测(CheckForHang) 处理程序 52<br>3.2 NDIS微端口初始化 53<br>3.2.1 注册一个NIC 53<br>3.2.1.1 分配一个适配器指定的环境区域 54<br>3.2.1.2 读取配置信息 54<br>3.2.1.3 注册NIC 54<br>3.2.2 声明资源 55<br>3.2.2.1 分配内存 55<br>3.2.2.2 注册端口 56<br>3.2.2.3 总线管理器DMA设备初始化 56<br>3.2.2.4可编程I/O设备初始化 57<br>3.2.2.5 内存映射设备初始化 58<br>3.2.2.6 从属DMA设备初始化 58<br>3.2.3 注册一个中断 59<br>3.2.4 注册一个关闭函数 59<br>3.2.5 初始化轮询时钟 59<br>3.2.6 在初始化当中的同步 60<br>3.2.7 在初始化时处理错误 60<br>3.3 查询微端口信息 61<br>3.4 减少微端口初始化时间 61<br>第四章 数据传输 64<br>4.1 中断处理 64<br>4.2 DPC处理程序 66<br>4.3 带外(OOB)数据包 66<br>4.3.1 等待发送的OOB数据 67<br>4.3.2 接收的OOB数据 68<br>4.4 发送包 69<br>4.4.1 无连接微端口的多包传送 70<br>4.4.1.1 串行微端口的多包传送 70<br>4.4.1.2 非串行微端口的多包传送 71<br>4.4.2 无连接微端口的单包发送 71<br>4.4.3 面向连接微端口的多包发送 72<br>4.4.4 发送数据前的内存同步 73<br>4.4.5 发送步骤 74<br>4.4.5.1 在总线控制器DMA NIC上发送包 74<br>4.4.5.2 在PIO设备上发送单包 76<br>4.4.5.3 使用板上内存发送包 77<br>4.5 非串行微端口 78<br>4.5.1 非串行微端口的NDIS要求 78<br>4.5.2 非串行微端口的驱动程序内部要求 78<br>4.6 接收数据 79<br>4.6.1 无连接和面向连接微端口的多包接收 79<br>4.6.2 无连接微端口的单包接收 82<br>4.6.3 接收数据的高速缓存(Cache)因素 83<br>4.6.4 接收数据的步骤 83<br>4.6.4.1 接收期间的包管理 84<br>4.6.4.2 在总线控制器DMA NIC上接收数据 84<br>4.6.4.3 在PIO NIC上接收数据 85<br>4.6.4.4 在内存映射设备上接收数据 85<br>4.7 保持统计量 85<br>4.8 802.1P 包的优先权 86<br>4.8.1 查询802.1p优先权支持 87<br>4.8.2 802.1优先权的包支持 87<br>4.8.3 为发送和接收指定包的大小 88<br>4.8.4 默认情况下禁止802.1p的优先权支持 88<br>第五章 获取和设置WMI的微端口信息及NDIS支持 89<br>5.1 NDIS管理信息和OID 89<br>5.2 查询微端口信息 89<br>5.2.1 无连接微端口的查询 90<br>5.2.2 面向连接微端口的查询 91<br>5.3 设置微端口信息 92<br>5.3.1 为无连接微端口设置信息 92<br>5.3.2 为面向连接微端口设置信息 92<br>5.3.3 设置微端口信息的时机 93<br>5.4 报告硬件状态 93<br>5.5 WMI的NDIS支持 94<br>5.5.1 用WMI注册与注销NDIS微端口 94<br>5.5.2 OID和微端口状态的GUID映射 94<br>5.5.3 支持命名VC 94<br>5.5.4 NDIS支持的WMI操作 95<br>5.5.5 向WMI注册标准微端口OID 95<br>5.5.6 向WMI注册的标准微端口状态 97<br>5.5.7 定制OID与状态指示 98<br>5.5.7.1 填充NDIS_GUID 98<br>5.5.7.2 包括MOF文件 99<br>第六章 微端口的电源管理 100<br>6.1 电源管理的需求与可选的OID 100<br>6.2 网络设备电源状态 101<br>6.3 网络唤醒事件 102<br>6.3.1 连接改变唤醒 102<br>6.3.2 网络唤醒帧 102<br>6.3.3 魔包唤醒 103<br>6.3.4 启用唤醒事件 103<br>6.3.5 处理唤醒事件 103<br>6.4 处理OID_PNP_QUERY_POWER 104<br>6.5 处理OID_PNP_SET_POWER 104<br>6.5.1 转入睡眠状态 104<br>6.5.2 转入工作状态 104<br>6.6 早期微端口的电源管理 105<br>第七章 重置,停止和关闭 106<br>7.1 硬件重置(Reset) 106<br>7.2 停止(Halt)处理程序 106<br>7.3 关闭(Shutdown)处理程序 107<br>第八章 广域网微端口 NIC驱动程序 109<br>8.1 RAS 体系结构 109<br>8.2 NDISWAN 概述 111<br>8.3 网络卡、绑定、和连接 113<br>8.4 广域网微端口驱动程序的实现 114<br>8.4.1 标准广域网微端口驱动程序与局域网微端口驱动程序的区别 115<br>8.4.2 CoNDIS广域网微端口驱动程序的附加特性 115<br>8.4.3 广域网微端口驱动程序提供的服务 116<br>8.4.3.1 注册为广域网微端口驱动程序 116<br>8.4.3.2 查询广域网微端口驱动程序的信息 117<br>8.4.3.3 设置广域网小段口驱动程序的状态 122<br>8.4.3.4 在广域网微端口驱动程序上发送数据 123<br>8.4.4 广域网微端口驱动程序做出的指示 125<br>8.4.4.1 指示从标准广域网微端口驱动程序接收数据 125<br>8.5 广域网包的组帧 128<br>8.5.1 异步帧结构 128<br>8.5.2 X.25帧结构 128<br>8.5.3 ISDN和Switched-56K帧结构 128<br>8.6 标准NDIS之上的电话服务扩展 128<br>8.6.1 NDISTAPI概述 129<br>8.6.2 线路设备、地址和呼叫 129<br>8.6.3 设置和查询请求 130<br>8.6.4 保持状态信息 130<br>8.6.5 建立句柄 131<br>8.6.6 TAPI注册 131<br>8.6.7 TAPI初始化 132<br>8.6.8 打开线路 133<br>8.6.9 接受内入呼叫 133<br>8.6.10 产生TAPI呼叫 134<br>8.6.11 主动事件处理 135<br>8.6.12 Line-Up指示 135<br>8.6.13 关闭呼叫线路 137<br>8.6.14 NDISTAPI接口 139<br>8.7 使用支持电话服务的CoNDIS扩展 143<br>8.7.1 NDPROXY概述 143<br>8.7.2 CoNDIS TAPI注册 144<br>8.7.3 CoNDIS TAPI初始化 144<br>8.7.4 建立外出呼叫 146<br>8.7.5 接受内入呼叫 147<br>8.7.6 CoNDIS TAPI关闭 150<br>8.7.7 语音流对呼叫管理器的要求 151<br>8.7.7.1 响应OID_CO_TAPI_LINE_CAPS查询 151<br>8.7.7.2 为外出呼叫指定参数 151<br>8.7.7.3 为内入呼叫指定参数 152<br>8.7.8 在面向连接NDIS之上支持电话服务的非广域网专用的扩展 152<br>第九章 任务卸载 153<br>9.1 查询任务卸载能力 153<br>9.1.1 报告NIC的校验和性能 154<br>9.1.2 报告NIC的IP安全性性能 155<br>9.1.3 报告NIC的TCP包分段性能 157<br>9.2 启用任务卸载能力 157<br>9.3 停用任务卸载能力 158<br>9.4 访问Per-Packet信息 158<br>9.5 卸载TCP/IP校验和任务 159<br>9.6 卸载IP安全任务 161<br>9.7 卸载大TCP包分段 164<br>9.8 卸载组合 165<br>9.9 使用注册表键值激活和禁止任务卸载 166<br>第十章 负载平衡和失效替换 166<br>10.1 关于LBFO 167<br>10.2 指定对LBFO的支持 168<br>10.3 在微端口驱动程序上实现LBFO 168<br>10.3.1 初始化微端口束 168<br>10.3.2 平衡微端口驱动程序的工作量 169<br>10.3.3 在主微端口失效后提升一个次微端口 169<br>第十一章 快速转发路径 169<br>11.1 关于FFP 170<br>11.1.1 使用一个NIC的FFP 170<br>11.1.2 使用多个NIC的FFP 170<br>11.1.3 IP转发 171<br>11.1.4 FFP和包过滤 171<br>11.2 NIDS中的FFP支持 172<br>11.3 为IP转发在微端口实现FFP 172<br>第十二章 带WDM低级接口的微端口驱动程序 174<br>12.1 WDM低层微端口 174<br>12.2 注册WDM低层的微端口函数 174<br>12.3 初始化WDM低层微端口 175<br>12.4 发布命令与远程设备通信 176<br>12.4.1 在总线上发送包 176<br>12.4.2 在总线上接收包 176<br>12.5 WDM低层的实现要点 176<br>12.6 WDM低层的编译标志 177<br>第十三章 IrDA微端口NIC驱动程序 178<br>13.1 IrDA微端口驱动程序简述 178<br>13.2 IrDA体系结构 179<br>13.3 IrDA协议驱动程序 179<br>13.4 IrDA介质特征 179<br>13.4.1 通信连接速度 180<br>13.4.2 通信连接回转时间 180<br>13.4.3 接收器同步 181<br>13.5 IrLAP帧格式 182<br>13.5.1 帧格式简述 182<br>13.5.2 帧信息的使用 183<br>13.5.3 地址成员 183<br>13.6 IrDA微端口驱动程序包编码方案 183<br>13.6.1 SIR编码 184<br>13.6.2 MIR编码 184<br>13.6.3 FIR编码 184<br>13.7 发送和接收帧序列 185<br>13.8 即插即用 185<br>13.8.1 非即插即用外部串行连接SIR适配器 185<br>13.8.2 非即插即用内部SIR适配器或者象串口一样错误地呈现于外的内部SIR适配器 186<br>13.8.3 即插即用外部串行连接SIR适配器 186<br>13.8.4 即插即用内部SIR适配器 186<br>13.8.5 非即插即用总线连接FIR适配器 187<br>13.8.6 即插即用总线连接FIR适配器 187<br>第三部分NDIS中间层驱动程序和TDI驱动程序 189<br>第一章 NDIS中间层驱动程序 189<br>1.1中间层驱动程序的DriverEntry函数 191<br>1.1.1 注册NDIS中间层驱动程序 191<br>1.1.1.1注册中间层驱动程序的Miniport 192<br>1.1.1.2注册中间层驱动程序的协议 194<br>1.2 中间层驱动程序的动态绑定 196<br>1.2.1 打开中间层驱动程序下层的适配器 197<br>1.2.2 微端口初始化 198<br>1.2.3 中间层驱动程序查询和设置操作 199<br>1.2.4作为面向连接客户程序注册中间层驱动程序 201<br>1.3中间层驱动程序数据包管理 203<br>1.4 中间层驱动程序的限制 205<br>1.5 中间层驱动程序接收数据 206<br>1.5.1下边界面向无连接的中间层驱动程序接收数据 206<br>1.5.2下边界面向连接的中间层驱动程序接收数据 208<br>1.5.3向高层驱动程序指示接收数据包 209<br>1.6通过中间层驱动程序传输数据包 210<br>1.6.1传递介质相关信息 211<br>1.7处理中间层驱动程序的PnP事件和PM事件 212<br>1.7.1处理OID_PNP_XXX查询和设置 213<br>1.7.2中间层驱动程序ProtocolPnPEvent处理程序的实现 214<br>1.7.3处理规定的电源请求 214<br>1.8中间层驱动程序复位操作 215<br>1.9中间层驱动程序拆除绑定操作 216<br>1.10中间层驱动程序状态指示 217<br>第二章 NDIS协议驱动程序 219<br>2.1 协议DriverEntry及其初始化 220<br>2.1.1注册NDIS协议驱动程序 220<br>2.1.2 打开中间层驱动程序低层的适配器 223<br>2.1.3 协议驱动程序查询和设置操作 224<br>2.1.4作为呼叫管理器或者面向连接客户程序进行注册 225<br>2.2 协议驱动程序数据包管理 229<br>2.3 协议驱动程序的动态绑定 230<br>2.4 协议驱动程序接收数据 231<br>2.4.1下边界面向无连接的中间层驱动程序接收数据 231<br>2.4.1.1 在中间层驱动程序中实现ProtocolReceivePacket处理程序 232<br>2.4.1.2 在协议驱动程序中实现ProtocolReceive处理程序 233<br>2.4.1.3 从面向无连接协议驱动程序中访问OOB数据信息 234<br>2.4.2 面向连接协议驱动程序接收数据 234<br>2.4.2.1 ProtocolCoReceivePacket处理程序实现 235<br>2.4.2.2 从面向连接协议驱动程序中访问OOB数据信息 235<br>2.5 发送协议驱动程序创建的数据包 236<br>2.5.1 从面向无连接协议驱动程序发送数据包 236<br>2.5.1.1面向无连接协议驱动程序传递介质相关信息 237<br>2.5.2 面向连接协议驱动程序发送数据包 238<br>2.5.2.1面向连接协议驱动程序传递介质相关信息 238<br>2.6处理协议驱动程序的PnP事件和PM事件 239<br>2.7协议驱动程序复位操作 240<br>2.8协议驱动程序拆除绑定操作 241<br>2.9协议驱动程序状态指示 241<br>第三章 TDI传输器及其客户 243<br>3.1 传输驱动程序接口(TDI) 243<br>3.2 TDI设备对象 245<br>3.3 TDI文件对象 246<br>3.3.1代表传输地址的文件对象 247<br>3.3.2代表连接端点的文件对象 247<br>3.3.3代表控制信道的文件对象 248<br>3.4 TDI传输驱动程序例程 248<br>3.5 TDI核心模式客户交互 249<br>3.6 TDI请求及事件 250<br>第四章 TDI例程、宏和回调 251<br>4.1 TDI驱动程序初始化 251<br>4.1.1 注册TDI传输驱动程序 252<br>4.1.2 卸载和注销TDI传输驱动程序 252<br>4.2 TDI驱动程序调度例程 253<br>4.3 TDI IOCTL请求 254<br>4.4 TDI 客户回调 255<br>4.5 TDI 库函数和宏 257<br>第五章 TDI操作 260<br>5.1打开传输地址 260<br>5.2打开连接端点 261<br>5.3打包并提交IOCTL请求 262<br>5.4设置和查询信息 262<br>5.5建立端端连接 263<br>5.6发送和接收面向连接数据 264<br>5.7发送和接收无连接数据 266<br>5.8面向连接和面向无连接传输 267<br>5.9请求传输相关操作 268<br>5.10接收错误通知 268<br>5.11断开端端连接 268<br>5.12关闭连接端点 269<br>5.13关闭传输地址和控制信道 269<br>第六章Windows Sockets的传输助手DLLS 271<br>6.1 Windows Sockets Helper DLL结构 271<br>6.2用WSH DLL通信 271<br>6.3配置WSH DLL 272<br>6.4WSH DLL同步 272<br>6.5用WSH DLL支持连接和断开数据 273<br>6.5.1客户应用程序和连接数据 273<br>6.5.2服务器应用程序和连接数据 273<br>6.5.3断连(disconnect)数据 274<br>6.6WSH DLL函数总览 274<br>第四部分面向连接的网络驱动程序接口标准(NDIS) 276<br>第一章 面向连接的网络驱动程序接口标准(NDIS) 276<br>1.1面向连接环境 276<br>1.2使用AFs,VCs,SAP和Parties 277<br>1.2.1地址族 277<br>1.2.2虚连接 277<br>1.2.3 SAPs 278<br>1.2.4 Parties 278<br>1.3服务质量 278<br>1.4MCM和呼叫管理器有何不同 278<br>1.4.1初始化的不同 279<br>1.4.2对NdisXxx函数调用的不同 279<br>1.4.3虚连接的不同 279<br>1.5面向连接的时间特性 280<br>1.6面向连接操作 280<br>1.6.1面向连接操作总结 280<br>1.6.1.1由客户执行的面向连接操作 280<br>1.6.1.2由呼叫管理器执行的面向连接操作 281<br>1.6.1.3由微端口执行的面向连接操作 282<br>1.6.2地址族和SAPs上的操作 283<br>1.6.2.1注册并打开一个地址族 283<br>1.6.2.2注册一个SAP 284<br>1.6.2.3注销SAP 285<br>1.6.2.4关闭一个地址族 285<br>1.6.3 VCs上的操作 286<br>1.6.3.1创建VC 286<br>1.6.3.2激活VC 287<br>1.6.3.3使VC去活 288<br>1.6.3.4删除VC 289<br>1.6.4创建呼叫 289<br>1.6.4.1进行呼叫 290<br>1.6.4.2指示内入呼叫 291<br>1.6.5改变活动VC的QoS 292<br>1.6.5.1客户发起的改变呼叫参数请求。 292<br>1.6.5.2改变呼叫参数的内入请求 293<br>1.6.6增加和删除Parties 293<br>1.6.6.1把一个Party加入到多点呼叫 293<br>1.6.6.2从多点呼叫中删除Party 294<br>1.6.6.3从多点呼叫中删除一个Party的内入请求 295<br>1.6.7发送并接收数据 295<br>1.6.7.1在VC上发送包 295<br>1.6.7.2接收VC上的包 296<br>1.6.8断开呼叫 297<br>1.6.8.1客户发起的关闭呼叫请求 297<br>1.6.8.2关闭呼叫的内入请求 298<br>1.6.9获取并设置信息 298<br>1.6.9.1查询或设置信息 298<br>1.6.9.2指示微端口状态 299<br>1.6.10重置 299<br>第五部分 安装网络组件 301<br>第一章 安装网络组件 301<br>1.1用于安装网络组件的组件和文件 301<br>1.2创建网络INF文件 302<br>1.2.1网络INFS文件名的约定 302<br>1.2.2网络INF文件的版本节 302<br>1.2.3网络INF文件的模型节 303<br>1.2.4 INF文件的DDInstall节 304<br>1.2.5删除节 306<br>1.2.6 ControlFlags节 306<br>1.2.7网络INF文件的add-registry-sections 306<br>1.2.7.1设置静态参数 307<br>1.2.7.2 为WAN适配器说明WAN端点 307<br>1.2.7.3为ISDN适配器说明ISDN键和值 307<br>1.2.7.4安装多协议WAN NICs 309<br>1.2.7.5请求安装另一个网络组件 310<br>1.2.7.6说明NetCLient组件的名字和提供者 310<br>1.2.7.7增加HelpText值 311<br>1.2.7.8为通知对象增加注册值 311<br>1.2.7.9向Ndi键增加服务相关值 311<br>1.2.7.10说明绑定接口 312<br>1.2.7.11为高级属性页说明配置参数 314<br>1.2.7.12为网络适配器说明定制属性页 315<br>1.2.7.13说明过滤器服务值 315<br>1.2.7.14说明束成员关系 317<br>1.2.7.15 Window 2000中不用的 Window 95/98 Ndi值和键 317<br>1.2.8 DDInstall.Service节 318<br>1.2.9 NetworkProrider和PrintProvider节 318<br>1.2.9.1包含一个NetworkProvider节 319<br>1.2.9.2 包括一个PrintProvider节 319<br>1.2.10 Winsock节 320<br>1.2.11网络组件安装需求总结 322<br>1.2.11.1网络适配器的安装需求 322<br>1.2.11.2网络协议安装要求 323<br>1.2.11.3中间层网络驱动程序的安装需求 324<br>1.2.11.4网络过滤器驱动程序的安装需求 325<br>1.2.11.5网络客户的安装需求 326<br>1.2.11.6网络服务的安装请求 327<br>第二章 网络组件的通知对象 328<br>2.1关于通知对象 328<br>2.1.1 通知对象图 329<br>2.1.2通知类型 329<br>2.1.3网络组件的安装 329<br>2.1.4删除网络组件 330<br>2.1.5升级网络组件 330<br>2.1.6显示并改变属性 330<br>2.1.7网络配置 331<br>2.2创建通知对象 331<br>2.2.1装载通知对象DLL和类对象 331<br>2.2.2定义通知对象 332<br>2.2.3创建并初始化通知对象实例 332<br>2.2.4安装,升级和删除组件 333<br>2.2.5为组件生成属性页 333<br>2.2.6设置环境来显示属性 334<br>2.2.7评价网络配置的变化 334<br>2.2.8将组件变化加入注册表 335<br>2.2.9配置组件驱动程序 335<br><br>
第 一 章 概述 1-1 简述计算机程序设计语言的发展历程。 解: 迄今为止计算机程序设计语言的发展经历了机器语言、汇编语言、高级语言等阶段,C++语言是一种面向对象的编程语言,也属于高级语言。 1-2 面向对象的编程语言有哪些特点? 解: 面向对象的编程语言与以往各种编程语言有根本的不同,它设计的出发点就是为了能更直接的描述客观世界中存在的事物以及它们之间的关系。面向对象的编程语言将客观事物看作具有属性和行为的对象,通过抽象找出同一类对象的共同属性(静态特征)和行为(动态特征),形成类。通过类的继承与多态可以很方便地实现代码重用,大大缩短了软件开发周期,并使得软件风格统一。因此,面向对象的编程语言使程序能够比较直接地反问题域的本来面目,软件开发人员能够利用人类认识事物所采用的一般思维方法来进行软件开发。C++语言是目前应用最广的面向对象的编程语言。 1-3 什么是结构化程序设计方法?这种方法有哪些优点和缺点? 解: 结构化程序设计的思路是:自顶向下、逐步求精;其程序结构是按功能划分为若干个基本模块;各模块之间的关系尽可能简单,在功能上相对独立;每一模块内部均是由顺序、选择和循环三种基本结构组成;其模块化实现的具体方法是使用子程序。结构化程序设计由于采用了模块分解与功能抽象,自顶向下、分而治之的方法,从而有效地将一个较复杂的程序系统设计任务分解成许多易于控制和处理的子任务,便于开发和维护。 虽然结构化程序设计方法具有很多的优点,但它仍是一种面向过程的程序设计方法,它把数据和处理数据的过程分离为相互独立的实体。当数据结构改变时,所有相关的处理过程都要进行相应的修改,每一种相对于老问题的新方法都要带来额外的开销,程序的可重用性差。 由于图形用户界面的应用,程序运行由顺序运行演变为事件驱动,使得软件使用起来越来越方便,但开发起来却越来越困难,对这种软件的功能很难用过程来描述和实现,使用面向过程的方法来开发和维护都将非常困难。 1-4 什么是对象?什么是面向对象方法?这种方法有哪些特点? 解: 从一般意义上讲,对象是现实世界中一个实际存在的事物,它可以是有形的,也可以是无形的。对象是构成世界的一个独立单位,它具有自己的静态特征和动态特征。面向对象方法中的对象,是系统中用来描述客观事物的一个实体,它是用来构成系统的一个基本单位,由一组属性和一组行为构成。 面向对象的方法将数据及对数据的操作方法放在一起,作为一个相互依存、不可分离的整体--对象。对同类型对象抽象出其共性,形成类。类中的大多数数据,只能用本类的方法进行处理。类通过一个简单的外部接口,与外界发生关系,对象与对象之间通过消息进行通讯。这样,程序模块间的关系更为简单,程序模块的独立性、数据的安全性就有了良好的保障。通过实现继承与多态性,还可以大大提高程序的可重用性,使得软件的开发和维护都更为方便。 面向对象方法所强调的基本原则,就是直接面对客观存在的事物来进行软件开发,将人们在日常生活中习惯的思维方式和表达方式应用在软件开发中,使软件开发从过分专业化的方法、规则和技巧中回到客观世界,回到人们通常的思维。 1-5 什么叫做封装? 解: 封装是面向对象方法的一个重要原则,就是把对象的属性和服务结合成一个独立的系统单位,并尽可能隐蔽对象的内部细节。 1-6 面向对象的软件工程包括哪些主要内容? 解: 面向对象的软件工程是面向对象方法在软件工程领域的全面应用,它包括面向对象的分析(OOA)、面向对象的设计(OOD)、面向对象的编程(OOP)、面向对象的测试(OOT)和面向对象的软件维护(OOSM)等主要内容。 1-7 简述计算机内部的信息可分为几类? 解: 计算机内部的信息可以分成控制信息和数据信息二大类;控制信息可分为指令和控制字两类;数据信息可分为数值信息和非数值信息两类。 1-8 什么叫二进制?使用二进制有何优点和缺点? 解: 二进制是基数为2,每位的权是以2 为底的幂的进制,遵循逢二进一原则,基本符号为0和1。采用二进制码表示信息,有如下几个优点:1.易于物理实现;2.二进制数运算简单;3.机器可靠性高;4.通用性强。其缺点是它表示数的容量较小,表示同一个数,二进制较其他进制需要更多的位数。 1-9 请将以下十进制数值转换为二进制和十六进制补码: (1)2 (2)9 (3)93 (4)-32 (5)65535 (6)-1 解: (1) (2)10 = (10)2 = (2)16 (2) (9)10 = (1001)2 = (9)16 (3) (93)10 = (1011101)2 = (5D)16 (4) (-32)10 = (11100000)2 = (E0)16 (5) (65535)10 = (11111111 11111111)2 = (FFFF)16 (6) (-1)10 = (11111111 11111111)2 = (FFFF)16 1-10 请将以下数值转换为十进制: (1)(1010)2 (2)(10001111)2 (3)(01011111 11000011)2 (4)(7F)16 (5)(2D3E)16 (6)(F10E)16 解: (1)(1010)2 = (10)10 (2)(10001111)2 = (143)10 (3)(01011111 11000011)2 = (24515)10 (4)(7F)16 = (127)10 (5)(2D3E)16 = (11582)10 (6)(F10E)16 = (61710)10 1-11 简要比较原码、反码、补码等几种编码方法。 解: 原码:将符号位数字化为 0 或 1,数的绝对值与符号一起编码,即所谓"符号──绝对值表示"的编码。 正数的反码和补码与原码表示相同。 负数的反码与原码有如下关系: 符号位相同(仍用1表示),其余各位取反(0变1,1变0)。 补码由该数反码的最末位加1求得。 第 二 章 C++简单程序设计 2-1 C++语言有那些主要特点和优点? 解: C++语言的主要特点表现在两个方面,一是全面兼容C,二是支持面向对象的方法。C++是一个更好的C,它保持了C的简洁、高效、接近汇编语言、具有良好的可读性和可移植性等特点,对C的类型系统进行了改革和扩充,因此C++比C更安全,C++的编译系统能检查出更多的类型错误。 C++语言最重要的特点是支持面向对象。 2-2 下列标识符哪些是合法的? Program, -page, _lock, test2, 3in1, @mail, A_B_C_D 解: Program, _lock, test2, A_B_C_D是合法的标识符,其它的不是。 2-3 例2.1中每条语句的作用是什么? #include void main(void) { cout<<"Hello!\n"; cout<<"Welcome to c++!\n"; } 解: #include //指示编译器将文件iostream.h中的代码 //嵌入到该程序中该指令所在的地方 void main() //主函数名,void 表示函数没有返回值 { //函数体标志 cout<<"Hello!\n"; //输出字符串Hello!到标准输出设备(显示器)上。 cout<<"Welcome to c++!\n"; //输出字符串Welcome to c++! } 在屏幕输出如下: Hello! Welcome to c++! 2-4 使用关键字const而不是#define语句的好处有哪些? 解: const定义的常量是有类型的,所以在使用它们时编译器可以查错;而且,这些变量在调试时仍然是可见的。 2-5 请写出C++语句声明一个常量PI,值为3.1416;再声明一个浮点型变量a,把PI的值赋给a。 解: const float PI = 3.1416; float a = PI; 2-6 在下面的枚举类型中,Blue的值是多少? enum COLOR { WHITE, BLACK = 100, RED, BLUE, GREEN = 300 }; 解: Blue = 102 2-7 注释有什么作用?C++中有哪几种注释的方法?他们之间有什么区别? 解: 注释在程序中的作用是对程序进行注解和说明,以便于阅读。编译系统在对源程序进行编译时不理会注释部分,因此注释对于程序的功能实现不起任何作用。而且由于编译时忽略注释部分,所以注释内容不会增加最终产生的可执行程序的大小。适当地使用注释,能够提高程序的可读性。在C++中,有两种给出注释的方法:一种是延用C语言方法,使用"/*"和"*/"括起注释文字。另一种方法是使用"//",从"//"开始,直到它所在行的行尾,所有字符都被作为注释处理。 2-8 什么叫做表达式?x = 5 + 7是一个表达式吗?它的值是多少? 解: 任何一个用于计算值的公式都可称为表达式。x = 5 + 7是一个表达式,它的值为12。 2-9 下列表达式的值是多少? 1. 201 / 4 2. 201 % 4 3. 201 / 4.0 解: 1. 50 2. 1 3. 50.25 2-10 执行完下列语句后,a、b、c三个变量的值为多少? a = 30; b = a++; c = ++a; 解: a:32 ; b:30 ; c:32; 2-11 在一个for循环中,可以初始化多个变量吗?如何实现? 解: 在for循环设置条件的第一个";"前,用,分隔不同的赋值表达式。 例如: for (x = 0, y = 10; x < 100; x++, y++) 2-12 执行完下列语句后,n的值为多少? int n; for (n = 0; n < 100; n++) 解: n的值为100 2-13 写一条for语句,计数条件为n从100到200,步长为2;然后用while和do…while语句完成同样的循环。 解: for循环: for (int n = 100; n <= 200; n += 2); while循环: int x = 100; while (n <= 200) n += 2; do…while循环: int n = 100; do { n += 2; } while(n y) x = y; else // y > x || y == x y = x; 2-17 修改下面这个程序中的错误,改正后它的运行结果是什么? #include void main() int i int j; i = 10; /* 给i赋值 j = 20; /* 给j赋值 */ cout << "i + j = << i + j; /* 输出结果 */ return 0; } 解: 改正: #include int main() { int i; int j; i = 10; // 给i赋值 j = 20; /* 给j赋值 */ cout << "i + j = " << i + j; /* 输出结果 */ return 0; } 程序运行输出: i + j = 30 2-18 编写一个程序,运行时提示输入一个数字,再把这个数字显示出来。 解: 源程序: #include int main() { int i; cout <> i; cout << "您输入一个数字是" << i << endl; return 0; } 程序运行输出: 请输入一个数字:5 您输入一个数字是5 2-19 C++有哪几种数据类型?简述其值域。编程显示你使用的计算机中的各种数据类型的字节数。 解: 源程序: #include int main() { cout << "The size of an int is:\t\t" << sizeof(int) << " bytes.\n"; cout << "The size of a short int is:\t" << sizeof(short) << " bytes.\n"; cout << "The size of a long int is:\t" << sizeof(long) << " bytes.\n"; cout << "The size of a char is:\t\t" << sizeof(char) << " bytes.\n"; cout << "The size of a float is:\t\t" << sizeof(float) << " bytes.\n"; cout << "The size of a double is:\t" << sizeof(double) << " bytes.\n"; return 0; } 程序运行输出: The size of an int is: 4 bytes. The size of a short int is: 2 bytes. The size of a long int is: 4 bytes. The size of a char is: 1 bytes. The size of a float is: 4 bytes. The size of a double is: 8 bytes. 2-20 打印ASCII码为32~127的字符。 解: #include int main() { for (int i = 32; i<128; i++) cout << (char) i; return 0; } 程序运行输出: !"#$%G'()*+,./0123456789:;?@ABCDEFGHIJKLMNOP_QRSTUVWXYZ[\]^'abcdefghijklmnopqrstuvwxyz~s 2-21 运行下面的程序,观察其输出,与你的设想是否相同? #include int main() { unsigned int x; unsigned int y = 100; unsigned int z = 50; x= y - z; cout << "Difference is: " << x; x = z - y; cout << "\nNow difference is: " << x <<endl; return 0; } 解: 程序运行输出: Difference is: 50 Now difference is: 4294967246 注意,第二行的输出并非 -50,注意x、y、z的数据类型。 2-22 运行下面的程序,观察其输出,体会i++与++i的差别。 #include int main() { int myAge = 39; // initialize two integers int yourAge = 39; cout << "I am: " << myAge << " years old.\n"; cout << "You are: " << yourAge << " years old\n"; myAge++; // postfix increment ++yourAge; // prefix increment cout << "One year passes...\n"; cout << "I am: " << myAge << " years old.\n"; cout << "You are: " << yourAge << " years old\n"; cout << "Another year passes\n"; cout << "I am: " << myAge++ << " years old.\n"; cout << "You are: " << ++yourAge << " years old\n"; cout << "Let's print it again.\n"; cout << "I am: " << myAge << " years old.\n"; cout << "You are: " << yourAge << " years old\n"; return 0; } 解: 程序运行输出: I am 39 years old You are 39 years old One year passes I am 40 years old You are 40 years old Another year passes I am 40 years old You are 41 years old Let's print it again I am 41 years old You are 41 years old 2-23 什么叫常量?什么叫变量? 解: 所谓常量是指在程序运行的整个过程中其值始终不可改变的量,除了用文字表示常量外,也可以为常量命名,这就是符号常量;在程序的执行过程中其值可以变化的量称为变量,变量是需要用名字来标识的。 2-24 变量有哪几种存储类型? 解: 变量有以下几种存储类型: auto存储类型:采用堆栈方式分配内存空间,属于一时性存储,其存储空间可以被若干变量多次覆盖使用; register存储类型:存放在通用寄存器中; extern存储类型:在所有函数和程序段中都可引用; static存储类型:在内存中是以固定地址存放的,在整个程序运行期间都有效。 2-25 写出下列表达式的值: 1. 2 < 3 && 6 < 9 2. ! ( 4 5) || (6 > 2 解: 1. 1 2. -1 3. 0 4. 0 2-28 编写一个完整的程序,实现功能:向用户提问"现在正在下雨吗?",提示用户输入Y或N。若输入为Y,显示"现在正在下雨。"; 若输入为N,显示"现在没有下雨。";否则继续提问"现在正在下雨吗?" 解: 源程序: #include #include void main() { char flag; while(1) { cout <> flag; if ( toupper(flag) == 'Y') { cout << "现在正在下雨。"; break; } if ( toupper(flag) == 'N') { cout << "现在没有下雨。"; break; } } } 程序运行输出: 现在正在下雨吗?(Yes or No):x 现在正在下雨吗?(Yes or No):l 现在正在下雨吗?(Yes or No):q 现在正在下雨吗?(Yes or No):n 现在没有下雨。 或: 现在正在下雨吗?(Yes or No):y 现在正在下雨。 2-29 编写一个完整的程序,运行时向用户提问"你考试考了多少分?(0~100)",接收输入后判断其等级,显示出来。规则如下: 解: #include void main() { int i,score; cout <> score; if (score>100 || score<0) cout << "分数值必须在0到100之间!"; else { i = score/10; switch (i) { case 10: case 9: cout << "你的成绩为优!"; break; case 8: cout << "你的成绩为良!"; break; case 7: case 6: cout << "你的成绩为中!"; break; default: cout << "你的成绩为差!"; } } } 程序运行输出: 你考试考了多少分?(0~100):85 你的成绩为良! 2-30 (1)实现一个简单的菜单程序,运行时显示"Menu: A(dd) D(elete) S(ort) Q(uit), Select one:"提示用户输入,A表示增加,D表示删除,S表示排序,Q表示退出,输入为A、D、S时分别提示"数据已经增加、删除、排序。"输入为Q时程序结束。要求使用if … else语句进行判断,用break、continue控制程序流程。 解: #include #include void main() { char choice,c; while(1) { cout <> c; choice = toupper(c); if (choice == 'A') { cout << "数据已经增加. " << endl; continue; } else if (choice == 'D') { cout << "数据已经删除. " << endl; continue; } else if (choice == 'S') { cout << "数据已经排序. " << endl; continue; } else if (choice == 'Q') break; } } 程序运行输出: Menu: A(dd) D(elete) S(ort) Q(uit), Select one:a 数据已经增加. Menu: A(dd) D(elete) S(ort) Q(uit), Select one:d 数据已经删除. Menu: A(dd) D(elete) S(ort) Q(uit), Select one:s 数据已经排序. Menu: A(dd) D(elete) S(ort) Q(uit), Select one:q (2)实现一个简单的菜单程序,运行时显示"Menu: A(dd) D(elete) S(ort) Q(uit), Select one:"提示用户输入,A表示增加,D表示删除,S表示排序,Q表示退出,输入为A、D、S时分别提示"数据已经增加、删除、排序。"输入为Q时程序结束。要求使用Switch语句。 解: 源程序: #include #include void main() { char choice; while(1) { cout <> choice; switch(toupper(choice)) { case 'A': cout << "数据已经增加. " << endl; break; case 'D': cout << "数据已经删除. " << endl; break; case 'S': cout << "数据已经排序. " << endl; break; case 'Q': exit(0); break; default: ; } } } 程序运行输出: Menu: A(dd) D(elete) S(ort) Q(uit), Select one:a 数据已经增加. Menu: A(dd) D(elete) S(ort) Q(uit), Select one:d 数据已经删除. Menu: A(dd) D(elete) S(ort) Q(uit), Select one:s 数据已经排序. Menu: A(dd) D(elete) S(ort) Q(uit), Select one:q 2-31 用穷举法找出1~100间的质数,显示出来。分别使用while,do-while,for循环语句实现。 解: 源程序: 使用while循环语句: #include #include void main() { int i,j,k,flag; i = 2; while(i <= 100) { flag = 1; k = sqrt(i); j = 2; while (j <= k) { if(i%j == 0) { flag = 0; break; } j++; } if (flag) cout << i << "是质数." << endl; i++; } } 使用do…while循环语句: #include #include void main() { int i,j,k,flag; i = 2; do{ flag = 1; k = sqrt(i); j = 2; do{ if(i%j == 0) { flag = 0; break; } j++; }while (j <= k); if (flag) cout << i << "是质数." << endl; i++; }while(i <= 100); } 使用for循环语句: #include #include void main() { int i,j,k,flag; for(i = 2; i <= 100; i++) { flag = 1; k = sqrt(i); for (j = 2; j <= k; j++) { if(i%j == 0) { flag = 0; break; } } if (flag) cout << i << "是质数." << endl; } } 程序运行输出: 2是质数. 3是质数. 5是质数. 7是质数. 11是质数. 13是质数. 17是质数. 19是质数. 23是质数. 29是质数. 31是质数. 37是质数. 41是质数. 43是质数. 47是质数. 53是质数. 59是质数. 61是质数. 67是质数. 71是质数. 73是质数. 79是质数. 83是质数. 89是质数. 97是质数. 2-32 比较Break语句与Continue语句的不同用法。 解: Break使程序从循环体和switch语句内跳出,继续执行逻辑上的下一条语句,不能用在别处; continue 语句结束本次循环,接着开始判断决定是否继续执行下一次循环; 2-33 定义一个表示时间的结构体,可以精确表示年、月、日、小时、分、秒;提示用户输入年、月、日、小时、分、秒的值,然后完整地显示出来。 解: 源程序见"实验指导"部分实验二 2-34 在程序中定义一个整型变量,赋以1~100的值,要求用户猜这个数,比较两个数的大小,把结果提示给用户,直到猜对为止。分别使用while、do…while语句实现循环。 解: //使用while语句 #include void main() { int n = 18; int m = 0; while(m != n) { cout <> m; if (n > m) cout << "你猜的值太小了!" << endl; else if (n < m) cout << "你猜的值太大了!" << endl; else cout << "你猜对了!" << endl; } } //使用do…while语句 #include void main() { int n = 18; int m = 0; do{ cout <> m; if (n > m) cout << "你猜的值太小了!" << endl; else if (n < m) cout << "你猜的值太大了!" << endl; else cout << "你猜对了!" << endl; }while(n != m); } 程序运行输出: 请猜这个数的值为多少?(0~~100):50 你猜的值太大了! 请猜这个数的值为多少?(0~~100):25 你猜的值太大了! 请猜这个数的值为多少?(0~~100):10 你猜的值太小了! 请猜这个数的值为多少?(0~~100):15 你猜的值太小了! 请猜这个数的值为多少?(0~~100):18 你猜对了! 2-35 定义枚举类型weekday,包括Sunday到Saturday七个元素在程序中定义weekday类型的变量,对其赋值,定义整型变量,看看能否对其赋weekday类型的值。 解: #include enum weekday { Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday }; void main() { int i; weekday d = Thursday; cout << "d = " << d << endl; i = d; cout << "i = " << i << endl; d = (weekday)6; cout << "d = " << d << endl; d = weekday( 4 ); cout << "d = " << d << endl; } 程序运行输出: d = 4 i = 4 d = 6 d = 4 2-36口袋中有红、黄、蓝、白、黑五种颜色的球若干个,每次从口袋中取出三个不同颜色的球,问有多少种取法。 解: #include using namespace std; int main() { enum color{red,yellow,blue,white,black}; enum color pri; int n,loop,i,j,k; char c; n=0; for(i=red;i<=black;i++) for(j=red;j<=black;j++) if(i!=j) { for(k=red;k<black;k++) if((k!=i)&&(k!=j)) { n=n+1; cout.width(4); cout<<n; for(loop=1;loop<=3;loop++) { switch(loop) { case 1: pri=(enum color)i; break; case 2: pri=(enum color)j; break; case 3: pri=(enum color)k; break; default: break; } switch(pri) { case red:cout<<"red";break; case yellow:cout<<"yellow";break; case blue:cout<<"blue";break; case white:cout<<"white";break; case black:cout<<"black";break; default: break; } } cout<<endl; } } cout<<"total:"<<n<<endl; } 2-37输出九九算表 #include #include using namespace std; int main() { int i,j; for(i=1;i<5;i++) cout<<setw(4)<<i; cout<<endl; cout<<endl; for(i=1;i<5;i++) { for(j=1;j<5;j++) cout<<setw(4)<<(i*j); cout<<endl; } } 第三章 函数 3-1 C++中的函数是什么?什么叫主调函数,什么叫被调函数,二者之间有什么关系?如何调用一个函数? 解: 一个较为复杂的系统往往需要划分为若干子系统,高级语言中的子程序就是用来实现这种模块划分的。C和C++语言中的子程序就体现为函数。调用其它函数的函数被称为主调函数,被其它函数调用的函数称为被调函数。一个函数很可能既调用别的函数又被另外的函数调用,这样它可能在某一个调用与被调用关系中充当主调函数,而在另一个调用与被调用关系中充当被调函数。 调用函数之前先要声明函数原型。按如下形式声明: 类型标识符 被调函数名 (含类型说明的形参表); 声明了函数原型之后,便可以按如下形式调用子函数: 函数名(实参列表) 3-2 观察下面程序的运行输出,与你设想的有何不同?仔细体会引用的用法。 源程序: #include int main() { int intOne; int &rSomeRef; = intOne; intOne = 5; cout << "intOne:\t\t" << intOne << endl; cout << "rSomeRef:\t" << rSomeRef << endl; int intTwo = 8; rSomeRef = intTwo; // not what you think! cout << "\nintOne:\t\t" << intOne << endl; cout << "intTwo:\t\t" << intTwo << endl; cout << "rSomeRef:\t" << rSomeRef << endl; return 0; } 程序运行输出: intOne: 5 rSomeRef: 5 intOne: 8 intTwo: 8 rSomeRef: 8 3-3 比较值调用和引用调用的相同点与不同点。 解: 值调用是指当发生函数调用时,给形参分配内存空间,并用实参来初始化形参(直接将实参的值传递给形参)。这一过程是参数值的单向传递过程,一旦形参获得了值便与实参脱离关系,此后无论形参发生了怎样的改变,都不会影响到实参。 引用调用将引用作为形参,在执行主调函数中的调用语句时,系统自动用实参来初始化形参。这样形参就成为实参的一个别名,对形参的任何操作也就直接作用于实参。 3-4 什么叫内联函数?它有哪些特点? 解: 定义时使用关键字 inline的函数叫做内联函数; 编译器在编译时在调用处用函数体进行替换,节省了参数传递、控制转移等开销; 内联函数体内不能有循环语句和switch语句; 内联函数的定义必须出现在内联函数第一次被调用之前; 对内联函数不能进行异常接口声明; 3-5 函数原型中的参数名与函数定义中的参数名以及函数调用中的参数名必须一致吗? 解: 不必一致,所有的参数是根据位置和类型而不是名字来区分的。 3-6 重载函数时通过什么来区分? 解: 重载的函数的函数名是相同的,但它们的参数的个数和数据类型不同,编译器根据实参和形参的类型及个数的最佳匹配,自动确定调用哪一个函数。 3-7 编写函数,参数为两个unsigned short int型数,返回值为第一个参数除以第二个参数的结果,数据类型为short int;如果第二个参数为0,则返回值为-1。在主程序中实现输入输出。 解: 源程序: #include short int Divider(unsigned short int a, unsigned short int b) { if (b == 0) return -1; else return a/b; } typedef unsigned short int USHORT; typedef unsigned long int ULONG; int main() { USHORT one, two; short int answer; cout <> one; cout <> two; answer = Divider(one, two); if (answer > -1) cout << "Answer: " << answer; else cout << "Error, can't divide by zero!"; return 0; } 程序运行输出: Enter two numbers. Number one:8 Number two:2 Answer: 4 3-8 编写函数把华氏温度转换为摄氏温度,公式为:C = (F - 32) * 5/9; 在主程序中提示用户输入一个华氏温度,转化后输出相应的摄氏温度。 解: 源程序见"实验指导"部分实验三 3-9 编写函数判断一个数是否是质数,在主程序中实现输入、输出。 解: #include #include int prime(int i); //判一个数是否是质数的函数 void main() { int i; cout <> i; if (prime(i)) cout << i << "是质数." << endl; else cout << i << "不是质数." << endl; } int prime(int i) { int j,k,flag; flag = 1; k = sqrt(i); for (j = 2; j <= k; j++) { if(i%j == 0) { flag = 0; break; } } if (flag) return 1; else return 0; } 程序运行输出: 请输入一个整数:1151 1151是质数. 3-10 编写函数求两个整数的最大公约数和最小公倍数。 解: 源程序: #include #include int fn1(int i,int j); //求最大公约数的函数 void main() { int i,j,x,y; cout <> i ; cout <> j ; x = fn1(i,j); y = i * j / x; cout << i << "和" << j << "的最大公约数是:" << x << endl; cout << i << "和" << j << "的最小公倍数是:" << y << endl; } int fn1(int i, int j) { int temp; if (i < j) { temp = i; i = j; j = i; } while(j != 0) { temp = i % j; i = j; j = temp; } return i; } 程序运行输出: 请输入一个正整数:120 请输入另一个正整数:72 120和72的最大公约数是:24 120和72的最小公倍数是:360 3-11 什么叫作嵌套调用?什么叫作递归调用? 解: 函数允许嵌套调用,如果函数1调用了函数2,函数2再调用函数3,便形成了函数的嵌套调用。 函数可以直接或间接地调用自身,称为递归调用。 3-12 在主程序中提示输入整数n,编写函数用递归的方法求1 + 2 + … + n的值。 解: #include #include int fn1(int i); void main() { int i; cout <> i ; cout << "从1累加到" <<i << "的和为:" << fn1(i) << endl; } int fn1(int i) { if (i == 1) return 1; else return i + fn1(i -1); } 程序运行输出: 请输入一个正整数:100 从1累加到100的和为:5050 3-13 编写递归函数GetPower(int x, int y)计算x的y次幂, 在主程序中实现输入输出。 解: 源程序: #include long GetPower(int x, int y); int main() { int number, power; long answer; cout <> number; cout <> power; answer = GetPower(number,power); cout << number << " to the " << power << "th power is " <<answer <2; fib(1) = fib(2) = 1;观察递归调用的过程。 解: 源程序见"实验指导"部分实验三 3-15 用递归的方法编写函数求n阶勒让德多项式的值,在主程序中实现输入、输出; 解: #include float p(int n, int x); void main() { int n,x; cout <> n; cout <> x; cout << "n = " << n << endl; cout << "x = " << x << endl; cout << "P" << n << "(" << x << ") = " << p(n,x) << endl; } float p(int n, int x) { if (n == 0) return 1; else if (n == 1) return x; else return ((2*n-1)*x*p(n-1,x) - (n-1)*p(n-2,x)) /n ; } 程序运行输出: 请输入正整数n:1 请输入正整数x:2 n = 1 x = 2 P1(2) = 2 请输入正整数n:3 请输入正整数x:4 n = 3 x = 4 P3(4) = 154 第 四 章 类 4-1 解释public和private的作用,公有类型成员与私有类型成员有些什么区别? 解: 公有类型成员用public关键字声明,公有类型定义了类的外部接口;私有类型的成员用private关键字声明,只允许本类的函数成员来访问,而类外部的任何访问都是非法的,这样,私有的成员就整个隐蔽在类中,在类的外部根本就无法看到,实现了访问权限的有效控制。 4-2 protected关键字有何作用? 解: protected用来声明保护类型的成员,保护类型的性质和私有类型的性质相似,其差别在于继承和派生时派生类的成员函数可以访问基类的保护成员。 4-3 构造函数和析构函数有什么作用? 解: 构造函数的作用就是在对象被创建时利用特定的值构造对象,将对象初始化为一个特定的状态,使此对象具有区别于彼对象的特征,完成的就是是一个从一般到具体的过程,构造函数在对象创建的时候由系统自动调用。 析构函数与构造函数的作用几乎正好相反,它是用来完成对象被删除前的一些清理工作,也就是专门作扫尾工作的。一般情况下,析构函数是在对象的生存期即将结束的时刻由系统自动调用的,它的调用完成之后,对象也就消失了,相应的内存空间也被释放。 4-4 数据成员可以为公有的吗?成员函数可以为私有的吗? 解: 可以,二者都是合法的。数据成员和成员函数都可以为公有或私有的。但数据成员最好定义为私有的。 4-5 已知class A中有数据成员int a,如果定义了A的两个对象A1、A2,它们各自的数据成员a的值可以不同吗? 解: 可以,类的每一个对象都有自己的数据成员。 4-6 什么叫做拷贝构造函数?拷贝构造函数何时被调用? 解: 拷贝构造函数是一种特殊的构造函数,具有一般构造函数的所有特性,其形参是本类的对象的引用,其作用是使用一个已经存在的对象,去初始化一个新的同类的对象。在以下三种情况下会被调用:在当用类的一个对象去初始化该类的另一个对象时;如果函数的形参是类对象,调用函数进行形参和实参结合时;如果函数的返回值是类对象,函数调用完成返回时; 4-7 拷贝构造函数与赋值运算符(=)有何不同? 解: 赋值运算符(=)作用于一个已存在的对象;而拷贝构造函数会创建一个新的对象。 4-8 定义一个Dog 类,包含的age、weight等属性,以及对这些属性操作的方法。实现并测试这个类。 解: 源程序: #include class Dog { public: Dog (int initialAge = 0, int initialWeight = 5); ~Dog(); int GetAge() { return itsAge;} // inline! void SetAge (int age) { itsAge = age;} // inline! int GetWeight() { return itsWeight;} // inline! void SetWeight (int weight) { itsAge = weight;} // inline! private: int itsAge, itsWeight; }; Dog::Dog(int initialAge, int initialWeight) { itsAge = initialAge; itsWeight = initialWeight; } Dog::~Dog() //destructor, takes no action { } int main() { Dog Jack(2,10); cout << "Jack is a Dog who is " ; cout << Jack.GetAge() << " years old and"; cout << Jack.GetWeight() << " pounds weight.\n"; Jack.SetAge(7); Jack.SetWeight(20); cout << "Now Jack is " ; cout << Jack.GetAge() << " years old and"; cout << Jack.GetWeight() << " pounds weight."; return 0; } 程序运行输出: Jack is a Dog who is 2 years old and 10 pounds weight. Now Jack is 7 years old 20 pounds weight. 4-9 设计并测试一个名为Rectangle的矩形类,其属性为矩形的左下角与右上角两个点的坐标,能计算矩形的面积。 解: 源程序: #include class Rectangle { public: Rectangle (int top, int left, int bottom, int right); ~Rectangle () {} int GetTop() const { return itsTop; } int GetLeft() const { return itsLeft; } int GetBottom() const { return itsBottom; } int GetRight() const { return itsRight; } void SetTop(int top) { itsTop = top; } void SetLeft (int left) { itsLeft = left; } void SetBottom (int bottom) { itsBottom = bottom; } void SetRight (int right) { itsRight = right; } int GetArea() const; private: int itsTop; int itsLeft; int itsBottom; int itsRight; }; Rectangle::Rectangle(int top, int left, int bottom, int right) { itsTop = top; itsLeft = left; itsBottom = bottom; itsRight = right; } int Rectangle::GetArea() const { int Width = itsRight-itsLeft; int Height = itsTop - itsBottom; return (Width * Height); } int main() { Rectangle MyRectangle (100, 20, 50, 80 ); int Area = MyRectangle.GetArea(); cout << "Area: " << Area << "\n"; return 0; } 程序运行输出: Area: 3000 Upper Left X Coordinate: 20 4-10 设计一个用于人事管理的People(人员)类。考虑到通用性,这里只抽象出所有类型人员都具有的属性:number(编号)、sex(性别)、birthday(出生日期)、id(身份证号)等等。其中"出生日期"定义为一个"日期"类内嵌子对象。用成员函数实现对人员信息的录入和显示。要求包括:构造函数和析构函数、拷贝构造函数、内联成员函数、带缺省形参值的成员函数、聚集。 解: 本题用作实验四的选做题,因此不给出答案。 4-11 定义一个矩形类,有长、宽两个属性,有成员函数计算矩形的面积 解: #include class Rectangle { public: Rectangle(float len, float width) { Length = len; Width = width; } ~Rectangle(){}; float GetArea() { return Length * Width; } float GetLength() { return Length; } float GetWidth() { return Width; } private: float Length; float Width; }; void main() { float length, width; cout <> length; cout <> width; Rectangle r(length, width); cout << "长为" << length << "宽为" << width << "的矩形的面积为:" << r.GetArea () << endl; } 程序运行输出: 请输入矩形的长度:5 请输入矩形的宽度:4 长为5宽为4的矩形的面积为:20 4-12 定义一个"数据类型" datatype类,能处理包含字符型、整型、浮点型三种类型的数据,给出其构造函数。 解: #include class datatype{ enum{ character, integer, floating_point } vartype; union { char c; int i; float f; }; public: datatype(char ch) { vartype = character; c = ch; } datatype(int ii) { vartype = integer; i = ii; } datatype(float ff) { vartype = floating_point; f = ff; } void print(); }; void datatype::print() { switch (vartype) { case character: cout << "字符型: " << c << endl; break; case integer: cout << "整型: " << i << endl; break; case floating_point: cout << "浮点型: " << f << endl; break; } } void main() { datatype A('c'), B(12), C(1.44F); A.print(); B.print(); C.print(); } 程序运行输出: 字符型: c 整型: 12 浮点型: 1.44 4-13 定义一个Circle类,有数据成员半径Radius,成员函数GetArea(),计算圆的面积,构造一个Circle的对象进行测试。 解: #include class Circle { public: Circle(float radius){ Radius = radius;} ~Circle(){} float GetArea() { return 3.14 * Radius * Radius; } private: float Radius; }; void main() { float radius; cout <> radius; Circle p(radius); cout << "半径为" << radius << "的圆的面积为:" << p.GetArea () << endl; } 程序运行输出: 请输入圆的半径:5 半径为5的圆的面积为:78.5 4-14 定义一个tree类,有成员ages,成员函数grow(int years)对ages加上years,age()显示tree对象的ages的值。 解: #include class Tree { int ages; public: Tree(int n=0); ~Tree(); void grow(int years); void age(); }; Tree::Tree(int n) { ages = n; } Tree::~Tree() { age(); } void Tree::grow(int years) { ages += years; } void Tree::age() { cout << "这棵树的年龄为" << ages << endl; } void main() { Tree t(12); t.age(); t.grow(4); } 程序运行输出: 这棵树的年龄为12 这棵树的年龄为16 第 五 章 C++程序的基本结构 5-1 什么叫做作用域?有哪几种类型的作用域? 解: 作用域讨论的是标识符的有效范围,作用域是一个标识符在程序正文中有效的区域。C++的作用域分为函数原形作用域、块作用域(局部作用域)、类作用域和文件作用域. 5-2 什么叫做可见性?可见性的一般规则是什么? 解: 可见性是标识符是否可以引用的问题; 可见性的一般规则是:标识符要声明在前,引用在后,在同一作用域中,不能声明同名的标识符。对于在不同的作用域声明的标识符,遵循的原则是:若有两个或多个具有包含关系的作用域,外层声明的标识符如果在内层没有声明同名标识符时仍可见,如果内层声明了同名标识符则外层标识符不可见。 5-3 下面的程序的运行结果是什么,实际运行一下,看看与你的设想有何不同。 #include void myFunction(); int x = 5, y = 7; int main() { cout << "x from main: " << x << "\n"; cout << "y from main: " << y << "\n\n"; myFunction(); cout << "Back from myFunction!\n\n"; cout << "x from main: " << x << "\n"; cout << "y from main: " << y << "\n"; return 0; } void myFunction() { int y = 10; cout << "x from myFunction: " << x << "\n"; cout << "y from myFunction: " << y << "\n\n"; } 解: 程序运行输出: x from main: 5 y from main: 7 x from myFunction: 5 y from myFunction: 10 Back from myFunction! x from main: 5 y from main: 7 5-4 假设有两个无关系的类Engine和Fuel,使用时,怎样允许Fuel成员访问Engine中的私有和保护的成员? 解: 源程序: class fuel; class engine { friend class fuel; private; int powerlevel; public; engine(){ powerLevel = 0;} void engine_fn(fuel &f); }; class fuel { friend class engine; private; int fuelLevel; public: fuel(){ fuelLevel = 0;} void fuel_fn( engine &e); }; 5-5 什么叫做静态数据成员?它有何特点? 解: 类的静态数据成员是类的数据成员的一种特例,采用static关键字来声明。对于类的普通数据成员,每一个类的对象都拥有一个拷贝,就是说每个对象的同名数据成员可以分别存储不同的数值,这也是保证对象拥有自身区别于其它对象的特征的需要,但是静态数据成员,每个类只要一个拷贝,由所有该类的对象共同维护和使用,这个共同维护、使用也就实现了同一类的不同对象之间的数据共享。 5-6 什么叫做静态函数成员?它有何特点? 解: 使用static关键字声明的函数成员是静态的,静态函数成员属于整个类,同一个类的所有对象共同维护,为这些对象所共享。静态函数成员具有以下两个方面的好处,一是由于静态成员函数只能直接访问同一个类的静态数据成员,可以保证不会对该类的其余数据成员造成负面影响;二是同一个类只维护一个静态函数成员的拷贝,节约了系统的开销,提高程序的运行效率。 5-7 定义一个Cat类,拥有静态数据成员HowManyCats,记录Cat的个体数目;静态成员函数GetHowMany(),存取HowManyCats。设计程序测试这个类,体会静态数据成员和静态成员函数的用法。 解: 源程序: #include class Cat { public: Cat(int age):itsAge(age){HowManyCats++; } virtual ~Cat() { HowManyCats--; } virtual int GetAge() { return itsAge; } virtual void SetAge(int age) { itsAge = age; } static int GetHowMany() { return HowManyCats; } private: int itsAge; static int HowManyCats; }; int Cat::HowManyCats = 0; void TelepathicFunction(); int main() { const int MaxCats = 5; Cat *CatHouse[MaxCats]; int i; for (i = 0; i<MaxCats; i++) { CatHouse[i] = new Cat(i); TelepathicFunction(); } for ( i = 0; i<MaxCats; i++) { delete CatHouse[i]; TelepathicFunction(); } return 0; } void TelepathicFunction() { cout << "There are " << Cat::GetHowMany() << " cats alive!\n"; } 程序运行输出: There are 1 cats alive! There are 2 cats alive! There are 3 cats alive! There are 4 cats alive! There are 5 cats alive! There are 4 cats alive! There are 3 cats alive! There are 2 cats alive! There are 1 cats alive! There are 0 cats alive! 5-8 什么叫做友元函数?什么叫做友元类? 解: 友元函数是使用friend关键字声明的函数,它可以访问相应类的保护成员和私有成员。友元类是使用friend关键字声明的类,它的所有成员函数都是相应类的友元函数。 5-9 如果类A是类B的友元,类B是类C的友元,类D是类A的派生类,那么类B是类A的友元吗?类C是类A的友元吗?类D是类B的友元吗? 解: 类B不是类A的友元,友元关系不具有交换性; 类C不是类A的友元,友元关系不具有传递性; 类D不是类B的友元,友元关系不能被继承。 5-10 静态成员变量可以为私有的吗?声明一个私有的静态整型成员变量。 解: 可以,例如: private: static int a; 5-11 在一个文件中定义一个全局变量n,主函数main(),在另一个文件中定义函数fn1(),在main()中对n赋值,再调用fn1(),在fn1()中也对n赋值,显示n最后的值。 解: #include #include "fn1.h" int n; void main() { n = 20; fn1(); cout << "n的值为" <<n; } // fn1.h文件 extern int n; void fn1() { n=30; } 程序运行输出: n的值为30 5-12 在函数fn1()中定义一个静态变量n,fn1()中对n的值加1,在主函数中,调用fn1()十次,显示n的值。 解: #include void fn1() { static int n = 0; n++; cout << "n的值为" << n <<endl; } void main() { for(int i = 0; i i =+10; } void Y::g(X* x) { x->i ++; } class Z { public: void f(X* x) { x->i += 5; } }; #endif // MY_X_Y_Z_H 程序运行输出:无 5-14 定义Boat与Car两个类,二者都有weight属性,定义二者的一个友元函数totalWeight(),计算二者的重量和。 解: 源程序: #include class Boat; class Car { private: int weight; public: Car(int j){weight = j;} friend int totalWeight(Car &aCar;, Boat &aBoat;); }; class Boat { private: int weight; public: Boat(int j){weight = j;} friend int totalWeight(Car &aCar;, Boat &aBoat;); }; int totalWeight(Car &aCar;, Boat &aBoat;) { return aCar.weight + aBoat.weight; } void main() { Car c1(4); Boat b1(5); cout << totalWeight(c1, b1) << endl; } 程序运行输出: 9 第 六 章 数组、指针与字符串 6-1 数组A[10][5][15]一共有多少个元素? 解: 10×5×15 = 750 个元素 6-2 在数组A[20]中第一个元素和最后一个元素是哪一个? 解: 第一个元素是A[0],最后一个元素是A[19]。 6-3 用一条语句定义一个有五个元素的整型数组,并依次赋予1~5的初值。 解: 源程序: int IntegerArray[5] = { 1, 2, 3, 4, 5 }; 或:int IntegerArray[] = { 1, 2, 3, 4, 5 }; 6-4 已知有一个数组名叫oneArray,用一条语句求出其元素的个数。 解: 源程序: nArrayLength = sizeof(oneArray) / sizeof(oneArray[0]); 6-5 用一条语句定义一个有5×3个元素的二维整型数组,并依次赋予1~15的初值。 解: 源程序: int theArray[5][3] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 }; 或:int theArray[5][3] = { {1,2,3}, {4,5,6}, {7,8,9}, {10,11,12},{13,14,15} }; 6-6 运算符*和&的作用是什么? 解: *称为指针运算符,是一个一元操作符,表示指针所指向的对象的值;&称为取地址运算符,也是一个一元操作符,是用来得到一个对象的地址。 6-7 什么叫做指针?指针中储存的地址和这个地址中的值有何区别? 解: 指针是一种数据类型,具有指针类型的变量称为指针变量。指针变量存放的是另外一个对象的地址,这个地址中的值就是另一个对象的内容。 6-8 定义一个整型指针,用new语句为其分配包含10个整型元素的地址空间。 解: 源程序: int *pInteger = new int[10]; 6-9 在字符串”Hello,world!”中结束符是什么? 解: 是NULL字符。 6-10 定义一个有五个元素的整型数组,在程序中提示用户输入元素值,最后再在屏幕上显示出来。 解: 源程序: #include int main() { int myArray[5]; int i; for ( i=0; i<5; i++) { cout << "Value for myArray[" << i <> myArray[i]; } for (i = 0; i<5; i++) cout << i << ": " << myArray[i] << "\n"; return 0; } 程序运行输出: Value for myArray[0]: 2 Value for myArray[1]: 5 Value for myArray[2]: 7 Value for myArray[3]: 8 Value for myArray[4]: 3 0: 2 1: 5 2: 7 3: 8 4: 3 6-11 引用和指针有何区别?何时只能使用指针而不能使用引用? 解: 引用是一个别名,不能为NULL值,不能被重新分配;指针是一个存放地址的变量。当需要对变量重新赋以另外的地址或赋值为NULL时只能使用指针。 6-12 声明下列指针:float类型变量的指针pFloat,char类型的指针pString和struct customer型的指针prec。 解: float *pfloat; char *pString; struct customer *prec; 6-13 给定float类型的指针fp,写出显示fp所指向的值的输出流语句。 解: cout << "Value == " << *fp; 6-14 程序中定义一个double类型变量的指针。分别显示指针占了多少字节和指针所指的变量占了多少字节。 解: double *counter; cout << "\nSize of pointer == "sizeof(counter); cout << '\nSize of addressed value == "<<sizeof(*counter); 6-15 const int * p1 和 int * const p2的区别是什么? 解: const int * p1 声明了一个指向整型常量的指针p1,因此不能通过指针p1来改变它所指向的整型值;int * const p2声明了一个指针型常量,用于存放整型变量的地址,这个指针一旦初始化后,就不能被重新赋值了。 6-16 定义一个整型变量a,一个整型指针p,一个引用r,通过p把a的值改为10,通过r把a的值改为5 解: void main() { int a; int *p = &a; int &r = a; *p = 10; r = 5; } 6-17 下列程序有何问题,请仔细体会使用指针时应避免出现这个的问题。 #include int main() { int *p; *pInt = 9; cout << "The value at p: " << *p; return 0; } 解: 指针p没有初始化,也就是没有指向某个确定的内存单元,它指向内存中的一个随机地址,给这个随机地址赋值是非常危险的。 6-18 下列程序有何问题,请改正;仔细体会使用指针时应避免出现的这个问题。 #include int Fn1(); int main() { int a = Fn1(); cout << "the value of a is: " << a; return 0; } int Fn1() { int * p = new int (5); return *p; } 解: 此程序中给*p分配的内存没有被释放掉。 改正: #include int* Fn1(); int main() { int *a = Fn1(); cout << "the value of a is: " << *a; delete a; return 0; } int* Fn1() { int * p = new int (5); return p; } 6-19 声明一个参数为整型,返回值为长整型的函数指针;声明类A的一个成员函数指针,其参数为整型,返回值长整型。 解: long (* p_fn1)(int); long ( A::*p_fn2)(int); 6-20 实现一个名为SimpleCircle的简单圆类,其数据成员int *itsRadius为一个指向其半径值的指针,设计对数据成员的各种操作,给出这个类的完整实现并测试这个类。 解: 源程序: #include class SimpleCircle { public: SimpleCircle(); SimpleCircle(int); SimpleCircle(const SimpleCircle &); ~SimpleCircle() {} void SetRadius(int); int GetRadius()const; private: int *itsRadius; }; SimpleCircle::SimpleCircle() { itsRadius = new int(5); } SimpleCircle::SimpleCircle(int radius) { itsRadius = new int(radius); } SimpleCircle::SimpleCircle(const SimpleCircle & rhs) { int val = rhs.GetRadius(); itsRadius = new int(val); } int SimpleCircle::GetRadius() const { return *itsRadius; } int main() { SimpleCircle CircleOne, CircleTwo(9); cout << "CircleOne: " << CircleOne.GetRadius() << endl; cout << "CircleTwo: " << CircleTwo.GetRadius() << endl; return 0; }程序运行输出: CircleOne: 5 CircleTwo: 9 6-21 编写一个函数,统计一个英文句子中字母的个数,在主程序中实现输入、输出。 解: 源程序: #include #include int count(char *str) { int i,num=0; for (i=0; str[i]; i++) { if ( (str[i]>='a' && str[i]='A' && str[i]<='Z') ) num++; } return num; } void main() { char text[100]; cout << "输入一个英语句子:" << endl; gets(text); cout << "这个句子里有" << count(text) << "个字母。" << endl; } 程序运行输出: 输入一个英语句子: It is very interesting! 这个句子里有19个字母。 6-22 编写函数int index(char *s, char *t),返回字符串t 在字符串s中出现的最左边的位置,如果在s中没有与t匹配的子串,就返回-1。 解: 源程序: #include int index( char *s, char *t) { int i,j,k; for(i = 0; s[i] != '\0'; i++) { for(j = i, k = 0; t[k] != '\0' && s[j] == t[k]; j++, k++) ; if (t[k] =='\0') return i; } return -1; } void main() { int n; char str1[20],str2[20]; cout <> str1; cout <> str2; n = index(str1,str2); if (n > 0) cout << str2 << "在" << str1 << "中左起第" << n+1 << "个位置。"<<endl; else cout << str2 << "不在" << str1 << "中。" << endl; } 程序运行输出: 输入一个英语单词:abcdefgh 输入另一个英语单词:de de在abcdefghijk中左起第4个位置。 6-23 编写函数reverse(char *s)的倒序递归程序,使字符串s倒序。 解: 源程序: #include #include void reverse(char *s, char *t) { char c; if (s < t) { c = *s; *s = *t; *t = c; reverse(++s, --t); } } void reverse( char *s) { reverse(s, s + strlen(s) - 1); } void main() { char str1[20]; cout <> str1; cout << "原字符串为:" << str1 << endl; reverse(str1); cout << "倒序反转后为:" << str1 << endl; } 程序运行输出: 输入一个字符串:abcdefghijk 原字符串为:abcdefghijk 倒序反转后为:kjihgfedcba 6-24 设学生人数N=8,提示用户输入N个人的考试成绩,然后计算出平均成绩,显示出来。 解: 源程序: #include #include #define N 8 float grades[N]; //存放成绩的数组 void main() { int i; float total,average; //提示输入成绩 for(i = 0; i < N; i++ ) { cout << "Enter grade #" <<(i +1) <> grades[i]; } total = 0; for (i = 0; i < N; i++) total += grades[i]; average = total / N; cout << "\nAverage grade: " << average << endl; } 程序运行输出: Enter grade #1: 86 Enter grade #2: 98 Enter grade #3: 67 Enter grade #4: 80 Enter grade #5: 78 Enter grade #6: 95 Enter grade #7: 78 Enter grade #8: 56 Average grade: 79.75 6-25 设计一个字符串类MyString,具有构造函数、析构函数、拷贝构造函数,重载运算符+、=、+=、[],尽可能地完善它,使之能满足各种需要。(运算符重载功能为选做,参见第8章) 解: #include #include class MyString { public: MyString(); MyString(const char *const); MyString(const MyString &); ~MyString(); char & operator[](unsigned short offset); char operator[](unsigned short offset) const; MyString operator+(const MyString&); void operator+=(const MyString&); MyString & operator= (const MyString &); unsigned short GetLen()const { return itsLen; } const char * GetMyString() const { return itsMyString; } private: MyString (unsigned short); // private constructor char * itsMyString; unsigned short itsLen; }; MyString::MyString() { itsMyString = new char[1]; itsMyString[0] = '\0'; itsLen=0; } MyString::MyString(unsigned short len) { itsMyString = new char[len+1]; for (unsigned short i = 0; i<=len; i++) itsMyString[i] = '\0'; itsLen=len; } MyString::MyString(const char * const cMyString) { itsLen = strlen(cMyString); itsMyString = new char[itsLen+1]; for (unsigned short i = 0; i<itsLen; i++) itsMyString[i] = cMyString[i]; itsMyString[itsLen]='\0'; } MyString::MyString (const MyString & rhs) { itsLen=rhs.GetLen(); itsMyString = new char[itsLen+1]; for (unsigned short i = 0; i<itsLen;i++) itsMyString[i] = rhs[i]; itsMyString[itsLen] = '\0'; } MyString::~MyString () { delete [] itsMyString; itsLen = 0; } MyString& MyString::operator=(const MyString & rhs) { if (this == &rhs;) return *this; delete [] itsMyString; itsLen=rhs.GetLen(); itsMyString = new char[itsLen+1]; for (unsigned short i = 0; i itsLen) return itsMyString[itsLen-1]; else return itsMyString[offset]; } char MyString::operator[](unsigned short offset) const { if (offset > itsLen) return itsMyString[itsLen-1]; else return itsMyString[offset]; } MyString MyString::operator+(const MyString& rhs) { unsigned short totalLen = itsLen + rhs.GetLen(); MyString temp(totalLen); for (unsigned short i = 0; i<itsLen; i++) temp[i] = itsMyString[i]; for (unsigned short j = 0; j<rhs.GetLen(); j++, i++) temp[i] = rhs[j]; temp[totalLen]='\0'; return temp; } void MyString::operator+=(const MyString& rhs) { unsigned short rhsLen = rhs.GetLen(); unsigned short totalLen = itsLen + rhsLen; MyString temp(totalLen); for (unsigned short i = 0; i<itsLen; i++) temp[i] = itsMyString[i]; for (unsigned short j = 0; j<rhs.GetLen(); j++, i++) temp[i] = rhs[i-itsLen]; temp[totalLen]='\0'; *this = temp; } int main() { MyString s1("initial test"); cout << "S1:\t" << s1.GetMyString() << endl; char * temp = "Hello World"; s1 = temp; cout << "S1:\t" << s1.GetMyString() << endl; char tempTwo[20]; strcpy(tempTwo,"; nice to be here!"); s1 += tempTwo; cout << "tempTwo:\t" << tempTwo << endl; cout << "S1:\t" << s1.GetMyString() << endl; cout << "S1[4]:\t" << s1[4] << endl; s1[4]='x'; cout << "S1:\t" << s1.GetMyString() << endl; cout << "S1[999]:\t" << s1[999] << endl; MyString s2(" Another myString"); MyString s3; s3 = s1+s2; cout << "S3:\t" << s3.GetMyString() << endl; MyString s4; s4 = "Why does this work?"; cout << "S4:\t" << s4.GetMyString() << endl; return 0; } 程序运行输出: S1: initial test S1: Hello World tempTwo: ; nice to be here! S1: Hello World; nice to be here! S1[4]: o S1: Hellx World; nice to be here! S1[999]: ! S3: Hellx World; nice to be here! Another myString S4: Why does this work? 6-26 编写一个3×3矩阵转置的函数,在main()函数中输入数据。 解: #include void move (int matrix[3][3]) { int i, j, k; for(i=0; i<3; i++) for (j=0; j<i; j++) { k = matrix[i][j]; matrix[i][j] = matrix[j][i]; matrix[j][i] = k; } } void main() { int i, j; int data[3][3]; cout << "输入矩阵的元素" << endl; for(i=0; i<3; i++) for (j=0; j<3; j++) { cout << "第" << i+1 << "行第" << j+1 <> data[i][j]; } cout << "输入的矩阵的为:" << endl; for(i=0; i<3; i++) { for (j=0; j<3; j++) cout << data[i][j] << " "; cout << endl; } move(data); cout << "转置后的矩阵的为:" << endl; for(i=0; i<3; i++) { for (j=0; j<3; j++) cout << data[i][j] << " "; cout << endl; } } 程序运行输出: 输入矩阵的元素 第1行第1个元素为:1 第1行第2个元素为:2 第1行第3个元素为:3 第2行第1个元素为:4 第2行第2个元素为:5 第2行第3个元素为:6 第3行第1个元素为:7 第3行第2个元素为:8 第3行第3个元素为:9 输入的矩阵的为: 1 2 3 4 5 6 7 8 9 转置后的矩阵的为: 1 4 7 2 5 8 3 6 9 6-27 编写一个矩阵转置的函数,矩阵的维数在程序中由用户输入。 解: #include void move (int *matrix ,int n) { int i, j, k; for(i=0; i<n; i++) for (j=0; j<i; j++) { k = *(matrix + i*n + j); *(matrix + i*n + j) = *(matrix + j*n + i); *(matrix + j*n + i) = k; } } void main() { int n, i, j; int *p; cout <> n; p = new int[n*n]; cout << "输入矩阵的元素" << endl; for(i=0; i<n; i++) for (j=0; j<n; j++) { cout << "第" << i+1 << "行第" << j+1 <> p[i*n + j]; } cout << "输入的矩阵的为:" << endl; for(i=0; i<n; i++) { for (j=0; j<n; j++) cout << p[i*n + j] << " "; cout << endl; } move(p, n); cout << "转置后的矩阵的为:" << endl; for(i=0; i<n; i++) { for (j=0; j<n; j++) cout << p[i*n + j] << " "; cout << endl; } } 程序运行输出: 请输入矩阵的维数:3 输入矩阵的元素 第1行第1个元素为:1 第1行第2个元素为:2 第1行第3个元素为:3 第2行第1个元素为:4 第2行第2个元素为:5 第2行第3个元素为:6 第3行第1个元素为:7 第3行第2个元素为:8 第3行第3个元素为:9 输入的矩阵的为: 1 2 3 4 5 6 7 8 9 转置后的矩阵的为: 1 4 7 2 5 8 3 6 9 6-28 定义一个Employee类,其中包括表示姓名、街道地址、城市和邮编等属性,包括chage_name()和display()等函数;display()使用cout语句显示姓名、街道地址、城市和邮编等属性,函数change_name()改变对象的姓名属性,实现并测试这个类。 解: 源程序: #include #include class Employee { private: char name[30]; char street[30]; char city[18]; char zip[6]; public: Employee(char *n, char *str, char *ct, char *z); void change_name(char *n); void display(); }; Employee::Employee (char *n,char *str,char *ct, char *z) { strcpy(name, n); strcpy(street, str); strcpy(city, ct); strcpy(zip, z); } void Employee::change_name (char *n) { strcpy(name, n); } void Employee::display () { cout << name << " " << street << " "; cout << city << " "<< zip; } void main(void) { Employee e1("张三","平安大街3号", "北京", "100000"); e1.display(); cout << endl; e1.change_name("李四"); e1.display(); cout << endl; } 程序运行输出: 张三 平安大街3号 北京 100000 李四 平安大街3号 北京 100000 第 七 章 继承与派生 7-1 比较类的三种继承方式public公有继承、protected保护继承、private私有继承之间的差别。 解: 不同的继承方式,导致不同访问属性的基类成员在派生类中的访问属性也有所不同: 公有继承,使得基类public(公有)和protected(保护)成员的访问属性在派生类中不变,而基类private(私有)成员不可访问。 私有继承,使得基类public(公有)和protected(保护)成员都以private(私有)成员身份出现在派生类中,而基类private(私有)成员不可访问。 保护继承中,基类public(公有)和protected(保护)成员都以protected(保护)成员身份出现在派生类中,而基类private(私有)成员不可访问。 7-2 派生类构造函数执行的次序是怎样的? 解: 派生类构造函数执行的一般次序为:调用基类构造函数;调用成员对象的构造函数;派生类的构造函数体中的内容。 7-3 如果在派生类B已经重载了基类A的一个成员函数fn1(),没有重载成员函数fn2(),如何调用基类的成员函数fn1()、fn2()? 解: 调用方法为: A::fn1(); fn2(); 7-4 什么叫做虚基类?有何作用? 解: 当某类的部分或全部直接基类是从另一个基类派生而来,这些直接基类中,从上一级基类继承来的成员就拥有相同的名称,派生类的对象的这些同名成员在内存中同时拥有多个拷贝,我们可以使用作用域分辨符来唯一标识并分别访问它们。我们也可以将直接基类的共同基类设置为虚基类,这时从不同的路径继承过来的该类成员在内存中只拥有一个拷贝,这样就解决了同名成员的唯一标识问题。 虚基类的声明是在派生类的定义过程,其语法格式为: class 派生类名:virtual 继承方式 基类名 上述语句声明基类为派生类的虚基类,在多继承情况下,虚基类关键字的作用范围和继承方式关键字相同,只对紧跟其后的基类起作用。声明了虚基类之后,虚基类的成员在进一步派生过程中,和派生类一起维护一个内存数据拷贝。 7-5 定义一个Shape基类,在此基础上派生出Rectangle和Circle,二者都有GetArea()函数计算对象的面积。使用Rectangle类创建一个派生类Square。 解: 源程序: #include class Shape { public: Shape(){} ~Shape(){} virtual float GetArea() { return -1; } }; class Circle : public Shape { public: Circle(float radius):itsRadius(radius){} ~Circle(){} float GetArea() { return 3.14 * itsRadius * itsRadius; } private: float itsRadius; }; class Rectangle : public Shape { public: Rectangle(float len, float width): itsLength(len), itsWidth(width){}; ~Rectangle(){}; virtual float GetArea() { return itsLength * itsWidth; } virtual float GetLength() { return itsLength; } virtual float GetWidth() { return itsWidth; } private: float itsWidth; float itsLength; }; class Square : public Rectangle { public: Square(float len); ~Square(){} }; Square::Square(float len): Rectangle(len,len) { } void main() { Shape * sp; sp = new Circle(5); cout << "The area of the Circle is " <GetArea () << endl; delete sp; sp = new Rectangle(4,6); cout << "The area of the Recta

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

明子~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值