870 likes | 1.07k Views
作弊是否很有诱惑性 ?. 上堂课已经讲了 作弊是有记录的 心理系很多同学集体作弊,让人震惊 下次再让抓到作弊,就不客气了 作业不一定在两个小时里都能完成 答疑没有一个人?. C 语言高级编程 (第一部分) 数组与算法 I. 北京大学 信息科学技术学院. 关于 宏. 宏名 (一般用大写, 以区别一般变量). 宏体 (可以是一个复杂的表达式). 形式: #define PI 3.14159. 作用与意义 1. 在源程序中,用简单的宏名 指代 复杂的宏体 2. 程序更加直观. 形式: #define PI 3.14159.
E N D
作弊是否很有诱惑性? • 上堂课已经讲了 • 作弊是有记录的 • 心理系很多同学集体作弊,让人震惊 • 下次再让抓到作弊,就不客气了 • 作业不一定在两个小时里都能完成 • 答疑没有一个人?
C语言高级编程(第一部分)数组与算法 I 北京大学信息科学技术学院
宏名 (一般用大写, 以区别一般变量) 宏体 (可以是一个复杂的表达式) 形式: #define PI 3.14159 作用与意义 1.在源程序中,用简单的宏名 指代 复杂的宏体 2.程序更加直观
形式: #define PI 3.14159 注意: 1.#define 可出现在程序的任一行 2.宏的作用范围:由 宏定义开始 到 程序末尾 之间的区域 3.宏定义不是C语句,不必在行尾加分号
#define PI 3.141593; #include <stdio.h> int main( ){ double S; S = PI - PI; printf(“%lf\n”, S); return 0; } S的值是多少?
按下build后… … 源文件 二进制代码 预编译 编译 连接 没有宏的源文件 可执行程序
把源程序中的所有PI 替换为3.141593; 预编译 没有宏的 源文件 源文件 #define PI 3.141593; int main( ){ double S; S = PI - PI; return 0; } int main( ){ double S; S = 3.141593; - 3.141593;; return 0; }
int main( ){ double S; S = 3.141593; - 3.141593;; return 0; } int main( ){ double S; S = 3.141593; - 3.141593; ; return 0; }
错误: 使用宏定义常量时,在结尾加; #define PI 3.14159; int main( ){ return 0; } #define PI 3.14159 int main( ){ return 0; } ✓ ✕
宏定义其他例子: //整数常量 #define MAX 200
#include <stdio.h> int main(){ int a, b; int e; scanf("%d", &a); scanf("%d", &b); …… …… …… printf("%d %d\n", a, b); return 0; } 程序填空,要求: 输出的两个数值按照 从小到大的顺序排列
#include <stdio.h> int main(){ int a, b; int e; scanf("%d", &a); scanf("%d", &b); if(a > b){ e = a; a = b; b = e; } printf("%d %d\n", a, b); return 0; }
#include <stdio.h> int main(){ int a, b, c; int e; scanf("%d", &a); scanf("%d", &b); scanf("%d", &c); …… …… …… printf("%d %d\n", a, b, c); return 0; } 程序填空,要求: 输出的3个数值按照 从小到大的顺序排列
#include <stdio.h> int main(){ int a, b, c; int e; scanf("%d", &a); scanf("%d", &b); scanf("%d", &c); if(a > b){ e = a; a = b; b = e; } if(b > c){ e = b; b = c; c = e; } if(a > b){ e = a; a = b; b = e; } printf("%d %d %d\n", a, b, c); return 0; }
如果要求: 1. 接收用户输入的10个数值 2. 输出的10个数值按照 从小到大的顺序排列 难道需要这样定义10个变量吗? int a, b, c, d, e, f, g, h, i, j; 如果要输入更多的数值呢?! 有没有一种更简便的方式, 可以一次定义一组变量?
数组是什么? 数组是一组变量 数组是一组 类型相同 的变量 数组是 一组具有编号的、类型相同 的变量
如何声明一个数组 必须是一个常量 int sz[10]; 数组的类型 数组名 数组中变量的数目
数组中变量的编号 int sz[10]; 0 1 2 3 4 5 6 7 8 9 数组中变量的编号 从0开始; 到数组的长度-1结束
如何访问数组中的变量 变量编号 int sz[10]; sz[0]= 1; sz[1] = 3; sz[2] = 7; … sz[8] = 16; sz[9] = 12; …sz[2]…; 数组名
数组变量赋值的一种特殊方式 • 声明时赋值 int sz[5] ={12, 3, 7, 28, -2};
访问数组中变量的一种常见方式 int sz[10]; int i; … i=…; sz[i] = … … i 的值可以根据需要变化
#include <stdio.h> int main(){ int sz[10]; int i; for(;; ){ ; } for(i = 0; i < 10; i++){ printf("%d ", sz[i]); } return 0; } 程序填空,要求: 1.接收用户输入的10个数字 2.存放在数组sz中
#include <stdio.h> int main(){ int sz[10]; int i; for( i=0 ; i < 10 ; i++){ scanf("%d", &(sz[i])); } for(i = 0; i < 10; i++){ printf("%d ", sz[i]); } return 0; }
数组的遍历 通过循环结构
正向遍历 #define LEN 10 int sz[LEN]; for(int i = 0; i < LEN; i++){ … sz[i] … }
反向遍历 #define LEN 10 int sz[LEN]; for(int i = LEN-1; i>= 0; i--){ … sz[i] … }
通过遍历实现对数组变量的控制台赋值 #define LEN 10 int sz[LEN]; for(int i = 0; i < LEN; i++){ scanf(“%d”, &(sz[i])); }
通过遍历实现对数组变量的控制台输出 #define LEN 10 int sz[LEN]; for(int i = 0; i < LEN; i++){ printf(“%d\n”, sz[i]); }
数组的应用示例 当程序要处理 一组类型相同、含义类似的数据时, 应该使用数组
游戏:过年抽奖 • 一个村庄,有128个村民 • 村长对村民说: • 今年村里出现了财政盈余M元; • M是2000-3000之间的一个整数 • 准备通过抽奖的方式把钱发给村民 • 游戏规则如下: • 每个村民上报一个在2000-3000元之间的整数 • 如果有人上报的数字和M相等,就把钱发给这些人 • 如果只有一个村民猜对,就把M元钱全部发给他 • 如果有多个人村民猜对,就把M元钱平均分配给这些村民 • 如果没有人猜对,财政盈余转为下年度开支 村长邀请我们编写一个程序, 实现村里财政盈余的自动分配
编程的基本思路 • 定义一个数组存放所有村民上报的数据 • 定义一个数组存放获奖者的编号(幸运者数组) • 定义一个整数存放获奖者人数 • 对村民从0开始编号(最后一个编号是127) • 村民按照编号顺序上报数字;程序将村民上报的数字存放在对应编号的数组变量中。 • 遍历村民上报的数字,若上报数字与幸运数相等,则 • 将村民编号 按顺序 添加到幸运者数组中; • 并将获奖者人数加1 • 最后,打印出获奖者编号和获得的奖金数额
#define LUCKY_M 2345//财政盈余 #define POPULATION 128 //村民数量 int main( ){ int people[POPULATION]; //记录所有村民上报数字的数组 int luckyPeople[POPULATION];//幸运者数组,记录获奖者编号,为什么和村民一样多? int i, nLucky=0; //循环变量,获奖者人数 for (i=0; i<POPULATION; i++) { scanf(“%d”, &(people[i])); //读入村民报的数字,数组下标就是村民的编号 } for (i=0; i<POPULATION; i++) { if ( people[i] == LUCKY_M ) { luckyPeople[nLucky] = i; nLucky ++; } } if (nLucky > 0){ for (i=0; i<nLucky; i++){ //输出获奖者编号及所获奖金数额 printf("%d %d\n", luckyPeople[i], LUCKY_M / nLucky); } return 0; } return -1; }
利用数组,对一组数据进行排序 显然,不能采用简单的比较。 需要有更有效的方法。 冒泡排序法 选择排序法
如何把大象关在冰箱里? 排序的基本方法 • 分3步: • 第一步:打开冰箱门; • 第二步:把大象推进冰箱; • 第三步:关上冰箱门;
int sz[LEN]; //#define LEN8 排序的基本方法 7 11 18 6 12 17 • 分8个步骤进行 • 第1步:把第1大的数放在变量sz[7]中; • 第2步:把第2大的数放在变量sz[6]中; • 第3步:把第3大的数放在变量sz[5]中; • 第4步:把第4大的数放在变量sz[4]中; • 第5步:把第5大的数放在变量sz[3]中; • 第6步:把第6大的数放在变量sz[2]中; • 第7步:把第7大的数放在变量sz[1]中; • 第8步:把第8大的数放在变量sz[0]中; 5 13 16 4 17 15 3 18 14 2 14 13 1 15 12 0 16 11 编号 排序前 的值 排序后 的值
排序的基本方法 int sz[LEN]; //#define LEN8 • 分8个步骤进行 • 第1步:把第1大的数放在变量sz[7]中; • 第2步:把第2大的数放在变量sz[6]中; • 第3步:把第3大的数放在变量sz[5]中; • 第4步:把第4大的数放在变量sz[4]中; • 第5步:把第5大的数放在变量sz[3]中; • 第6步:把第6大的数放在变量sz[2]中; • 第7步:把第7大的数放在变量sz[1]中; • 第8步:把第8大的数放在变量sz[0]中; • LEN个数,分LEN个步骤进行 • 第1步:把第1大的数放在变量sz[LEN-1]中; • 第2步:把第2大的数放在变量sz[LEN-2]中; • 第3步:把第3大的数放在变量sz[LEN-3]中; • 第4步:把第4大的数放在变量sz[LEN-4]中; • 第5步:把第5大的数放在变量sz[LEN-5]中; • 第6步:把第6大的数放在变量sz[LEN-6]中; • … • 第LEN步:把第LEN大的数放在变量sz[LEN-LEN]中; 抽象
排序的基本方法 • LEN个数,分LEN个步骤进行 • 第1步:把第1大的数放在变量sz[LEN-1]中; • 第2步:把第2大的数放在变量sz[LEN-2]中; • 第3步:把第3大的数放在变量sz[LEN-3]中; • 第4步:把第4大的数放在变量sz[LEN-4]中; • 第5步:把第5大的数放在变量sz[LEN-5]中; • 第6步:把第6大的数放在变量sz[LEN-6]中; • … • 第LEN步:把第LEN大的数放在变量sz[LEN-LEN]中;
排序的基本方法 对数组intsz[LEN]进行排序, 可以分为LEN 个步骤进行。 第k步:把第k 大的数放在变量 sz[LEN-k] 中; (K=1, 2, 3, 4, …, LEN-1, LEN)
用冒泡法作第1步: 把第1大的数放在变量sz[LEN-1]中; int e; for(int i = 0; i < LEN - 1; i++){ if(sz[i] >sz[i+1]){ e = sz[i+1]; sz[i+1] = sz[i]; sz[i] = e; } }