290 likes | 466 Views
第三讲:程序设计基础. 深入数组与函数. x. y. 程序 和 程序的执行. 妈妈给小明留了一张纸条:“去真诚超市买一束花,送给张阿姨” --- 程序 小明执行妈妈的命令 --- 程序的执行. 7. 8. nums. nums[0]. nums[1]. nums[4]. 再说数组. int nums[ 5 ] = { 1, 2, 3, 4, 5 };. 1. 2. 3. 4. 5. nums: 指向该数组所占内存单元的首地址的指针, 常变量,赋初值后不能再改变. nums[ 0 ]: 代表该数组的第一个盒子,
E N D
第三讲:程序设计基础 深入数组与函数
x y 程序和程序的执行 • 妈妈给小明留了一张纸条:“去真诚超市买一束花,送给张阿姨” --- 程序 • 小明执行妈妈的命令 --- 程序的执行 7 8
nums nums[0] nums[1] nums[4] 再说数组 • int nums[ 5 ] = { 1, 2, 3, 4, 5 }; 1 2 3 4 5 • nums: 指向该数组所占内存单元的首地址的指针,常变量,赋初值后不能再改变 • nums[ 0 ]: 代表该数组的第一个盒子, • 可以出现在赋值语句的左边和右边 • nums == &nums[ 0 ] ? • &nums == &nums[ 0 ]?
常变量,C++特有 • 显式定义常变量(constant variable) 在通常的变量定义之前加上const,如: constint LOOP_TIMES = 10; • 在定义常变量的同时必须初始化。 • const int a; → const int a = 5; • 变量的值在初始化后,就不能再改变 • const int a = 5; a = a + 1; • C++程序员喜欢用常变量来代替符号常量。 (重要!二者的区别请参见课本P30--31) • 符号常量,没有类型,在预编译时被替换 • 常变量,具有类型,在内存中存在着以它命名的内存空间
nums nums[0] nums[1] nums[4] 数组名:隐式定义的常指针变量 • int nums[ 5 ] = { 1, 2, 3, 4, 5 }; 1 2 3 4 5 • nums: 指向该数组所占内存单元的首地址的常量指针int* const nums; • nums == &nums[ 0 ] true • &nums == &nums[ 0 ]? false
arr e e l l l l . . \0 \0 H H o o 字符数组及字符串常量
boss worker1 worker2 worker3 worker4 worker5 诸葛亮的悲剧 • 懿问曰:“孔明寝食及事之繁简若何?”使者曰:“丞相夙兴夜寐,罚二十以上皆亲览焉。所啖之食,日不过数升。”懿顾谓诸将曰:“孔明食少事烦,其能久乎?” • 事无巨细,事必躬亲 • 工作必须分工,人员各司其职
函数原型: 函数定义: 把函数看做加工设备 • 返回值类型 函数名(类型 参数1,类型 参数2,…) { 函数体 } • 参数列表:进料口,接受特定类型的“原材料”; 加工后的产品(返回值)通过“出料口”送出,与出料口的类型必须匹配
将result的内容 取出,送至出料口 将盒子a和b的内容 取出,送至进料口 函数的调用和参数传递
arr[0] arr[1] arr 数组参数传递 nums[1] nums[0] nums
使用函数模块化程序 • 分而治之(divide and conquer) • 由小的、简单的部件构建程序,使得程序的开发更易于控制 • 一个只执行单个任务的小函数的测试和调试要比大函数容易 • 软件重用(software reuse) • 编写一次,能够在程序的多个地方重用 • 每个函数应该限定于单一的、良好定义的任务 • 函数名应该有效地表达任务 • 如果不能为函数起一个能表达其任务的简洁的名字, 那么该函数可能试图执行太多的不同任务。通常,最好把这样的函数拆分成多个小函数
函数重用的例子 • 求n个整数的平均值 • int average( int nums[], int n ) • 即可用来求学生成绩的平均值, 也可求某个月的平均气温
函数的定义和调用 • 函数的原型(Prototype) • int square(int ); • int average(int[], int); • 函数的定义(Definition) • Head int average(int nums[ ], int n) • Body { } • 函数的调用 • 如果函数在调用前就已定义,单独的函数原型没有必要 • 如果函数在定义的前面被调用,并且没有相应的函数原型,会出现编译错误
函数的重载(Overloading) • 函数的签名(Function Signature) • 函数原型中的函数名和参数类型部分 • 函数的返回值类型不属于函数签名 • 函数的重载 (重要:课本p99--101) • 函数对应某种功能。为了实现细节不同的同一类功能, • int square1( int x ); double square2( double x ); • C++允许函数同名,称为函数的重载(Overloading)。 但是要求:要么参数个数不一样, 要么至少有一个位置的参数类型不同。
函数的重载 下面那些函数定义是可以添加的?
引用和引用参数 • 参数传递方式 • 按值传递 (pass-by-value) • 调用函数时,根据形参类型获得一块内存,存放实参值的副本 • 传递大的数据项时,如结构体,生成副本需要花费大量的时间和内存空间。 • 按引用传递 (pass-by-reference) • 将形参定义为指针类型。本质上还是一种按值传递。 调用函数时,将一个地址(实参的值)放入指针类型的盒子。 这个地址要么从指针类型的实参变量中取出,要么通过&运算符从实参变量获得。 • 将形参定义为对某个类型的变量的引用,称为引用参数 int &count count是对一个int类型变量的引用
引用参数的例子 源代码
x y 函数内的引用 • 引用还可以在函数中用做其他变量的别名
*p x 0x123456EC 0x12345678 y 7 0x123456EC p 引用和指针的不同 • 指针是一种数据类型,指针类型的变量有独立的内存 • 引用只是变量的一个别名,并不是定义了一种特殊类型的变量,所以并不对应单独的内存 int x = 7; int* p; p = &x; int &y = x;
小结 • 数组 • 数组名是一个隐式定义的常指针变量 • 常变量 • 函数参数传递 • 传递数组,将数组名作为实参传递给形参 • 传递指针,往“进料口”放入“地址值” • 传递引用参数,往“进料口”传递一个变量的别名,此别名仅供本函数使用 • 函数的重载 • 函数的名字相同,但参数列表不同。
?? 函数的重载 下面那些函数定义是可以添加的?
小测验 • 请编写一个函数,返回指定的整数的各位数的和。