函数
函数:具有特定功能的代码段。
函数的使用,可以省去很多重复代码的编写,大大简化程序,提高开发效率。
函数包括库函数和自定义函数(开发者自己写的函数)。
函数的定义,有以下四种:
1、无返回值无参型
//函数定义有四种形式 //函数是为了完成某项任务。 //任务材料:参数 //交任务:返回值
//第一种:无参数,无返回值。
void sayHi(){ printf("HI,约吗?"); } |
2、有返回值无参型
//第二种:无参数,有返回值。
int numberOne(){
//将结果返回 //函数执行到return就结束。 // return 10.10 ;////如果返回类型不匹配,不报错,但是结果不准了。(注意) return 1; //return后面的代码不会被执行 printf("我还没出场呢。。");
}
|
3、无返回值有参型
//第三种:有参数,无返回值。 // 参数可以任意多个, // 但是调用函数的时候,必须一一赋值。
void printSum(int num1,int num2){ printf("%d + %d = %d",num1,num2,num1 + num2);
}
|
4、有返回值有参型
//第四种:有参数,有返回值。 // num1,num2(int ) 返回sum //不知道num1,num2叫做形参 int sum(int num1 ,int num2){
return num1 + num2;
} |
求1~n的加和:
#import <Foundation/Foundation.h> //练习 //1、 //int sumValue(int n){ // int sum = 0; // for (int i = 0; i <= n ; i ++) { // sum = sum +i; // } // return sum; //} int main(int argc,constchar * argv[]){ // printf("%d",sumValue(9)); return 0; }
|
输入年月日,输出是在一年内的第几天:
switch方式:
//switch方式 /* int dayOfYear(int year,int month,int day){
int total = 0;
switch (month) { case 1: total = day; break; case 2: total = 31 + day; break; case 3: total = 31 + 28 + day; break; case 4: total = 31 + 28 + 31 + day; break; case 5: total = 31+ 28 + 31 + 30 + day; break; case 6: total = 31+ 28 + 31 + 30 + 31 + day; break; case 7: total = 31+ 28 + 31 + 30 + 31 + 30 + day; break; case 8: total = 31+ 28 + 31 + 30 + 31 + 30 + 31 + day; break; case 9: total = 31+ 28 + 31 + 30 + 31 + 30 + 31 + 31 + day; break;
case 10: total = 31+ 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + day; break; case 11: total = 31+ 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + day; break; case 12: total = 31+ 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + day; break; default: return 0; break; }
return total; }
|
数组方式:
*/ //数组方式 /* int dayOfYear(int month , int day){ int array[12] = {31,28,31,30,31,30,31,30,31,31,30,31}; int sum = 0; for (int i = 0; i < month - 1; i ++) { sum += array[i]; } sum += day; return sum; } */ int main(int argc,constchar * argv[]){ // printf("%d",dayOfYear(12,11)); return 0; } |
函数调用:
我们在定义一个函数后,需要在其他函数里调用我们定义好的这个函数。才能实现这个函数的功能。
如上面的一些代码,我们在定义了函数后,在main()函数里调用了我们定义好的函数。这样就能把我们定义的功能体现出来。
函数声明:
函数声明的出现,是因为我们有时候在main()函数后面定义我们的函数,但是在main()函数里调用我们定义的函数,这样的话,在编译的时候,系统会报错,说是这个函数没有定义。此时,我们应该在main()函数前对我们定义的函数进行声明。声明形式为:我们自定义的函数的返回类型函数名 参数:
void sum(int num);这个就是我们自定义的函数的函数声明。加上声明之后,main()函数调用自定义函数才不会报错。
//函数声明。 //若不声明,则下面会报错。 //void sayHi();
int main(int argc,constchar * argv[]){
//2015年04月02日14:31:27北京
//函数的调用 // sayHi(); //
return 0; } //函数的定义 //void sayHi(){ // printf("今天天气不错,约吗?"); //} //int sum (int num1, int num2){ // return num1 + num2; //} |
函数的声明,在Xcode里,这样隔开会比较好:新建一个Objective-C class的文件,命名好后,会生成一个.h和一个.m文件,我们将所有的函数声明放在.h的文件里,将函数的定义,放在.m文件里。
在main函数调用之前,需要将.h文件引用进main.m文件中,方式为:
//引入.h文件 #import "Hi.h"//自己定义的文件,用" "来引入。意思就是把Hi.h里的东西全部原封不动的复制到这个地方。 //.h文件不参与翻译。 //若干个.m文件在翻译时,是连成一块的。
#import "operator.h" |
系统的东西用< >来引入
#import <Foundation/Foundation.h>
一些例子:
定义4个函数,实现 + — * /四个运算。
operator.h文件
//函数声明
int sum (int num1 ,int num2); int sub (int num1 ,int num2); int total (int num1 ,int num2); int mod (int num1 ,int num2); |
operator.m文件
//函数定义 //函数名不能重复。 //函数名的命名规则和变量是一样的。
//+ int sum (int num1 ,int num2){ return num1 + num2; }
//- int sub (int num1 ,int num2){ if(num1 > num2){ return num1 - num2; }else{ return num2 - num1; } }
// *
int total (int num1 ,int num2){ return num1 * num2; }
int mod(int num1 ,int num2){ if(num2 != 0){ return num1 / num2; }else{ printf("除数不为0"); return -1; }
}
|
main.m文件
#import <Foundation/Foundation.h>//系统的东西用< >来引入
//引入.h文件 //自己定义的文件,用" "来引入。意思就是把Hi.h里的东西全部原封不动的复制到这个地方。 //.h文件不参与翻译。 //若干个.m文件在翻译时,是连成一块的。
#import "operator.h"
//函数声明。 //若不声明,则下面会报错。 //void sayHi();
//函数声明时,参数名可以去掉,只留参数类型。 //int sum (int , int num2);//
int main(int argc,constchar * argv[]){
//2015年04月02日14:31:27北京
//函数的调用 printf("加法:%d\n",sum(10,20)); printf("减法:%d\n",sub(10,20)); printf("乘法:%d\n",total(10,20)); printf("除法:%d\n",mod(10,20));
return 0; } |
编译过程:
在编译时,不对.h文件翻译,只对.m文件惊醒翻译。翻译时,将所有的.m文件连接成一块,然后进行翻译。
数组作为函数参数:
数组作为函数参数的时候,注意几点:
1、数组作为参数,不用给定一个数组长度(元素个数)。因为就算给定一个长度,在我们传进来的数组时,长度会根据我们传进来的数组的长度来确定实际长度。所以不用给定长度。
2、再在后面定义一个变量,用来装我们传过来的数组的长度。
形式如下:
voidprintArray(int arr[],int n){}
一些例子:
定义一个数组,用函数打印出来。用数组作为参数传递。
#import <Foundation/Foundation.h> //打印数组 //数组作为参数的时候,不用给元素个数。 //再定义一个变量n,用来给出要便利多少次。 //void printArray(int arr[],int n){ // for (int i = 0; i < n ; i++) { // printf("%d\t",arr[i]); // } //} int main(int argc,constchar * argv[]) {
//2015年04月02日15:55:41北京 /* // int array[5] = {5,4,3,2,1}; // // printArray(array, 5); return 0; } |
定义一个随机数组,用函数进行冒泡排序:
#import <Foundation/Foundation.h>
//函数冒泡排序 void sortArr(int arr[],int n){
for (int i = 0; i < n - 1 ; i ++) { for (int j = 0; j < n - (i+1); j++) { if (arr[j] > arr[j+1]) { arr[j] = arr[j] ^ arr[j+1]; arr[j+1] = arr[j] ^ arr[j+1]; arr[j] = arr[j] ^ arr[j+1];
} } } for (int i = 0; i < n ; i ++) { printf("%d\t",arr[i]); }
} int main(int argc,constchar * argv[]) {
//2015年04月02日15:55:41北京
int array[10] = {0}; for (int i = 0 ; i < 10 ; i ++) { array[i] = arc4random() % 100; } sortArr(array,10);
return 0; } |
函数的嵌套:
函数的嵌套,就是函数里调用函数。
函数允许函数嵌套调用,但是不允许函数嵌套定义。
一些例子:
简单嵌套调用:
#import <Foundation/Foundation.h> //声明: void sayHi();
void sayWhat(){ sayHi(); } void sayHi(){ printf("Hello,Kitty"); }
//函数不允许嵌套定义,但是可以嵌套调用。 //函数嵌套调用:函数里边调用函数
int main(int argc,constchar * argv[]){ sayWhat(); return 0; } |
比较几个数的大小:
#import <Foundation/Foundation.h> //函数不允许嵌套定义,但是可以嵌套调用。
//函数嵌套调用:函数里边调用函数
//求两个数最大值 int twoNumberMax (int num1 ,int num2){ return num1 > num2 ? num1 : num2; } //求三个数的最大值 int threeNUmberMax(int num1 ,int num2,int num3){
int temp =twoNumberMax(num1, num2); return temp > num3 ? temp : num3; } //比较4个数 int fourNumberMax(int num1 ,int num2,int num3,int num4){
int temp =threeNUmberMax(num1, num2, num3); return temp > num4 ? temp : num4; } |
递归:
递归就是函数自己调用自己。
递归慎用,因为如果自己不清楚声明情况下才能让递归停止的话,或者需求给定的样本太大,则不用。小样本,并且能控制条件让递归停止,则可以用,否则会沾满内存,使程序崩溃。
在能用非递归来解决,尽量用非递归的方式来解决。
#import <Foundation/Foundation.h> //递归:自己调自己..(慎用)样本小得时候可以用,大得话,再说把。 //void sayHi(){ // printf("Hello,六娃\n"); // sayHi(); //}
int mul(int n){ //非递归 // int num = 0; // for (int i = 1 ; i <= 5 ; i ++) { // num *=i; // } // return num;
//递归
//使用递归必须能够结束。 if (n == 1) { return 1; }else{ return n*mul(n -1 ); }
} int main(int argc,constchar * argv[]) {
// sayHi(); int num =mul(3); printf("%d",num); return 0; }
|
作用域:
作用域,就是说一个变量的生命周期。
注意一下几点:
1、局部变量:
就是变量在一对花括号内,出了这对花括号,则内存释放这个变量,这个变量的声明结束。括号内的变量在和括号外的变量同名时,按照强龙不压地头蛇的思路,就是以花括号内的变量来使用,出了花括号,就以外面的变量来使用。
2、全局变量:
全局变量就是在花括号外的变量,它的生命从开始创建到程序结束才会结束。全局变量不仅仅可以在一个.m文件里使用,也可以跨文件使用,但是要在使用全局变量的另一个.m文件里头加上这句话:
externint n1;//n1在本文件中没有,他就去外面的.m文件中去找。
例子:main.m文件
// // main.m // CLesson6_作用域 // // Created by lanou3g on 15/4/2. // Copyright (c) 2015年 xy2蓝翔. All rights reserved. //
#import <Foundation/Foundation.h> #import "test.h"
//全局变量作用域 //生命周期是整个程序。 //跨文件使用 int n1 = 10;
int main(int argc,constchar * argv[]) { //2015年04月02日17:15:12北京
//局部变量的作用域 //凡是出现在花括号{}里边的,都是局部变量。 //他们的作用域,就在这对花括号{}里边。 //在同一个作用域中,变量名不能重复。 //不同的作用域,变量名可以重复。
// int num1 = 10; // int num1 = 40; // { // //强龙不压地头蛇 // int num1 = 40; // int num2 = 20; // } say(); return 0; } |
test.m文件
//// test.m // CLesson6_作用域// // Created by lanou3g on 15/4/2. // Copyright (c) 2015年 xy2蓝翔. All rights reserved. externint n1;//n1在本文件中没有,他就去外面的.m文件中去找。
void say(){ printf("%d",n1); } |