IOS开发OC基础知识(七) 函数

55 阅读13分钟

函数

/*
     不使用函数的弊端:
     1.重复代码太多, 又臭又长
     2.当需求变更, 很多地方都需要修改代码
     */
    /*
     使用函数的好处:
     1.提高了代码的复用性, 代码更简洁
     2.当需求变更, 不用修改很多地方
     */
    
    left();
    printf("------\n");
    /*
     printf("看反光镜\n");
     printf("向左打方向盘\n");
     printf("加油门\n");
     printf("回正方向盘\n");
     printf("通知后方的飞机\n");
     */
    /*
     printf("看反光镜\n");
     printf("向右打方向盘\n");
     printf("加油门\n");
     printf("回正方向盘\n");
     */
    right();
    printf("------\n");
    /*
     printf("看反光镜\n");
     printf("向左打方向盘\n");
     printf("加油门\n");
     printf("回正方向盘\n");
     printf("通知后方的飞机\n");
     */
    left();

函数的定义

/*
 函数的定义格式:
 返回值类型 函数名称(形参列表)
 {
 函数体; // 语句; ...
 }
 */
/*
 初学者如何定义函数:
 应该有4个确定:
 1.确定函数名称(给函数起一个有意义的名称, 让调用者一看到名称就知道这个函数是干什么的)
 1.1函数是标示符的一种 , 遵守规则 : 26个字母 , 数字 , _组成, 遵守规范: 驼峰命名
 2.确定形参列表
 2.1形参列表的格式 (数据类型 变量名称, ...)
 2.2如何确定形参列表? 就看看以后调用函数时, 是否需要传递一些辅助的数据给函数
 3.确定返回值
 4.确定返回值类型
 4.1return的是什么类型, 那么返回值类型就写什么类型
 */
 
int getMax(int v1, int v2)
{
    int max = v1 > v2 ? v1 : v2;
    /*
     return有两个作用:
     1.返回数据给函数调用者
     2.结束函数
     */
    return max;
}
int main(int argc, const char * argv[]) {
    
    // 需求: 要求获取两个数的最大值
    int a = 10;
    int b = 20;
    //    int max = a > b ? a : b;

    int result = getMax(a , b);
    printf("result = %i\n", result);
    
    int m = 998;
    int n = 668;
    result = getMax(m, n);
    //    int max2 = m > n ? m : n;
    printf("result = %i\n", result);
    
    return 0;
}

函数的调用过程

/*
 4个确定:
 1.确定函数名称
 2.确定形参列表
 3.确定返回值
 4.确定返回值类型
 */
// 注意: 形参列表中的变量只有当函数被调用时才会分配存储空间
// 形参列表中的每一个变量我们称之为, 形式参数, 简称形参
int average(int v1, int v2)
{
    int average = (v1 + v2) / 2;
    return average;
}
int main(int argc, const char * argv[]) {
    // 需求: 求两个数的平均值
    int a = 10;
    int b = 20;
    // 调用函数时传入的参数, 我们称之为实际参数, 简称实参
    int result = average(a, b);
    printf("result = %i\n", result);
    return 0;
}

函数的注意点

// 1.如果"基本数据类型"(char int double float)作为函数的参数, 在函数中修改形参的值, 不会影响到外面实参的值
    // 2.实参的个数, 必须和形参的个数相同
    /*
    int getMin(int v1, int v2)
    {
        // 注意: 在函数中修改形参的值, 不会影响到外面实参的值(当然也有一定的前提)
        v1 = 50;
        int min = v1 < v2 ? v1 : v2;
        return min;
    }
     */
  

    // 3.返回值可以和返回值类型不一样,但是如果返回值和返回值类型不一样的时候 \
    系统会对返回值进行自动类型转换(隐式类型转换), 将返回值转换为返回值类型
    // 注意: 在企业级开发中千万不要这样写
    // 4.函数可以有形参也可以没有形参
    int getHeight()
    {
        return 1.75;
    }
    // 5.函数可以有返回值, 也可以没有返回值
    // 如果函数没有返回值, 那么返回值类型就写viod
    // 如果函数没饭返回值, 那么可以不写return, 但是如果写了return也不会报错
    void printRose()
    {
        printf(" {@}\n");
        printf("  |\n");
        printf(" \\|/\n");// 在C语言中\有特殊的函数, 它是一个转义字符
        printf("  |\n");
        return;
    }
    // return的应用场景
    // 1.用于在函数中返回结果给函数调用者
    // 2.结束函数
    // 3.提前结束函数
    // 4.return后面不可以写任何语句, 因为执行不到
    // break;
    // continue;
     /*

    login(账号, 密码)
    {
        // 1.用户只输入的了账号
        // 2.用户只输入了密码
        // 如果用户只输入了账号或者密码, 就没有必要发送请求
        if (账号 == NULL) {
            return;
        }
        
        if (密码 == NULL) {
            return;
        }
        
        // 发送网络请求到服务器, 将用户的账号和密码上传
        // get请求: http://www.momo.com/?username="lnj"&password="lmj";
    }
     */
  
    // 7.函数名称不能相同
    // 7.1形参列表不同也不可以
    // 7.2返回值类型不同也不可以
    //void test()
    //{
    //    
    //}
  
    //void test()
    //{
    //    
    //}
 

    //void test(int a)
    //{
    //    
    //}

    //int test()
    //{
    //    
    //}

  // 8.函数不能嵌套定义
    //void test()
    //{
    //    void demo()
    //    {
    //        
    //    }
    //}
    
    // 9.C语言是弱语言
    //  9.1函数可以没有返回值类型
    // 如果函数没有写返回值类型, 那么默认就是int类型
    /*
    test()
    {
        return 1.75;
    }
     */

    int main(int argc, const char * argv[]) {
        /*
        // 需求: 获取两个数的最小值
        int a = 10;
        int b = 20;
        int c = 5;
        int result =  getMin(a, b);
        printf("result %i\n", result);
        printf("a = %i, b = %i", a, b);
         */

        /*
        double height = getHeight();
        printf("height = %f\n", height);
         */
        // 需求: 打印一朵玫瑰花
    //    printRose();
        double result = test();
        printf("result = %f\n", result);
        return 0;
    }

函数练习

/*
 【理解】写一个函数打印一朵玫瑰花
 【理解】写一个函数打印N朵玫瑰花
 【理解】写一个函数从键盘输入三个整型数字,找出其最大值
 【理解】写一个函数求三个数的平均值
 */
void printRose()
{
    printf(" {@}\n");
    printf("  |\n");
    printf(" \\|/\n");// 在C语言中\有特殊的函数, 它是一个转义字符
    printf("  |\n");
}
 
void printRoses(int value)
{
    for (int i = 0; i < value; i++) {
        /*
        printf(" {@}\n");
        printf("  |\n");
        printf(" \\|/\n");// 在C语言中\有特殊的函数, 它是一个转义字符
        printf("  |\n");
         */
        printRose();
    }
}
  
int getMax(int v1, int v2, int v3)
{
    int temp = v1 > v2 ? v1 : v2;
    int max = temp > v3 ? temp : v3;
    return max;
}
 
int average(int v1, int v2, int v3)
{
    int average = (v1 + v2 + v3) / 3;
    return average;
}
int main(int argc, const char * argv[]) {

    /*
//    printRose();
    int number = 5;
    printRoses(number);
     */
    /*
    printf("请输入三个整数, 用逗号隔开, 以回车结束\n");
    int num1, num2, num3;
    scanf("%i,%i,%i", &num1, &num2, &num3);
    int result = getMax(num1, num2, num3);
    printf("result = %i\n", result);
     */
    printf("请输入三个整数, 用逗号隔开, 以回车结束\n");
    int num1, num2, num3;
    scanf("%i,%i,%i", &num1, &num2, &num3);
    int result = average(num1, num2, num3);
    printf("result = %i\n", result);
    return 0;
}

函数的声明和定义

// 以前我们在定义函数的时候, 一直都是把函数定义在main函数的前面
// C语言规定: 一般情况下, 如果想要调用一个函数, 该函数必须在调用之前出现
/*
void printRose()
{
    printf(" {@}\n");
    printf("  |\n");
    printf(" \\|/\n");// 在C语言中\有特殊的函数, 它是一个转义字符
    printf("  |\n");
}
 */
// 函数的声明
// 函数的声明的作用: 在调用函数之前, 告诉系统有这个函数 \
并且告诉系统, 该函数叫什么名字, 接收什么参数, 返回什么类型的值
void printRose();
//int sum(int v1, int v2);
// 声明的其它写法
//int sum(int, int);
int sum(int, int);
int sum(int, int);
int sum(int, int);
int sum(int, int);
int sum(int, int);
int sum(int, int);
int sum(int, int);
int main(int argc, const char * argv[]) {
    printRose();
    
//    函数的声明, 只需要在函数被使用之前告知系统就可以了, 它可以写在函数的外面也可以写在函数的里面
    int sum(int, int);
    int result = sum(10, 20);
    printf("result = %i\n", result);
    return 0;
}
// 完整的实现了函数的功能的代码, 称之为函数的定义(函数的实现)
void printRose()
{
    printf(" {@}\n");
    printf("  |\n");
    printf(" \\|/\n");// 在C语言中\有特殊的函数, 它是一个转义字符
    printf("  |\n");
}
// 注意: 如果函数的返回值是int类型, 那么不用写声明, 函数也不会报错  
int sum(int v1, int v2)
{
    return v1 + v2;
}
  
/*
 C语言中是不允许重复定义(实现)同名称的函数
int sum(int v1, int v2)
{
    return v1 + v2;
}
*/

main函数分析

// main是函数的名称, 是系统规定的名称, 系统启动程序就会调用名称叫做main的函数
// main函数只能由系统调用 ,不能手动调用
 
// 其实系统在启动程序的时候, 会给我们的程序传递一些参数
//  argc : 就是系统传递进来的参数个数, 默认是1
//  argv : 就是系统传递进来的参数实际的值, 默认是程序的名称
int main(int argc, const char * argv[]) {
    
    printf("argc = %i\n", argc);
    printf("argv = %s\n", argv[0]);
    printf("argv = %s\n", argv[1]);
   
    // return 结束函数
    // 0 : 返回给操作系统, 如果返回0, 代表程序整除结束, 如果返回其它值代表程序非正常结束
    return 0;
}

递归函数

void scanfNumber();
void test();  
int main(int argc, const char * argv[]) {
    
    // 需求: 要求用户输入一个大于0的数, 如果用户输入的数不大于0\
    那么就一直重复的提醒输入重新输入, 直到用户输入的值大于0为止
    /*
    int number = -1;
    while (number < 0) {
        printf("请输入一个大于0的整数, 以回车结束\n");
        scanf("%i", &number);
    }
    printf("number = %i\n", number);
    */
    
    // 一般情况下, 能用循环做得事情, 用递归函数都能做
    // 但是要注意: 不是什么时候都使用递归, 递归要慎用(性能问题)
    // 什么是递归函数: 函数自己搞自己
//    scanfNumber();
    
    // 注意: 递归一定要由一个明确的结束条件, 否则会造成死循环(无限循环)
    test();
    return 0;
}
  
void test()
{
    printf("test\n");
    test();
}

void scanfNumber()
{
    // 1.接收用户输入的值
    int number = -1;
    printf("请输入一个大于0的整数, 以回车结束\n");
    scanf("%i", &number);

    // 2.判断用户输入的值是否合法
    if (number < 0) {
        // 不合法, 需要重新输入
        // 函数可以自己调用自己
        scanfNumber();
    }else
    {
        printf("number = %i\n", number);
    }
}

递归函数练习

#include <stdio.h>
int myPow(int base, int n);
int myPow2(int base, int n);
int main(int argc, const char * argv[]) {
    /*
     设计一个函数用来计算B的n次方
     b = 2
     n = 3
     
     int result = b(3);
     b(0) = 1; // 计算0次方
     b(1) = b(0) * b; // 0次方 * 当前的这个数 == 1次方
     b(2) = b(1) * b; // 1次方 * 当前的这个数 ==  2次方
     b(3) = b(2) * b; // 2次方 * 当前的这个数 == 3次方
     b(n) = b(n - 1) * b;
     
     2(3)
     2 * 2 * 2;
     result = 1 * 2; // 计算1次方
     result = 2(result) * 2; // 1次方 * 当前的这个数 = 2次方
     result = 2 * 2(result) * 2; // 2次方 * 当前的这个数 = 3次方
     用上一次的结果 * 2
     */
    int a = 2;
    int b = 3;
//    int resutl = myPow(a, b);
    int resutl = myPow2(a, b);
    printf("result = %i\n", resutl);
    return 0;
}
/*
 1.必须有一个明确的结束标志
 2.自己调用自己
 */
int myPow2(int base, int n)
{
    int result = 1;
    if (n <= 0) {
        // 结束条件
        return result;
    }else
    {
        return myPow2(base, n - 1) * base;
    }
}
int myPow(int base, int n)
{
    // 1.定义变量保存计算的结果
    int result = 1; //
    for (int i = 0; i < n; i++) {
        printf("%i * %i\n", result, base);
        result = result * base;
    }
    return result;
}

递归练习2

#include <stdio.h>

int main(int argc, const char * argv[]) {
    // 用递归法求N的阶乘
    /*
     4! = 4 * 3 * 2 * 1
     4! == 4 * 3!               3! == 3 * 2 * 1
     4! == 4 * 3 * 2!           2! == 2 * 1
     4! == 4 * 3 * 2 * 1!       1! = 1

     4! == 4 * 3 * 2 *1
     4! == 4 * 3!
     3! == 3 * 2!
     2! == 2 * 1!
     1! == 1
     
     n!= n * (n - 1)!;
     */
    int a = 3;
    int result = factorial(a);
    printf("result = %i\n", result);
    return 0;
}
int factorial(int n)// 3  2  1
{
    // 结束条件
    if (n == 1) {
        return 1;
    }else
    {
//      return 3 * factorial(3 - 1); == return 3 * 2
//      return 2 * factorial(2 - 1); == return 2 * 1;
        return n * factorial(n - 1);
    }
}

递归练习3

#include <stdio.h> // 告诉编译器printf函数的格式, 声明printf函数
  
int main(int argc, const char * argv[]) {
    /*
     有5个人坐在一起,问第5个人多少岁?他说比第4个人大两岁。问 第4个人岁数,他说比第3个人大两岁。问第3个人,又说比第2个 人大两岁。问第2个人,说比第1个人大两岁。最后问第1个人, 他说是10岁。请问第5个人多大?

     第一个人得岁数 == 10
     第二个人得岁数 == 第一个人 + 2  // 12
     第三个人得岁数 == 第二个人 + 2  // 14
     第四个人得岁数 == 第三个人 + 2  // 16
     第五个人得岁数 == 第四个人 + 2  // 18
    
     一致第一个人得年龄, 和每个人之间的年龄差, 求第n个人的年龄
     age(1) == 10
     age(2) == age(1) + 2;
     age(3) == age(2) + 2;
     age(4) == age(3) + 2;
     age(5) == age(4) + 2;
     age(n) = age(n - 1) + 2;
     */
    int result = age(3);
    printf("result = %i\n", result);
    return 0;
}
int age(int n) // 3  2  1
{
   // 定义结束条件
    if (n == 1) {
        return 10;
    }else
    {
//      return 14;
//      return 12;
        return age(n - 1) + 2;
    }
}

include基本概念

#include <stdio.h> // 告诉系统printf函数是存在的, 告诉系统printf函数的格式(声明printf函数)
// include的作用, 是将include右边的文件拷贝到当前文件中
int main(int argc, const char * argv[]) {
    //     include指令不一定要写在文件的头部
//#include "abc/lnj.txt"
#include "/Users/xiaomage/Desktop/课堂共享/day05/code/day05/include基本概念/abc/lnj.txt"
    return 0;
}
/*
 include后面的 <> 和 "" 的区别
 >如果使用<>代表会先从开发工具的编译环境中去查找
    + /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/usr/include/
 >如果编译环境中没有找到, 那么会再去系统的编译环境中找
    + /usr/include/stdio.h
 >如果使用""代表会先从当前文件所在的文件夹下面查找
 >如果在当前文件所在的文件夹下面没有找到, 那么就回去开发工具的编译环境中去查找
 >如果编译环境中没有找到, 那么会再去系统的编译环境中找
 注意: include后面不一定要写文件名称 也可以写路径(相对路径/ 全路径)
 */

多文件开发

//  main.c
//  多文件开发

#include <stdio.h>
#include "lisi.h"

//int sum(int v1, int v2);
//int average(int v1, int v2);
//int test(int v1, int v2);

/*
 弊端:
 1.李四改了张三也要改
 2.张三每次还要去李四的文件中一个一个的找
 为了解决这个问题, 可以引用.h文件来解决 , 引入头文件来解决
*/
int main(int argc, const char * argv[]) {
   /*
    国家电力系统
    计算两个用户的电费
    张三 : 菜鸟
    李四 : 大神
    */

    /*
    int result =  sum(10, 20);
    printf("result = %i\n", result);
     */

    /*
    int result = sum(10, 20);
    printf("result = %i\n", result);
    result = average(10, 20);
    printf("result = %i\n", result);
    printf("%i\n", test(10, 20));
     */
    printf("%i\n", sum(10, 20));
    printf("%i\n", average(10, 20));
    printf("%i\n", test(10, 20));
    printf("%i\n", new1(998));

    return 0;
}

/*
int sum(int v1, int v2)
{
   int value = v1 + v2;
   return value;
}

 */
//  lisi.h
// 注意: .h是专门用来被拷贝的, 不会参与编译
#define day05_lisi_h
// 计算两个用户和
int sum(int v1, int v2);
// 计算两个用户的平均值
int average(int v1, int v2);
// 计算两个用户一年的费用
int test(int v1, int v2);
// 获取电量
int new1(int v1);
#endif
//
//  lisi.c
#include <stdio.h>
 

int sum(int v1, int v2)
{
    return (v1  + v2) * 10;
}
 
int average(int v1, int v2)
{
    return (v1 + v2) / 2;
}
  
int test(int v1, int v2)
{
    return v1 * v1 + v2 * v2 + v1 + v2 * v1;
} 

int new1(int v1)
{
    return v1;
}