在数组中查找一个数并输出所处位置

《程序设计基础实训指导教程-c语言》
ISBN 978-7-03-032846-5
p73
4.1.2 上级实训内容

【实训内容2】输入10个数,保存在一个数组中,再任意输入一个数,在数组中查找这个数,给出是否找到的信息,如果找到了,要求输出该数在数组中所处的位置;如果找不到,输出“没有找到”。

#include <stdio.h>
#define MAX 10
int main(void)
{
	int num[MAX],temp,i;
	int cnt=0;
	printf("输入%d个数:\n",MAX);
	for(i=0;i<MAX;i++)
	{
		scanf("%d",&num[i]);
	}
	printf("输入要查找的数:\n");
	scanf("%d",&temp);
	for(i=0;i<MAX;i++)
	{
		if(num[i]==temp)
		{
			printf("找到了,该数在数组中为第%d个数",i+1);
			cnt=1;
			break;
		}
		else
		{
			cnt=0;	//匹配不到,不输出,以便最后输出“没有找到”
		}
	}
	if(cnt==0)
	{
		printf("没有找到");
	}
}

在这里插入图片描述
在这里插入图片描述

  • 9
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
目录<br><br>前言<br>1. 一般信息<br>1.1. 关于本手册<br>1.2. 本手册采用的惯例<br>1.3. MySQL AB概述<br>1.4. MySQL据库管理系统概述<br>1.4.1. MySQL的历史<br>1.4.2. MySQL的的主要特性<br>1.4.3. MySQL稳定性<br>1.4.4. MySQL表最大能达到多少<br>1.4.5. 2000年兼容性<br>1.5. MaxDB据库管理系统概述<br>1.5.1. 什么是MaxDB?<br>1.5.2. MaxDB的历史<br>1.5.3. MaxDB的特性<br>1.5.4. 许可和支持<br>1.5.5. MaxDB和MySQL之间的特性差异<br>1.5.6. MaxDB和MySQL之间的协同性<br>1.5.7. 与MaxDB有关的链接<br>1.6. MySQL发展大事记<br>1.6.1. MySQL 5.1的新特性<br>1.7. MySQL信息源<br>1.7.1. MySQL邮件列表<br>1.7.2. IRC(在线聊天系统)上的MySQL社区支持<br>1.7.3. MySQL论坛上的MySQL社区支持<br>1.8. MySQL标准的兼容性<br>1.8.1. MySQL遵从的标准是什么<br>1.8.2. 选择SQL模式<br>1.8.3. 在ANSI模式下运行MySQL<br>1.8.4. MySQL对标准SQL的扩展<br>1.8.5. MySQL与标准SQL的差别<br>1.8.6. MySQL处理约束的方式<br>2. 安装MySQL<br>2.1. 一般安装问题<br>2.1.1. MySQL支持的操作系统<br>2.1.2. 选择要安装的MySQL分发版<br>2.1.3. 怎样获得MySQL<br>2.1.4. 通过MD5校验和或GnuPG验证软件包的完整性<br>2.1.5. 安装布局<br>2.2. 使用二进制分发版的标准MySQL安装<br>2.3. 在Windows上安装MySQL<br>2.3.1. Windows系统要求<br>2.3.2. 选择安装软件包<br>2.3.3. 用自动安装器安装MySQL<br>2.3.4. 使用MySQL安装向导<br>2.3.5. 使用配置向导<br>2.3.6. 通过非安装Zip文件安装MySQL<br>2.3.7. 提取安装档案文件<br>2.3.8. 创建选项文件<br>2.3.9. 选择MySQL服务器类型<br>2.3.10. 首次启动服务器<br>2.3.11. 从Windows命令行启动MySQL<br>2.3.12. 以Windows服务方式启动MySQL<br>2.3.13. 测试MySQL安装<br>2.3.14. 在Windows环境下对MySQL安装的故障诊断与排除<br>2.3.15. 在Windows下升级MySQL<br>2.3.16. Windows版MySQL同Unix版MySQL对比<br>2.4. 在Linux下安装MySQL<br>2.5.在Mac OS X中安装MySQL<br>2.6. 在NetWare中安装MySQL<br>2.7. 在其它类Unix系统中安装MySQL<br>2.8. 使用源码分发版安装MySQL<br>2.8.1. 源码安装概述<br>2.8.2. 典型配置选项<br>2.8.3. 从开发源码树安装<br>2.8.4. 处理MySQL编译问题<br>2.8.5. MIT-pthreads注意事项<br>2.8.6. 在Windows下从源码安装MySQL<br>2.8.7. 在Windows下编译MySQL客户端<br>2.9. 安装后的设置和测试<br>2.9.1. Windows下安装后的过程<br>2.9.2. Unix下安装后的过程<br>2.9.3. 使初始MySQL账户安全<br>2.10. 升级MySQL<br>2.10.1. 从5.0版升级<br>2.10.2. 升级授权表<br>2.10.3. 将MySQL据库拷贝到另一台机器<br>2.11. 降级MySQL<br>2.12. 具体操作系统相关的注意事项<br>2.12.1. Linux注意事项<br>2.12.2. Mac OS X注意事项<br>2.12.3. Solaris注意事项<br>2.12.4. BSD注意事项<br>2.12.5. 其它Unix注意事项<br>2.12.6. OS/2注意事项<br>2.13. Perl安装注意事项<br>2.13.1. 在Unix中安装Perl<br>2.13.2. 在Windows下安装ActiveState Perl<br>2.13.3. 使用Perl DBI/DBD接口的问题<br>3. 教程<br>3.1. 连接与断开服务器<br>3.2. 输入查询<br>3.3. 创建并使用据库<br>3.3.1. 创建并选择据库<br>3.3.2. 创建表<br>3.3.3. 将据装入表中<br>3.3.4. 从表检索信息<br>3.4. 获得据库和表的信息<br>3.5. 在批处理模式下使用mysql<br>3.6. 常用查询的例子<br>3.6.1. 列的最大值<br>3.6.2. 拥有某个列的最大值的行<br>3.6.3. 列的最大值:按组<br>3.6.4. 拥有某个字段的组间最大值的行<br>3.6.5. 使用用户变量<br>3.6.6. 使用外键<br>3.6.7. 根据两个键搜索<br>3.6.8. 根据天计算访问量<br>3.6.9. 使用AUTO_INCREMENT<br>3.7. 孪生项目的查询<br>3.7.1. 查找所有未分发的孪生项<br>3.7.2. 显示孪生对状态的表<br>3.8. 与Apache一起使用MySQL<br>4. MySQL程序概述<br>4.1. MySQL程序概述<br>4.2. 调用MySQL程序<br>4.3. 指定程序选项<br>4.3.1. 在命令行上使用选项<br>4.3.2. 使用选项文件<br>4.3.3. 用环境变量指定选项<br>4.3.4. 使用选项设置程序变量<br>5. 据库管理<br>5.1. MySQL服务器和服务器启动脚本<br>5.1.1. 服务器端脚本和实用工具概述<br>5.1.2. mysqld-max扩展MySQL服务器<br>5.1.3. mysqld_safe:MySQL服务器启动脚本<br>5.1.4. mysql.server:MySQL服务器启动脚本<br>5.1.5. mysqld_multi:管理多个MySQL服务器的程序<br>5.2. mysqlmanager:MySQL实例管理器<br>5.2.1. 用MySQL实例管理器启动MySQL服务器<br>5.2.2. 连接到MySQL实例管理器并创建用户账户<br>5.2.3. MySQL实例管理器命令行选项<br>5.2.4. MySQL实例管理器配置文件<br>5.2.5. MySQL实例管理器识别的命令<br>5.3. mysqld:MySQL服务器<br>5.3.1. mysqld命令行选项<br>5.3.2. SQL服务器模式<br>5.3.3. 服务器系统变量<br>5.3.4. 服务器状态变量<br>5.4. mysql_fix_privilege_tables:升级MySQL系统表<br>5.5. MySQL服务器关机进程<br>5.6. 一般安全问题<br>5.6.1. 通用安全指南<br>5.6.2. 使MySQL在攻击者面前保持安全<br>5.6.3. Mysqld安全相关启动选项<br>5.6.4. LOAD DATA LOCAL安全问题<br>5.7. MySQL访问权限系统<br>5.7.1. 权限系统的作用<br>5.7.2. 权限系统工作原理<br>5.7.3. MySQL提供的权限<br>5.7.4. 与MySQL服务器连接<br>5.7.5. 访问控制, 阶段1:连接核实<br>5.7.6. 访问控制, 阶段2:请求核实<br>5.7.7. 权限更改何时生效<br>5.7.8. 拒绝访问错误的原因<br>5.7.9. MySQL 4.1中的密码哈希处理<br>5.8. MySQL用户账户管理<br>5.8.1. MySQL用户名和密码<br>5.8.2. 向MySQL增加新用户账户<br>5.8.3. 从MySQL删除用户账户<br>5.8.4. 限制账户资源<br>5.8.5. 设置账户密码<br>5.8.6. 使你的密码安全<br>5.8.7. 使用安全连接<br>5.9. 备份与恢复<br>5.9.1. 据库备份<br>5.9.2. 示例用备份与恢复策略<br>5.9.3. 自动恢复<br>5.9.4. 表维护和崩溃恢复<br>5.9.5. myisamchk:MyISAM表维护实用工具<br>5.9.6. 建立表维护计划<br>5.9.7. 获取关于表的信息<br>5.10. MySQL本地化和国际应用<br>5.10.1. 据和排序用字符集<br>5.10.2. 设置错误消息语言<br>5.10.3. 添加新的字符集<br>5.10.4. 字符定义组<br>5.10.5. 字符串比较支持<br>5.10.6. 多字节字符支持<br>5.10.7. 字符集问题<br>5.10.8. MySQL服务器时区支持<br>5.11. MySQL日志文件<br>5.11.1. 错误日志<br>5.11.2. 通用查询日志<br>5.11.3. 二进制日志<br>5.11.4. 慢速查询日志<br>5.11.5. 日志文件维护<br>5.12. 在同一台机器上运行多个MySQL服务器<br>5.12.1. 在Windows下运行多个服务器<br>5.12.2. 在Unix中运行多个服务器<br>5.12.3. 在多服务器环境中使用客户端程序<br>5.13. MySQL查询高速缓冲<br>5.13.1. 查询高速缓冲如何工作<br>5.13.2. 查询高速缓冲SELECT选项<br>5.13.3. 查询高速缓冲配置<br>5.13.4. 查询高速缓冲状态和维护<br>6. MySQL中的复制<br>6.1. 复制介绍<br>6.2. 复制实施概述<br>6.3. 复制实施细节<br>6.3.1. 复制主线程状态<br>6.3.2. 复制从I/O线程状态<br>6.3.3. 复制从SQL线程状态<br>6.3.4. 复制传递和状态文件<br>6.4. 如何设置复制<br>6.5. 不同MySQL版本之间的复制兼容性<br>6.6. 升级复制设置<br>6.6.1. 将复制升级到5.0版<br>6.7. 复制特性和已知问题<br>6.8. 复制启动选项<br>6.9. 复制FAQ<br>6.10. 复制故障诊断与排除<br>6.11. 通报复制缺陷<br>6.12. 多服务器复制中的Auto-Increment<br>7. 优化<br>7.1. 优化概述<br>7.1.1. MySQL设计局限与折衷<br>7.1.2. 为可移植性设计应用程序<br>7.1.3. 我们已将MySQL用在何处?<br>7.1.4. MySQL基准套件<br>7.1.5. 使用自己的基准<br>7.2. 优化SELECT语句和其它查询<br>7.2.1. EXPLAIN语法(获取SELECT相关信息)<br>7.2.2. 估计查询性能<br>7.2.3. SELECT查询的速度<br>7.2.4. MySQL怎样优化WHERE子句<br>7.2.5. 范围优化<br>7.2.6. 索引合并优化<br>7.2.7. MySQL如何优化IS NULL<br>7.2.8. MySQL如何优化DISTINCT<br>7.2.9. MySQL如何优化LEFT JOIN和RIGHT JOIN<br>7.2.10. MySQL如何优化嵌套Join<br>7.2.11. MySQL如何简化外部联合<br>7.2.12. MySQL如何优化ORDER BY<br>7.2.13. MySQL如何优化GROUP BY<br>7.2.14. MySQL如何优化LIMIT<br>7.2.15. 如何避免表扫描<br>7.2.16. INSERT语句的速度<br>7.2.17. UPDATE语句的速度<br>7.2.18. DELETE语句的速度<br>7.2.19. 其它优化技巧<br>7.3. 锁定事宜<br>7.3.1. 锁定方法<br>7.3.2. 表锁定事宜<br>7.4. 优化据库结构<br>7.4.1. 设计选择<br>7.4.2. 使你的据尽可能小<br>7.4.3. 列索引<br>7.4.4. 多列索引<br>7.4.5. MySQL如何使用索引<br>7.4.6. MyISAM键高速缓冲<br>7.4.7. MyISAM索引统计集合<br>7.4.8. MySQL如何计算打开的表<br>7.4.9. MySQL如何打开和关闭表<br>7.4.10. 在同一个据库中创建多个表的缺陷<br>7.5. 优化MySQL服务器<br>7.5.1. 系统因素和启动参的调节<br>7.5.2. 调节服务器参<br>7.5.3. 控制查询优化器的性能<br>7.5.4. 编译和链接怎样影响MySQL的速度<br>7.5.5. MySQL如何使用内存<br>7.5.6. MySQL如何使用DNS<br>7.6. 磁盘事宜<br>7.6.1. 使用符号链接<br>8. 客户端和实用工具程序<br>8.1. 客户端脚本和实用工具概述<br>8.2. myisampack:生成压缩、只读MyISAM表<br>8.3. mysql:MySQL命令行工具<br>8.3.1. 选项<br>8.3.2. mysql命令<br>8.3.3. 怎样从文本文件执行SQL语句<br>8.3.4. mysql技巧<br>8.4. mysqlaccess:用于检查访问权限的客户端<br>8.5. mysqladmin:用于管理MySQL服务器的客户端<br>8.6. mysqlbinlog:用于处理二进制日志文件的实用工具<br>8.7. mysqlcheck:表维护和维修程序<br>8.8. mysqldump:据库备份程序<br>8.9. mysqlhotcopy:据库备份程序<br>8.10. mysqlimport:据导入程序<br>8.11. mysqlshow-显示据库、表和列信息<br>8.12. myisamlog:显示MyISAM日志文件内容<br>8.13. perror:解释错误代码<br>8.14. replace:字符串替换实用工具<br>8.15. mysql_zap:杀死符合某一模式的进程<br>9. 语言结构<br>9.1. 文字值<br>9.1.1. 字符串<br>9.1.2. 值<br>9.1.3. 十六进制值<br>9.1.4. 布尔值<br>9.1.5. 位字段值<br>9.1.6. NULL值<br>9.2. 据库、表、索引、列和别名<br>9.2.1. 识别符限制条件<br>9.2.2. 识别符大小写敏感性<br>9.3. 用户变量<br>9.4. 系统变量<br>9.4.1. 结构式系统变量<br>9.5. 注释语法<br>9.6. MySQL中保留字的处理<br>10. 字符集支持<br>10.1. 常规字符集和校对<br>10.2. MySQL中的字符集和校对<br>10.3. 确定默认字符集和校对<br>10.3.1. 服务器字符集和校对<br>10.3.2. 据库字符集和校对<br>10.3.3. 表字符集和校对<br>10.3.4. 列字符集和校对<br>10.3.5. 字符集和校对分配示例<br>10.3.6. 连接字符集和校对<br>10.3.7. 字符串文字字符集和校对<br>10.3.8. 在SQL语句中使用COLLATE<br>10.3.9. COLLATE子句优先<br>10.3.10. BINARY操作符<br>10.3.11. 校对确定较为复杂的一些特殊情况<br>10.3.12. 校对必须适合字符集<br>10.3.13. 校对效果的示例<br>10.4. 字符集支持影响到的操作<br>10.4.1. 结果字符串<br>10.4.2. CONVERT()<br>10.4.3. CAST()<br>10.4.4. SHOW语句<br>10.5. Unicode支持<br>10.6. 用于元据的UTF8<br>10.7. 与其它DBMS的兼容性<br>10.8. 新字符集配置文件格式<br>10.9. 国家特有字符集<br>10.10. MySQL支持的字符集和校对<br>10.10.1. Unicode字符集<br>10.10.2. 西欧字符集<br>10.10.3. 中欧字符集<br>10.10.4. 南欧与中东字符集<br>10.10.5. 波罗的海字符集<br>10.10.6. 西里尔字符集<br>10.10.7. 亚洲字符集<br>11. 列类型<br>11.1. 列类型概述<br>11.1.1. 值类型概述<br>11.1.2. 日期和时间类型概述<br>11.1.3. 字符串类型概述<br>11.2. 值类型<br>11.3. 日期和时间类型<br>11.3.1. DATETIME、DATE和TIMESTAMP类型<br>11.3.2. TIME类型<br>11.3.3. YEAR类型<br>11.3.4. Y2K事宜和日期类型<br>11.4. String类型<br>11.4.1. CHAR和VARCHAR类型<br>11.4.2. BINARY和VARBINARY类型<br>11.4.3. BLOB和TEXT类型<br>11.4.4. ENUM类型<br>11.4.5. SET类型<br>11.5. 列类型存储需求<br>11.6. 选择正确的列类型<br>11.7. 使用来自其他据库引擎的列类型<br>12. 函和操作符<br>12.1. 操作符<br>12.1.1. 操作符优先级<br>12.1.2. 圆括号<br>12.1.3. 比较函和操作符<br>12.1.4. 逻辑操作符<br>12.2. 控制流程函<br>12.3. 字符串函<br>12.3.1. 字符串比较函<br>12.4. 值函<br>12.4.1. 算术操作符<br>12.4.2. 学函<br>12.5. 日期和时间函<br>12.6. MySQL使用什么日历?<br>12.7. 全文搜索功能<br>12.7.1. 布尔全文搜索<br>12.7.2. 全文搜索带查询扩展<br>12.7.3. 全文停止字<br>12.7.4. 全文限定条件<br>12.7.5. 微调MySQL全文搜索<br>12.8. Cast函和操作符<br>12.9. 其他函<br>12.9.1. 位函<br>12.9.2. 加密函<br>12.9.3. 信息函<br>12.9.4. 其他函<br>12.10. 与GROUP BY子句同时使用的函和修改程序<br>12.10.1. GROUP BY(聚合)函<br>12.10.2. GROUP BY修改程序<br>12.10.3. 具有隐含字段的GROUP BY<br>13. SQL语句语法<br>13.1. 据定义语句<br>13.1.1. ALTER DATABASE语法<br>13.1.2. ALTER TABLE语法<br>13.1.3. CREATE DATABASE语法<br>13.1.4. CREATE INDEX语法<br>13.1.5. CREATE TABLE语法<br>13.1.6. DROP DATABASE语法<br>13.1.7. DROP INDEX语法<br>13.1.8. DROP TABLE语法<br>13.1.9. RENAME TABLE语法<br>13.2. 据操作语句<br>13.2.1. DELETE语法<br>13.2.2. DO语法<br>13.2.3. HANDLER语法<br>13.2.4. INSERT语法<br>13.2.5. LOAD DATA INFILE语法<br>13.2.6. REPLACE语法<br>13.2.7. SELECT语法<br>13.2.8. Subquery语法<br>13.2.9. TRUNCATE语法<br>13.2.10. UPDATE语法<br>13.3. MySQL实用工具语句<br>13.3.1. DESCRIBE语法(获取有关列的信息)<br>13.3.2. USE语法<br>13.4. MySQL事务处理和锁定语句<br>13.4.1. START TRANSACTION, COMMIT和ROLLBACK语法<br>13.4.2. 不能回滚的语句<br>13.4.3. 会造成隐式提交的语句<br>13.4.4. SAVEPOINT和ROLLBACK TO SAVEPOINT语法<br>13.4.5. LOCK TABLES和UNLOCK TABLES语法<br>13.4.6. SET TRANSACTION语法<br>13.4.7. XA事务<br>13.5. 据库管理语句<br>13.5.1. 账户管理语句<br>13.5.2. 表维护语句<br>13.5.3. SET语法<br>13.5.4. SHOW语法<br>13.5.5. 其它管理语句<br>13.6. 复制语句<br>13.6.1. 用于控制主服务器的SQL语句<br>13.6.2. 用于控制从服务器的SQL语句<br>13.7. 用于预处理语句的SQL语法<br>14. 插件式存储引擎体系结构<br>14.1. 前言<br>14.2. 概述<br>14.3. 公共MySQL据库服务器层<br>14.4. 选择存储引擎<br>14.5. 将存储引擎指定给表<br>14.6. 存储引擎和事务<br>14.7. 插入存储引擎<br>14.8. 拔出存储引擎<br>14.9. 插件式存储器的安全含义<br>15. 存储引擎和表类型<br>15.1. MyISAM存储引擎<br>15.1.1. MyISAM启动选项<br>15.1.2. 键所需的空间<br>15.1.3. MyISAM表的存储格式<br>15.1.4. MyISAM表方面的问题<br>15.2. InnoDB存储引擎<br>15.2.1. InnoDB概述<br>15.2.2. InnoDB联系信息<br>15.2.3. InnoDB配置<br>15.2.4. InnoDB启动选项<br>15.2.5. 创建InnoDB表空间<br>15.2.6. 创建InnoDB表<br>15.2.7. 添加和删除InnoDB据和日志文件<br>15.2.8. InnoDB据库的备份和恢复<br>15.2.9. 将InnoDB据库移到另一台机器上<br>15.2.10. InnoDB事务模型和锁定<br>15.2.11. InnoDB性能调节提示<br>15.2.12. 多版本的实施<br>15.2.13. 表和索引结构<br>15.2.14. 文件空间管理和磁盘I/O<br>15.2.15. InnoDB错误处理<br>15.2.16. 对InnoDB表的限制<br>15.2.17. InnoDB故障诊断与排除<br>15.3. MERGE存储引擎<br>15.3.1. MERGE表方面的问题<br>15.4. MEMORY (HEAP)存储引擎<br>15.5. BDB (BerkeleyDB)存储引擎<br>15.5.1. BDB支持的操作系统<br>15.5.2. 安装BDB<br>15.5.3. BDB启动选项<br>15.5.4. BDB表的特性<br>15.5.5. 修改BDB所需的事宜<br>15.5.6. 对BDB表的限制<br>15.5.7. 使用BDB表时可能出现的错误<br>15.6. EXAMPLE存储引擎<br>15.7. FEDERATED存储引擎<br>15.7.1. 安装FEDERATED存储引擎<br>15.7.2. FEDERATED存储引擎介绍<br>15.7.3. 如何使用FEDERATED表<br>15.7.4. FEDERATED存储引擎的局限性<br>15.8. ARCHIVE存储引擎<br>15.9. CSV存储引擎<br>15.10. BLACKHOLE存储引擎<br>16. 编写自定义存储引擎<br>16.1. 前言<br>16.2. 概述<br>16.3. 创建存储引擎源文件<br>16.4. 创建handlerton<br>16.5. 对处理程序进行实例化处理<br>16.6. 定义表扩展<br>16.7. 创建表<br>16.8. 打开表<br>16.9. 实施基本的表扫描功能<br>16.9.1. 实施store_lock()函<br>16.9.2. 实施external_lock()函<br>16.9.3. 实施rnd_init()函<br>16.9.4. 实施info()函<br>16.9.5. 实施extra()函<br>16.9.6. 实施rnd_next()函<br>16.10. 关闭表<br>16.11. 为存储引擎添加对INSERT的支持<br>16.12. 为存储引擎添加对UPDATE的支持<br>16.13. 为存储引擎添加对DELETE的支持<br>16.14. API引用<br>16.14.1. bas_ext<br>16.14.2. close<br>16.14.3. create<br>16.14.4. delete_row<br>16.14.5. delete_table<br>16.14.6. external_lock<br>16.14.7. extra<br>16.14.8. info<br>16.14.9. open<br>16.14.10. rnd_init<br>16.14.11. rnd_next<br>16.14.12. store_lock<br>16.14.13. update_row<br>16.14.14. write_row<br>17. MySQL簇<br>17.1. MySQL簇概述<br>17.2. MySQL簇的基本概念<br>17.3. 多计算机的简单基础知识<br>17.3.1. 硬件、软件和联网<br>17.3.2. 安装<br>17.3.3. 配置<br>17.3.4. 首次启动<br>17.3.5. 加载示例据并执行查询<br>17.3.6. 安全关闭和重启<br>17.4. MySQL簇的配置<br>17.4.1. 从源码创建MySQL簇<br>17.4.2. 安装软件<br>17.4.3. MySQL簇的快速测试设置<br>17.4.4. 配置文件<br>17.5. MySQL簇中的进程管理<br>17.5.1. 用于MySQL簇的MySQL服务器进程使用<br>17.5.2. ndbd,存储引擎节点进程<br>17.5.3. ndb_mgmd,“管理服务器”进程<br>17.5.4. ndb_mgm,“管理客户端”进程<br>17.5.5. 用于MySQL簇进程的命令选项<br>17.6. MySQL簇的管理<br>17.6.1. MySQL簇的启动阶段<br>17.6.2. “管理客户端”中的命令<br>17.6.3. MySQL簇中生成的事件报告<br>17.6.4. 单用户模式<br>17.6.5. MySQL簇的联机备份<br>17.7. 使用与MySQL簇的高速互连<br>17.7.1. 配置MySQL簇以使用SCI套接字<br>17.7.2. 理解簇互连的影响<br>17.8. MySQL簇的已知限制<br>17.9. MySQL簇发展的重要历程<br>17.9.1. MySQL 5.0中的MySQL簇变化<br>17.9.2. 关于MySQL簇的MySQL 5.1发展历程<br>17.10. MySQL簇常见问题解答<br>17.11. MySQL簇术语表<br>18. 分区<br>18.1. MySQL中的分区概述<br>18.2. 分区类型<br>18.2.1. RANGE分区<br>18.2.2. LIST分区<br>18.2.3. HASH分区<br>18.2.4. KEY分区<br>18.2.5. 子分区<br>18.2.6. MySQL分区处理NULL值的方式<br>18.3. 分区管理<br>18.3.1. RANGE和LIST分区的管理<br>18.3.2. HASH和KEY分区的管理<br>18.3.3. 分区维护<br>18.3.4. 获取关于分区的信息<br>19. MySQL中的空间扩展<br>19.1. 前言<br>19.2. OpenGIS几何模型<br>19.2.1. Geometry类的层次<br>19.2.2. 类Geometry<br>19.2.3. 类Point<br>19.2.4. 类Curve<br>19.2.5. 类LineString<br>19.2.6. 类Surface<br>19.2.7. 类Polygon<br>19.2.8. 类GeometryCollection<br>19.2.9. 类MultiPoint<br>19.2.10. 类MultiCurve<br>19.2.11. 类MultiLineString<br>19.2.12. 类MultiSurface<br>19.2.13. 类MultiPolygon<br>19.3. 支持的空间据格式<br>19.3.1. 著名的文本(WKT)格式<br>19.3.2. 著名的二进制(WKB)格式<br>19.4. 创建具备空间功能的MySQL据库<br>19.4.1. MySQL空间据类型<br>19.4.2. 创建空间值<br>19.4.3. 创建空间列<br>19.4.4. 填充空间列<br>19.4.5. 获取空间据<br>19.5. 分析空间信息<br>19.5.1. Geometry格式转换函<br>19.5.2. Geometry函<br>19.5.3. 从已有Geometry创建新Geometry的函<br>19.5.4. 测试几何对象间空间关系的函<br>19.5.5. 关于几何最小边界矩形(MBR)的关系<br>19.5.6. 测试几何类之间空间关系的函<br>19.6. 优化空间分析<br>19.6.1. 创建空间索引<br>19.6.2. 使用空间索引<br>19.7. MySQL的一致性和兼容性<br>19.7.1. 尚未实施的GIS特性<br>20. 存储程序和函<br>20.1. 存储程序和授权表<br>20.2. 存储程序的语法<br>20.2.1. CREATE PROCEDURE和CREATE FUNCTION<br>20.2.2. ALTER PROCEDURE和ALTER FUNCTION<br>20.2.3. DROP PROCEDURE和DROP FUNCTION<br>20.2.4. SHOW CREATE PROCEDURE和SHOW CREATE FUNCTION<br>20.2.5. SHOW PROCEDURE STATUS和SHOW FUNCTION STATUS<br>20.2.6. CALL语句<br>20.2.7. BEGIN ... END复合语句<br>20.2.8. DECLARE语句<br>20.2.9. 存储程序中的变量<br>20.2.10. 条件和处理程序<br>20.2.11. 光标<br>20.2.12. 流程控制构造<br>20.3. 存储程序、函、触发程序和复制:常见问题<br>20.4. 存储子程序和触发程序的二进制日志功能<br>21. 触发程序<br>21.1. CREATE TRIGGER语法<br>21.2. DROP TRIGGER语法<br>21.3. 使用触发程序<br>22. 视图<br>22.1. ALTER VIEW语法<br>22.2. CREATE VIEW语法<br>22.3. DROP VIEW语法<br>22.4. SHOW CREATE VIEW语法<br>23. INFORMATION_SCHEMA信息据库<br>23.1. INFORMATION_SCHEMA表<br>23.1.1. INFORMATION_SCHEMA SCHEMATA表<br>23.1.2. INFORMATION_SCHEMA TABLES表<br>23.1.3. INFORMATION_SCHEMA COLUMNS表<br>23.1.4. INFORMATION_SCHEMA STATISTICS表<br>23.1.5. INFORMATION_SCHEMA USER_PRIVILEGES表<br>23.1.6. INFORMATION_SCHEMA SCHEMA_PRIVILEGES表<br>23.1.7. INFORMATION_SCHEMA TABLE_PRIVILEGES表<br>23.1.8. INFORMATION_SCHEMA COLUMN_PRIVILEGES表<br>23.1.9. INFORMATION_SCHEMA CHARACTER_SETS表<br>23.1.10. INFORMATION_SCHEMA COLLATIONS表<br>23.1.11. INFORMATION_SCHEMA COLLATION_CHARACTER_SET_APPLICABILITY表<br>23.1.12. INFORMATION_SCHEMA TABLE_CONSTRAINTS表<br>23.1.13. INFORMATION_SCHEMA KEY_COLUMN_USAGE表<br>23.1.14. INFORMATION_SCHEMA ROUTINES表<br>23.1.15. INFORMATION_SCHEMA VIEWS表<br>23.1.16. INFORMATION_SCHEMA TRIGGERS表<br>23.1.17. 其他INFORMATION_SCHEMA表<br>23.2. SHOW语句的扩展<br>24. 精度学<br>24.1. 值的类型<br>24.2. DECIMAL据类型更改<br>24.3. 表达式处理<br>24.4. 四舍五入<br>24.5. 精度学示例<br>25. API和库<br>25.1. libmysqld,嵌入式MySQL服务器库<br>25.1.1. 嵌入式MySQL服务器库概述<br>25.1.2. 使用libmysqld编译程序<br>25.1.3. 使用嵌入式MySQL服务器时的限制<br>25.1.4. 与嵌入式服务器一起使用的选项<br>25.1.5. 嵌入式服务器中尚需完成的事项(TODO)<br>25.1.6. 嵌入式服务器示例<br>25.1.7. 嵌入式服务器的许可<br>25.2. MySQL C API<br>25.2.1. C API据类型<br>25.2.2. C API函概述<br>25.2.3. C API函描述<br>25.2.4. C API预处理语句<br>25.2.5. C API预处理语句的据类型<br>25.2.6. C API预处理语句函概述<br>25.2.7. C API预处理语句函描述<br>25.2.8. C API预处理语句方面的问题<br>25.2.9. 多查询执行的C API处理<br>25.2.10. 日期和时间值的C API处理<br>25.2.11. C API线程函介绍<br>25.2.12. C API嵌入式服务器函介绍<br>25.2.13. 使用C API时的常见问题<br>25.2.14. 创建客户端程序<br>25.2.15. 如何生成线程式客户端<br>25.3. MySQL PHP API<br>25.3.1. 使用MySQL和PHP的常见问题<br>25.4. MySQL Perl API<br>25.5. MySQL C++ API<br>25.5.1. Borland C++<br>25.6. MySQL Python API<br>25.7. MySQL Tcl API<br>25.8. MySQL Eiffel Wrapper<br>25.9. MySQL程序开发实用工具<br>25.9.1. msql2mysql:转换mSQL程序以用于MySQL<br>25.9.2. mysql_config:获取编译客户端的编译选项<br>26. 连接器<br>26.1. MySQL Connector/ODBC<br>26.1.1. MyODBC介绍<br>26.1.2. 关于ODBC和MyODBC的一般信息<br>26.1.3. 如何安装MyODBC<br>26.1.4. 在Windows平台上从二进制版本安装MyODBC<br>26.1.5. I在Unix平台上从二进制版本安装MyODBC <br>26.1.6. 在Windows平台上从源码版本安装MyODBC<br>26.1.7. 在Unix平台上从源码版本安装MyODBC <br>26.1.8. 从BitKeeper开发源码树安装MyODBC<br>26.1.9. MyODBC配置<br>26.1.10. 与MyODBC连接相关的事宜<br>26.1.11. MyODBC和Microsoft Access<br>26.1.12. MyODBC和Microsoft VBA及ASP<br>26.1.13. MyODBC和第三方ODBC工具<br>26.1.14. MyODBC通用功能<br>26.1.15. 基本的MyODBC应用步骤<br>26.1.16. MyODBC API引用<br>26.1.17. MyODBC据类型<br>26.1.18. MyODBC错误代码<br>26.1.19. MyODBC与VB:ADO、DAO和RDO<br>26.1.20. MyODBC与Microsoft.NET<br>26.1.21. 感谢<br>26.2. MySQL Connector/NET<br>26.2.1. 前言<br>26.2.2. 下载并安装MySQL Connector/NET<br>26.2.3. Connector/NET体系结构<br>26.2.4. 使用MySQL Connector/NET<br>26.2.5. MySQL Connector/NET变更史<br>26.3. MySQL Connector/J<br>26.3.1. 基本的JDBC概念<br>26.3.2. 安装 Connector/J<br>26.3.3. JDBC引用<br>26.3.4. 与J2EE和其他Java框架一起使用 Connector/J<br>26.3.5. 诊断 Connector/J方面的问题<br>26.3.6. Changelog<br>26.4. MySQL Connector/MXJ<br>26.4.1. 前言<br>26.4.2. 支持平台:<br>26.4.3. Junit测试要求<br>26.4.4. 运行Junit测试<br>26.4.5. 作为JDBC驱动程序的一部分运行<br>26.4.6. 在Java对象中运行<br>26.4.7. MysqldResource API<br>26.4.8. 在JMX代理(custom)中运行<br>26.4.9. 部署在标准的JMX代理环境下 (JBoss)<br>26.4.10. 安装<br>27. 扩展MySQL<br>27.1. MySQL内部控件<br>27.1.1. MySQL线程<br>27.1.2. MySQL测试套件<br>27.2. 为MySQL添加新函<br>27.2.1. 自定义函接口的特性<br>27.2.2. CREATE FUNCTION/DROP FUNCTION语法<br>27.2.3. 添加新的自定义函<br>27.2.4. 添加新的固有函<br>27.3. 为MySQL添加新步骤<br>27.3.1. 步骤分析<br>27.3.2. 编写步骤<br>A. 问题和常见错误<br>A.1. 如何确定导致问题的原因<br>A.2. 使用MySQL程序时的常见错误<br>A.2.1. 拒绝访问<br>A.2.2. 无法连接到[local] MySQL服务器<br>A.2.3. 客户端不支持鉴定协议<br>A.2.4. 输入密码时出现密码错误<br>A.2.5. 主机的host_name被屏蔽<br>A.2.6. 连接过多<br>A.2.7. 内存溢出<br>A.2.8. MySQL服务器不可用<br>A.2.9. 信息包过大<br>A.2.10. 通信错误和失效连接<br>A.2.11. 表已满<br>A.2.12. 无法创建文件/写入文件<br>A.2.13. 命令不同步<br>A.2.14. 忽略用户<br>A.2.15. 表tbl_name不存在<br>A.2.16. 无法初始化字符集<br>A.2.17. 文件未找到<br>A.3. 与安装有关的事宜<br>A.3.1. 与MySQL客户端库的链接问题<br>A.3.2. 如何以普通用户身份运行MySQL<br>A.3.3. 与文件许可有关的问题<br>A.4. 与管理有关的事宜<br>A.4.1. 如何复位根用户密码<br>A.4.2. 如果MySQL依然崩溃,应作些什么<br>A.4.3. MySQL处理磁盘满的方式<br>A.4.4. MySQL将临时文件储存在哪里<br>A.4.5. 如何保护或更改MySQL套接字文件/tmp/mysql.sock<br>A.4.6. 时区问题<br>A.5. 与查询有关的事宜<br>A.5.1. 搜索中的大小写敏感性<br>A.5.2. 使用DATE列方面的问题<br>A.5.3. 与NULL值有关的问题<br>A.5.4. 与列别名有关的问题<br>A.5.5. 非事务表回滚失败<br>A.5.6. 从相关表删除行<br>A.5.7. 解决与不匹配行有关的问题<br>A.5.8. 与浮点比较有关的问题<br>A.6. 与优化器有关的事宜<br>A.7. 与表定义有关的事宜<br>A.7.1. 与ALTER TABLE有关的问题<br>A.7.2. 如何更改表中的列顺序<br>A.7.3. TEMPORARY TABLE问题<br>A.8. MySQL中的已知事宜<br>A.8.1. MySQL中的打开事宜<br>B. 错误代码和消息<br>B.1. 服务器错误代码和消息<br>B.2. 客户端错误代码和消息<br>C. 感谢<br>C.1. MySQL AB处的开发人<br>C.2. MySQL贡献人<br>C.3. 资料员和译员<br>C.4. MySQL使用和包含的库<br>C.5. 支持MySQL的软件包<br>C.6. 用于创建MySQL的工具<br>C.7. MySQL支持人员<br>D. MySQL变更史<br>D.1. 5.1.x版中的变更情况(开发)<br>D.1.1. 5.1.2版中的变更情况(尚未发布)<br>D.1.2. 5.1.1版中的变更情况(尚未发布)<br>D.2. MyODBC的变更情况<br>D.2.1. MyODBC 3.51.12的变更情况<br>D.2.2. MyODBC 3.51.11的变更情况<br>E. 移植到其他系统<br>E.1. 调试MySQL服务器<br>E.1.1. 针对调试编译MySQL<br>E.1.2. 创建跟踪文件<br>E.1.3. 在gdb环境下调试mysqld<br>E.1.4. 使用堆栈跟踪<br>E.1.5. 使用日志文件找出mysqld中的错误原因<br>E.1.6. 如果出现表崩溃,请生成测试案例<br>E.2. 调试MySQL客户端<br>E.3. DBUG软件包<br>E.4. 关于RTS线程的注释<br>E.5. 线程软件包之间的差异<br>F. 环境变量<br>G. MySQL正则表达式<br>H. MySQL中的限制<br>H.1. 联合的限制<br>I. 特性限制<br>I.1. 对存储子程序和触发程序的限制<br>I.2. 对服务器端光标的限制<br>I.3. 对子查询的限制<br>I.4. 对视图的限制<br>I.5. 对XA事务的限制<br>J. GNU通用公共许可<br>K. MySQL FLOSS许可例外<br>索引<br>图形清单<br><br>14.1. MySQL插件式存储引擎的体系结构<br>14.2. 存储引擎比较<br>16.1. MySQL体系结构<br>表格清单<br><br>26.1. 连接属性<br>26.2. 转换表<br>26.3. 用于ResultSet.getObject()的MySQL类型和Java类型<br>26.4. MySQL对Java编码名称的翻译<br>示例清单<br><br>26.1. 从DriverManager获得连接<br>26.2. 使用java.sql.Statement执行SELECT查询<br>26.3. 存储程序示例<br>26.4. 使用Connection.prepareCall()<br>26.5. 注册输出<br>26.6. 设置CallableStatement输入参<br>26.7. 检索结果和输出值<br>26.8. 使用Statement.getGeneratedKeys()检索AUTO_INCREMENT列的值<br>26.9. 使用SELECT LAST_INSERT_ID()检索AUTO_INCREMENT列的值<br>26.10. 在可更新的ResultSets中检索AUTO_INCREMENT列的值<br>26.11. 设置Unix环境下的CLASSPATH<br>26.12. 与J2EE应用服务器一起使用连接池<br>26.13. 重试逻辑的事务示例
适用于初第七章:结构与联合 结构类型定义和结构变量说明   在实际问题中,一组据往往具有不同的据类型。例如, 在学生登记表中,姓名应为字符型;学号可为整型或字符型; 年龄应为整型;性别应为字符型;成绩可为整型或实型。 显然不能用一个组来存放这一组据。 因为数组中各元素的类型和长度都必须一致,以便于编译系统处理。为了解决这个问题,C语言中给出了另一种构造据类型——“结构”。 它相当于其它高级语言中的记录。   “结构”是一种构造类型,它是由若干“成员”组成的。 每一个成员可以是一个基本据类型或者又是一个构造类型。 结构既是一种“构造”而成的据类型, 那么在说明和使用之前必须先定义它,也就是构造它。如同在说明和调用函之前要先定义函一样。 一、结构的定义 定义一个结构的一般形式为: struct 结构名 { 成员表列 }; 成员表由若干个成员组成, 每个成员都是该结构的一个组成部分。对每个成员也必须作类型说明,其形式为: 类型说明符 成员名; 成员名的命名应符合标识符的书写规定。例如: struct stu { int num; char name[20]; char sex; float score; };   在这个结构定义中,结构名为stu,该结构由4个成员组成。 第一个成员为num,整型变量;第二个成员为name,字符组;第三个成员为sex,字符变量;第四个成员为score,实型变量。 应注意在括号后的分号是不可少的。结构定义之后,即可进行变量说明。 凡说明为结构stu的变量都由上述4个成员组成。由此可见, 结构是一种复杂的据类型,是目固定,类型不同的若干有序变量的集合。 二、结构类型变量的说明 说明结构变量有以下三种方法。以上面定义的stu为例来加以说明。 1. 先定义结构,再说明结构变量。如: struct stu { int num; char name[20]; char sex; float score; }; struct stu boy1,boy2; 说明了两个变量boy1和boy2为stu结构类型。也可以用宏定义使一个符号常量来表示一个结构类型,例如: #define STU struct stu STU { int num; char name[20]; char sex; float score; }; STU boy1,boy2; 2. 在定义结构类型的同时说明结构变量。例如: struct stu { int num; char name[20]; char sex; float score; }boy1,boy2; 3. 直接说明结构变量。例如: struct { int num; char name[20]; char sex; float score; }boy1,boy2;   第三种方法与第二种方法的区别在于第三种方法中省去了结构名,而直接给出结构变量。三种方法中说明的boy1,boy2变量都具有图7.1所示的结构。说明了boy1,boy2变量为stu类型后,即可向这两个变量中的各个成员赋值。在上述stu结构定义中,所有的成员都是基本据类型或组类型。成员也可以又是一个结构, 即构成了嵌套的结构。例如,图7.2给出了另一个据结构。 按图7.2可给出以下结构定义: struct date{ int month; int day; int year; } struct{ int num; char name[20]; char sex; struct date birthday; float score; }boy1,boy2;   首先定义一个结构date,由month(月)、day(日)、year(年) 三个成员组成。 在定义并说明变量 boy1 和 boy2 时, 其中的成员birthday被说明为data结构类型。成员名可与程序中其它变量同名,互不干扰。结构变量成员的表示方法在程序中使用结构变量时, 往往不把它作为一个整体来使用。   在ANSI C中除了允许具有相同类型的结构变量相互赋值以外, 一般对结构变量的使用,包括赋值、输入、输出、 运算等都是通过结构变量的成员来实现的。   表示结构变量成员的一般形式是: 结构变量名.成员名 例如:boy1.num 即第一个人的学号 boy2.sex 即第二个人的性别 如果成员本身又是一个结构则必须逐级找到最低级的成员才能使用。例如:boy1.birthday.month 即第一个人出生的月份成员可以在程序中单独使用,与普通变量完全相同。 结构变量的赋值 前面已经介绍,结构变量的赋值就是给各成员赋值。 可用输入语句或赋值语句来完成。 [例7.1]给结构变量赋值并输出其值。 main(){ struct stu { int num; char *name; char sex; float score; } boy1,boy2; boy1.num=102; boy1.name="Zhang ping"; printf("input sex and score\n"); scanf("%c %f",&boy1.sex,&boy1.score); boy2=boy1; printf("Number=%d\nName=%s\n",boy2.num,boy2.name); printf("Sex=%c\nScore=%f\n",boy2.sex,boy2.score); }   本程序中用赋值语句给num和name两个成员赋值,name是一个字符串指针变量。用scanf函动态地输入sex和score成员值,然后把boy1的所有成员的值整体赋予boy2。最后分别输出boy2 的各个成员值。本例表示了结构变量的赋值、输入和输出的方法。 结构变量的初始化   如果结构变量是全局变量或为静态变量, 则可对它作初始化赋值。对局部或自动结构变量不能作初始化赋值。 [例7.2]外部结构变量初始化。 struct stu /*定义结构*/ { int num; char *name; char sex; float score; } boy2,boy1={102,"Zhang ping",'M',78.5}; main() { boy2=boy1; printf("Number=%d\nName=%s\n",boy2.num,boy2.name); printf("Sex=%c\nScore=%f\n",boy2.sex,boy2.score); } struct stu { int num; char *name; char sex; float score; }boy2,boy1={102,"Zhang ping",'M',78.5}; main() { boy2=boy1; …… } 本例中,boy2,boy1均被定义为外部结构变量,并对boy1作了初始化赋值。在main函中,把boy1的值整体赋予boy2, 然后用两个printf语句输出boy2各成员的值。 [例7.3]静态结构变量初始化。 main() { static struct stu /*定义静态结构变量*/ { int num; char *name; char sex; float score; }boy2,boy1={102,"Zhang ping",'M',78.5}; boy2=boy1; printf("Number=%d\nName=%s\n",boy2.num,boy2.name); printf("Sex=%c\nScore=%f\n",boy2.sex,boy2.score); } static struct stu { int num; char *name; char sex; float score; }boy2,boy1={102,"Zhang ping",'M',78.5};   本例是把boy1,boy2都定义为静态局部的结构变量, 同样可以作初始化赋值。 结构组的元素也可以是结构类型的。 因此可以构成结构型组。结构组的每一个元素都是具有相同结构类型的下标结构变量。 在实际应用中,经常用结构组来表示具有相同据结构的一个群体。如一个班的学生档案,一个车间职工的工资表等。 结构组的定义方法和结构变量相似,只需说明它为组类型即可。例如: struct stu { int num; char *name; char sex; float score; }boy[5]; 定义了一个结构组boy1,共有5个元素,boy[0]~boy[4]。每个组元素都具有struct stu的结构形式。 对外部结构组或静态结构组可以作初始化赋值,例如: struct stu { int num; char *name; char sex; float score; }boy[5]={ {101,"Li ping","M",45}, {102,"Zhang ping","M",62.5}, {103,"He fang","F",92.5}, {104,"Cheng ling","F",87}, {105,"Wang ming","M",58}; } 当对全部元素作初始化赋值时,也可不给出组长度。 [例7.4]计算学生的平均成绩和不及格的人。 struct stu { int num; char *name; char sex; float score; }boy[5]={ {101,"Li ping",'M',45}, {102,"Zhang ping",'M',62.5}, {103,"He fang",'F',92.5}, {104,"Cheng ling",'F',87}, {105,"Wang ming",'M',58}, }; main() { int i,c=0; float ave,s=0; for(i=0;i<5;i++) { s+=boy[i].score; if(boy[i].score<60) c+=1; } printf("s=%f\n",s); ave=s/5; printf("average=%f\ncount=%d\n",ave,c); } 本例程序中定义了一个外部结构组boy,共5个元素, 并作了初始化赋值。在main函中用for语句逐个累加各元素的score 成员值存于s之中,如score的值小于60(不及格)即计器C加1, 循环完毕后计算平均成绩,并输出全班总分,平均分及不及格人。 [例7.5]建立同学通讯录 #include"stdio.h" #define NUM 3 struct mem { char name[20]; char phone[10]; }; main() { struct mem man[NUM]; int i; for(i=0;i<NUM;i++) { printf("input name:\n"); gets(man[i].name); printf("input phone:\n"); gets(man[i].phone); } printf("name\t\t\tphone\n\n"); for(i=0;i<NUM;i++) printf("%s\t\t\t%s\n",man[i].name,man[i].phone); }   本程序中定义了一个结构mem,它有两个成员name和phone 用来表示姓名和电话号码。在主函中定义man为具有mem 类型的结构组。在for语句中,用gets函分别输入各个元素中两个成员的值。然后又在for语句中用printf语句输出各元素中两个成员值。 结构指针变量 结构指针变量的说明和使用一个指针变量当用来指向一个结构变量时, 称之为结构指针变量。 结构指针变量中的值是所指向的结构变量的首地址。 通过结构指针即可访问该结构变量, 这与组指针和函指针的情况是相同的。结构指针变量说明的一般形式为: struct 结构名*结构指针变量名 例如,在前面的例7.1中定义了stu这个结构, 如要说明一个指向stu的指针变量pstu,可写为: struct stu *pstu;   当然也可在定义stu结构时同时说明pstu。与前面讨论的各类指针变量相同,结构指针变量也必须要先赋值后才能使用。赋值是把结构变量的首地址赋予该指针变量, 不能把结构名赋予该指针变量。如果boy是被说明为stu类型的结构变量,则: pstu=&boy是正确的,而: pstu=&stu是错误的。   结构名和结构变量是两个不同的概念,不能混淆。 结构名只能表示一个结构形式,编译系统并不对它分配内存空间。 只有当某变量被说明为这种类型的结构时,才对该变量分配存储空间。 因此上面&stu这种写法是错误的,不可能去取一个结构名的首地址。 有了结构指针变量,就能更方便地访问结构变量的各个成员。 其访问的一般形式为: (*结构指针变量).成员名 或为: 结构指针变量->成员名 例如: (*pstu).num或者: pstu->num 应该注意(*pstu)两侧的括号不可少, 因为成员符“.”的优先级高于“*”。如去掉括号写作*pstu.num则等效于*(pstu.num),这样,意义就完全不对了。 下面通过例子来说明结构指针变量的具体说明和使用方法。 [例7.6] struct stu { int num; char *name; char sex; float score; } boy1={102,"Zhang ping",'M',78.5},*pstu; main() { pstu=&boy1; printf("Number=%d\nName=%s\n",boy1.num,boy1.name); printf("Sex=%c\nScore=%f\n\n",boy1.sex,boy1.score); printf("Number=%d\nName=%s\n",(*pstu).num,(*pstu).name); printf("Sex=%c\nScore=%f\n\n",(*pstu).sex,(*pstu).score); printf("Number=%d\nName=%s\n",pstu->num,pstu->name); printf("Sex=%c\nScore=%f\n\n",pstu->sex,pstu->score); }   本例程序定义了一个结构stu,定义了stu类型结构变量boy1 并作了初始化赋值,还定义了一个指向stu类型结构的指针变量pstu。在main函中,pstu被赋予boy1的地址,因此pstu指向boy1 。然后在printf语句内用三种形式输出boy1的各个成员值。 从运行结果可以看出: 结构变量.成员名 (*结构指针变量).成员名 结构指针变量->成员名   这三种用于表示结构成员的形式是完全等效的。结构组指针变量结构指针变量可以指向一个结构组, 这时结构指针变量的值是整个结构组的首地址。 结构指针变量也可指向结构组的一个元素,这时结构指针变量的值是该结构组元素的首地址。设ps为指向结构组的指针变量,则ps也指向该结构组的0号元素,ps+1指向1号元素,ps+i则指向i号元素。 这与普通组的情况是一致的。 [例7.7]用指针变量输出结构组。 struct stu { int num; char *name; char sex; float score; }boy[5]={ {101,"Zhou ping",'M',45}, {102,"Zhang ping",'M',62.5}, {103,"Liou fang",'F',92.5}, {104,"Cheng ling",'F',87}, {105,"Wang ming",'M',58}, }; main() { struct stu *ps; printf("No\tName\t\t\tSex\tScore\t\n"); for(ps=boy;ps<boy+5;ps++) printf("%d\t%s\t\t%c\t%f\t\n",ps->num,ps->name,ps->sex,ps-> score); }   在程序中,定义了stu结构类型的外部组boy 并作了初始化赋值。在main函内定义ps为指向stu类型的指针。在循环语句for的表达式1中,ps被赋予boy的首地址,然后循环5次,输出boy数组中各成员值。 应该注意的是, 一个结构指针变量虽然可以用来访问结构变量或结构组元素的成员,但是,不能使它指向一个成员。 也就是说不允许取一个成员的地址来赋予它。因此,下面的赋值是错误的。 ps=&boy[1].sex;而只能是:ps=boy;(赋予组首地址) 或者是: ps=&boy[0];(赋予0号元素首地址) 结构指针变量作函   在ANSI C标准中允许用结构变量作函进行整体传送。 但是这种传送要将全部成员逐个传送, 特别是成员为组时将会使传送的时间和空间开销很大,严重地降低了程序的效率。 因此最好的办法就是使用指针,即用指针变量作函进行传送。 这时由实参传向形参的只是地址,从而减少了时间和空间的开销。 [例7.8]题目与例7.4相同,计算一组学生的平均成绩和不及格人。 用结构指针变量作函编程。 struct stu { int num; char *name; char sex; float score;}boy[5]={ {101,"Li ping",'M',45}, {102,"Zhang ping",'M',62.5}, {103,"He fang",'F',92.5}, {104,"Cheng ling",'F',87}, {105,"Wang ming",'M',58}, }; main() { struct stu *ps; void ave(struct stu *ps); ps=boy; ave(ps); } void ave(struct stu *ps) { int c=0,i; float ave,s=0; for(i=0;i<5;i++,ps++) { s+=ps->score; if(ps->score<60) c+=1; } printf("s=%f\n",s); ave=s/5; printf("average=%f\ncount=%d\n",ave,c); }   本程序中定义了函ave,其形参为结构指针变量ps。boy 被定义为外部结构组,因此在整个源程序中有效。在main 函中定义说明了结构指针变量ps,并把boy的首地址赋予它,使ps指向boy 组。然后以ps作实参调用函ave。在函ave 中完成计算平均成绩和统计不及格人的工作并输出结果。与例7.4程序相比,由于本程序全部采用指针变量作运算和处理,故速度更快,程序效率更高。. topoic=动态存储分配   在组一章中,曾介绍过组的长度是预先定义好的, 在整个程序中固定不变。C语言中不允许动态组类型。例如: int n;scanf("%d",&n);int a[n]; 用变量表示长度,想对组的大小作动态说明, 这是错误的。但是在实际的编程中,往往会发生这种情况, 即所需的内存空间取决于实际输入的据,而无法预先确定。对于这种问题, 用组的办法很难解决。为了解决上述问题,C语言提供了一些内存管理函,这些内存管理函可以按需要动态地分配内存空间, 也可把不再使用的空间回收待用,为有效地利用内存资源提供了手段。 常用的内存管理函有以下三个: 1.分配内存空间函malloc 调用形式: (类型说明符*) malloc (size) 功能:在内存的动态存储区中分配一块长度为"size" 字节的连续区域。函的返回值为该区域的首地址。 “类型说明符”表示把该区域用于何种据类型。(类型说明符*)表示把返回值强制转换为该类型指针。“size”是一个无符号。例如: pc=(char *) malloc (100); 表示分配100个字节的内存空间,并强制转换为字符组类型, 函的返回值为指向该字符组的指针, 把该指针赋予指针变量pc。 2.分配内存空间函 calloc calloc 也用于分配内存空间。调用形式: (类型说明符*)calloc(n,size) 功能:在内存动态存储区中分配n块长度为“size”字节的连续区域。函的返回值为该区域的首地址。(类型说明符*)用于强制类型转换。calloc函与malloc 函的区别仅在于一次可以分配n块区域。例如: ps=(struet stu*) calloc(2,sizeof (struct stu)); 其中的sizeof(struct stu)是求stu的结构长度。因此该语句的意思是:按stu的长度分配2块连续区域,强制转换为stu类型,并把其首地址赋予指针变量ps。 3.释放内存空间函free 调用形式: free(void*ptr); 功能:释放ptr所指向的一块内存空间,ptr 是一个任意类型的指针变量,它指向被释放区域的首地址。被释放区应是由malloc或calloc函所分配的区域:[例7.9]分配一块区域,输入一个学生据。 main() { struct stu { int num; char *name; char sex; float score; } *ps; ps=(struct stu*)malloc(sizeof(struct stu)); ps->num=102; ps->name="Zhang ping"; ps->sex='M'; ps->score=62.5; printf("Number=%d\nName=%s\n",ps->num,ps->name); printf("Sex=%c\nScore=%f\n",ps->sex,ps->score); free(ps); }   本例中,定义了结构stu,定义了stu类型指针变量ps。 然后分配一块stu大内存区,并把首地址赋予ps,使ps指向该区域。再以ps为指向结构的指针变量对各成员赋值,并用printf 输出各成员值。最后用free函释放ps指向的内存空间。 整个程序包含了申请内存空间、使用内存空间、释放内存空间三个步骤, 实现存储空间的动态分配。链表的概念在例7.9中采用了动态分配的办法为一个结构分配内存空间。每一次分配一块空间可用来存放一个学生的据, 我们可称之为一个结点。有多少个学生就应该申请分配多少块内存空间, 也就是说要建立多少个结点。当然用结构组也可以完成上述工作, 但如果预先不能准确把握学生人,也就无法确定组大小。 而且当学生留级、退学之后也不能把该元素占用的空间从数组中释放出来。 用动态存储的方法可以很好地解决这些问题。 有一个学生就分配一个结点,无须预先确定学生的准确人,某学生退学, 可删去该结点,并释放该结点占用的存储空间。从而节约了宝贵的内存资源。 另一方面,用组的方法必须占用一块连续的内存区域。 而使用动态分配时,每个结点之间可以是不连续的(结点内是连续的)。 结点之间的联系可以用指针实现。 即在结点结构中定义一个成员项用来存放下一结点的首地址,这个用于存放地址的成员,常把它称为指针域。可在第一个结点的指针域内存入第二个结点的首地址, 在第二个结点的指针域内又存放第三个结点的首地址, 如此串连下去直到最后一个结点。最后一个结点因无后续结点连接,其指针域可赋为0。这样一种连接方式,在据结构中称为“链表”。图7.3为链表的示意图。   在图7.3中,第0个结点称为头结点, 它存放有第一个结点的首地址,它没有据,只是一个指针变量。 以下的每个结点都分为两个域,一个据域,存放各种实际的据,如学号num,姓名name,性别sex和成绩score等。另一个域为指针域, 存放下一结点的首地址。链表中的每一个结点都是同一种结构类型。例如, 一个存放学生学号和成绩的结点应为以下结构: struct stu { int num; int score; struct stu *next; }   前两个成员项组成据域,后一个成员项next构成指针域, 它是一个指向stu类型结构的指针变量。链表的基本操作对链表的主要操作有以下几种: 1.建立链表; 2.结构的查找输出; 3.插入一个结点; 4.删除一个结点; 下面通过例题来说明这些操作。 [例7.10]建立一个三个结点的链表,存放学生据。 为简单起见, 我们假定学生据结构中只有学号和年龄两项。 可编写一个建立链表的函creat。程序如下: #define NULL 0 #define TYPE struct stu #define LEN sizeof (struct stu) struct stu { int num; int age; struct stu *next; }; TYPE *creat(int n) { struct stu *head,*pf,*pb; int i; for(i=0;i<n;i++) { pb=(TYPE*) malloc(LEN); printf("input Number and Age\n"); scanf("%d%d",&pb->num,&pb->age); if(i==0) pf=head=pb; else pf->next=pb; pb->next=NULL; pf=pb; } return(head); }   在函外首先用宏定义对三个符号常量作了定义。这里用TYPE表示struct stu,用LEN表示sizeof(struct stu)主要的目的是为了在以下程序内减少书写并使阅读更加方便。结构stu定义为外部类型,程序中的各个函均可使用该定义。   creat函用于建立一个有n个结点的链表,它是一个指针函,它返回的指针指向stu结构。在creat函内定义了三个stu结构的指针变量。head为头指针,pf 为指向两相邻结点的前一结点的指针变量。pb为后一结点的指针变量。在for语句内,用malloc函建立长度与stu长度相等的空间作为一结点,首地址赋予pb。然后输入结点据。如果当前结点为第一结点(i==0),则把pb值 (该结点指针)赋予head和pf。如非第一结点,则把pb值赋予pf 所指结点的指针域成员next。而pb所指结点为当前的最后结点,其指针域赋NULL。 再把pb值赋予pf以作下一次循环准备。   creat函的形参n,表示所建链表的结点,作为for语句的循环次。图7.4表示了creat函的执行过程。 [例7.11]写一个,在链表中按学号查找该结点。 TYPE * search (TYPE *head,int n) { TYPE *p; int i; p=head; while (p->num!=n && p->next!=NULL) p=p->next; /* 不是要找的结点后移一步*/ if (p->num==n) return (p); if (p->num!=n&& p->next==NULL) printf ("Node %d has not been found!\n",n }   本函中使用的符号常量TYPE与例7.10的宏定义相同,等于struct stu。函有两个形参,head是指向链表的指针变量,n为要查找的学号。进入while语句,逐个检查结点的num成员是否等于n,如果不等于n且指针域不等于NULL(不是最后结点)则后移一个结点,继续循环。如找到该结点则返回结点指针。 如循环结束仍未找到该结点则输出“未找到”的提示信息。 [例7.12]写一个,删除链表中的指定结点。删除一个结点有两种情况: 1. 被删除结点是第一个结点。这种情况只需使head指向第二个结点即可。即head=pb->next。其过程如图7.5所示。 2. 被删结点不是第一个结点,这种情况使被删结点的前一结点指向被删结点的后一结点即可。即pf->next=pb->next。其过程如图7.6所示。 函编程如下: TYPE * delete(TYPE * head,int num) { TYPE *pf,*pb; if(head==NULL) /*如为空表, 输出提示信息*/ { printf("\nempty list!\n"); goto end;} pb=head; while (pb->num!=num && pb->next!=NULL) /*当不是要删除的结点,而且也不是最后一个结点时,继续循环*/ {pf=pb;pb=pb->next;}/*pf指向当前结点,pb指向下一结点*/ if(pb->num==num) {if(pb==head) head=pb->next; /*如找到被删结点,且为第一结点,则使head指向第二个结点, 否则使pf所指结点的指针指向下一结点*/ else pf->next=pb->next; free(pb); printf("The node is deleted\n");} else printf("The node not been foud!\n"); end: return head; }   函有两个形参,head为指向链表第一结点的指针变量,num删结点的学号。 首先判断链表是否为空,为空则不可能有被删结点。若不为空,则使pb指针指向链表的第一个结点。进入while语句后逐个查找被删结点。找到被删结点之后再看是否为第一结点,若是则使head指向第二结点(即把第一结点从链中删去),否则使被删结点的前一结点(pf所指)指向被删结点的后一结点(被删结点的指针域所指)。如若循环结束未找到要删的结点, 则输出“末找到”的提示信息。最后返回head值。 [例7.13]写一个,在链表中指定位置插入一个结点。在一个链表的指定位置插入结点, 要求链表本身必须是已按某种规律排好序的。例如,在学生据链表中, 要求学号顺序插入一个结点。设被插结点的指针为pi。 可在三种不同情况下插入。 1. 原表是空表,只需使head指向被插结点即可。见图7.7(a) 2. 被插结点值最小,应插入第一结点之前。这种情况下使head指向被插结点,被插结点的指针域指向原来的第一结点则可。即:pi->next=pb; head=pi; 见图7.7(b) 3. 在其它位置插入,见图7.7(c)。这种情况下,使插入位置的前一结点的指针域指向被插结点,使被插结点的指针域指向插入位置的后一结点。即为:pi->next=pb;pf->next=pi; 4. 在表末插入,见图7.7(d)。这种情况下使原表末结点指针域指向被插结点,被插结点指针域置为NULL。即: pb->next=pi; pi->next=NULL; TYPE * insert(TYPE * head,TYPE *pi) { TYPE *pf,*pb; pb=head; if(head==NULL) /*空表插入*/ (head=pi; pi->next=NULL;} else { while((pi->num>pb->num)&&(pb->next!=NULL)) {pf=pb; pb=pb->next; }/*找插入位置*/ if(pi->num<=pb->num) {if(head==pb)head=pi;/*在第一结点之前插入*/ else pf->next=pi;/*在其它位置插入*/ pi->next=pb; } else {pb->next=pi; pi->next=NULL;} /*在表末插入*/ } return head;}   本函有两个形参均为指针变量,head指向链表,pi 指向被插结点。函中首先判断链表是否为空,为空则使head指向被插结点。表若不空,则用while语句循环查找插入位置。找到之后再判断是否在第一结点之前插入,若是则使head 指向被插结点被插结点指针域指向原第一结点,否则在其它位置插入, 若插入的结点大于表中所有结点,则在表末插入。本函返回一个指针, 是链表的头指针。 当插入的位置在第一个结点之前时, 插入的新结点成为链表的第一个结点,因此head的值也有了改变, 故需要把这个指针返回主调函。 [例7.14]将以上建立链表,删除结点,插入结点的函组织在一起,再建一个输出全部结点的函,然后用main函调用它们。 #define NULL 0 #define TYPE struct stu #define LEN sizeof(struct stu) struct stu { int num; int age; struct stu *next; }; TYPE * creat(int n) { struct stu *head,*pf,*pb; int i; for(i=0;i<n;i++) { pb=(TYPE *)malloc(LEN); printf("input Number and Age\n"); scanf("%d%d",&pb->num,&pb->age); if(i==0) pf=head=pb; else pf->next=pb; pb->next=NULL; pf=pb; } return(head); } TYPE * delete(TYPE * head,int num) { TYPE *pf,*pb; if(head==NULL) { printf("\nempty list!\n"); goto end;} pb=head; while (pb->num!=num && pb->next!=NULL) {pf=pb;pb=pb->next;} if(pb->num==num) { if(pb==head) head=pb->next; else pf->next=pb->next; printf("The node is deleted\n"); } else free(pb); printf("The node not been found!\n"); end: return head; } TYPE * insert(TYPE * head,TYPE * pi) { TYPE *pb ,*pf; pb=head; if(head==NULL) { head=pi; pi->next=NULL; } else { while((pi->num>pb->num)&&(pb->next!=NULL)) { pf=pb; pb=pb->next; } if(pi->num<=pb->num) { if(head==pb) head=pi; else pf->next=pi; pi->next=pb; } else { pb->next=pi; pi->next=NULL; } } return head; } void print(TYPE * head) { printf("Number\t\tAge\n"); while(head!=NULL) { printf("%d\t\t%d\n",head->num,head->age); head=head->next; } } main() { TYPE * head,*pnum; int n,num; printf("input number of node: "); scanf("%d",&n); head=creat(n); print(head); printf("Input the deleted number: "); scanf("%d",&num); head=delete(head,num); print(head); printf("Input the inserted number and age: "); pnum=(TYPE *)malloc(LEN); scanf("%d%d",&pnum->num,&pnum->age); head=insert(head,pnum); print(head); }   本例中,print函用于输出链表中各个结点据域值。函的形参head的初值指向链表第一个结点。在while语句中,输出结点值后,head值被改变,指向下一结点。若保留头指针head, 则应另设一个指针变量,把head值赋予它,再用它来替代head。在main函中,n为建立结点的目, num为待删结点的据域值;head为指向链表的头指针,pnum为指向待插结点的指针。 main函中各行的意义是: 第六行输入所建链表的结点; 第七行调creat函建立链表并把头指针返回给head; 第八行调print函输出链表; 第十行输入待删结点的学号; 第十一行调delete函删除一个结点; 第十二行调print函输出链表; 第十四行调malloc函分配一个结点的内存空间, 并把其地址赋予pnum; 第十五行输入待插入结点的据域值; 第十六行调insert函插入pnum所指的结点; 第十七行再次调print函输出链表。   从运行结果看,首先建立起3个结点的链表,并输出其值;再删103号结点,只剩下105,108号结点;又输入106号结点据, 插入后链表中的结点为105,106,108。联合“联合”也是一种构造类型的据结构。 在一个“联合”内可以定义多种不同的据类型, 一个被说明为该“联合”类型的变量中,允许装入该“联合”所定义的任何一种据。 这在前面的各种据类型中都是办不到的。例如, 定义为整型的变量只能装入整型据,定义为实型的变量只能赋予实型据。   在实际问题中有很多这样的例子。 例如在学校的教师和学生中填写以下表格: 姓 名 年 龄 职 业 单位 “职业”一项可分为“教师”和“学生”两类。 对“单位”一项学生应填入班级编号,教师应填入某系某教研室。 班级可用整型量表示,教研室只能用字符类型。 要求把这两种类型不同的据都填入“单位”这个变量中, 就必须把“单位”定义为包含整型和字符型组这两种类型的“联合”。   “联合”与“结构”有一些相似之处。但两者有本质上的不同。在结构中各成员有各自的内存空间, 一个结构变量的总长度是各成员长度之和。而在“联合”中,各成员共享一段内存空间, 一个联合变量的长度等于各成员中最长的长度。应该说明的是, 这里所谓的共享不是指把多个成员同时装入一个联合变量内, 而是指该联合变量可被赋予任一成员值,但每次只能赋一种值, 赋入新值则冲去旧值。如前面介绍的“单位”变量, 如定义为一个可装入“班级”或“教研室”的联合后,就允许赋予整型值(班级)或字符串(教研室)。要么赋予整型值,要么赋予字符串,不能把两者同时赋予它。联合类型的定义和联合变量的说明一个联合类型必须经过定义之后, 才能把变量说明为该联合类型。 一、联合的定义 定义一个联合类型的一般形式为: union 联合名 { 成员表 }; 成员表中含有若干成员,成员的一般形式为: 类型说明符 成员名 成员名的命名应符合标识符的规定。 例如: union perdata { int class; char office[10]; };   定义了一个名为perdata的联合类型,它含有两个成员,一个为整型,成员名为class;另一个为字符组,组名为office。联合定义之后,即可进行联合变量说明,被说明为perdata类型的变量,可以存放整型量class或存放字符组office。 二、联合变量的说明   联合变量的说明和结构变量的说明方式相同, 也有三种形式。即先定义,再说明;定义同时说明和直接说明。以perdata类型为例,说明如下: union perdata { int class; char officae[10]; }; union perdata a,b; /*说明a,b为perdata类型*/ 或者可同时说明为: union perdata { int class; char office[10]; }a,b;或直接说明为: union { int class; char office[10]; }a,b 经说明后的a,b变量均为perdata类型。 它们的内存分配示意图如图7—8所示。a,b变量的长度应等于 perdata 的成员中最长的长度, 即等于 office组的长度,共10个字节。从图中可见,a,b变量如赋予整型值时,只使用了2个字节,而赋予字符组时,可用10个字节。 联合变量的赋值和使用   对联合变量的赋值,使用都只能是对变量的成员进行。 联合变量的成员表示为: 联合变量名.成员名 例如,a被说明为perdata类型的变量之后,可使用 a.class a.office 不允许只用联合变量名作赋值或其它操作。 也不允许对联合变量作初始化赋值,赋值只能在程序中进行。还要再强调说明的是,一个联合变量, 每次只能赋予一个成员值。换句话说,一个联合变量的值就是联合变员的某一个成员值。 [例7.15]设有一个教师与学生通用的表格,教师据有姓名,年龄,职业,教研室四项。学生有姓名,年龄,职业,班级四项。 编程输入人员据, 再以表格输出。 main() { struct { char name[10]; int age; char job; union { int class; char office[10]; } depa; }body[2]; int n,i; for(i=0;i<2;i++) { printf("input name,age,job and department\n"); scanf("%s %d %c",body[i].name,&body[i].age,&body[i].job); if(body[i].job=='s') scanf("%d",&body[i].depa.class); else scanf("%s",body[i].depa.office); } printf("name\tage job class/office\n"); for(i=0;i<2;i++) { if(body[i].job=='s') printf("%s\t%3d %3c %d\n",body[i].name,body[i].age ,body[i].job,body[i].depa.class); else printf("%s\t%3d %3c %s\n",body[i].name,body[i].age, body[i].job,body[i].depa.office); } }   本例程序用一个结构组body来存放人员据, 该结构共有四个成员。其中成员项depa是一个联合类型, 这个联合又由两个成员组成,一个为整型量class,一个为字符组office。在程序的第一个for语句中,输入人员的各项据,先输入结构的前三个成员name,age和job,然后判别job成员项,如为"s"则对联合depa?class输入(对学生赋班级编号)否则对depa?office输入(对教师赋教研组名)。   在用scanf语句输入时要注意,凡为组类型的成员,无论是结构成员还是联合成员,在该项前不能再加"&"运算符。如程序第18行中 body[i].name是一个组类型,第22行中的body[i].depa.office也是组类型,因此在这两项之间不能加"&"运算符。程序中的第二个for语句用于输出各成员项的值: 本章小结 1. 结构和联合是两种构造类型据,是用户定义新据类型的重要手段。结构和联合有很多的相似之处,它们都由成员组成。成员可以具有不同的据类型。成员的表示方法相同。都可用三种方式作变量说明。 2. 在结构中,各成员都占有自己的内存空间,它们是同时存在的。一个结构变量的总长度等于所有成员长度之和。在联合中,所有成员不能同时占用它的内存空间,它们不能同时存在。联合变量的长度等于最长的成员的长度。 3. “.”是成员运算符,可用它表示成员项,成员还可用“->”运算符来表示。 4. 结构变量可以作为函,函也可返回指向结构的指针变量。而联合变量不能作为函,函也不能返回指向联合的指针变量。但可以使用指向联合变量的指针,也可使用联合组。 5. 结构定义允许嵌套,结构中也可用联合作为成员,形成结构和联合的嵌套。 6. 链表是一种重要的据结构,它便于实现动态的存储分配。本章介绍是单向链表,还可组成双向链表,循环链表等。 资料收集:beck Copyright 2002 www.vcok.com, All Rights Reserved 学者

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

折腾的小飞

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

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

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

打赏作者

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

抵扣说明:

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

余额充值