Day09

作者: 喝酸奶要舔盖__ | 来源:发表于2018-09-07 12:44 被阅读0次

    变量作用域

    C语言变量作用域
    
    1. 如果是局部变量和全局变量同名,那么在访问变量时候,采用就近原则
       会现在局部变量中寻找,找不到再去全局变量中找
    2. 在函数中不能访问其他函数中定义的局部变量
    3. 在函数中可以访问全局变量
    4. 多个函数可以共享一个全局变量
    

    字符串

    • 基本概念
    /*
         * 1. 字符串是什么?
         * 将字符串在一起就是字符串,在C语言中字符串就是一个特殊的数组而已
         *
         * 2. 特殊点:
         *   如果想要用数组来表示字符串,那么数组必须是char类型的,而且最后一个元素
         * 必须是\0
         *
         * 3. 由于字符串比较特殊
         *   所以在C语言中除了可以用字符数组来表示字符串,还可以用""来表示字符串
         *
         */
    
        char str1[] = {'w', 'j', 'n', '\0'}; //字符串以'\0'结尾
        char str2[] = {'w', 'j', 'n'}; //不是字符串,是字符数组
        //赋值的同时部分初始化,没有初始化的元素会自动赋值为0
        char str3[10] = {'w', 'j', 'n', '\0'};
        chr str4 = "wjh";
        printf("%s\n", str);
    
    • 字符串内存分析
        //两者在内存中存储的状态
        char str1[] = {'w', 'j', 'n', '\0'}; //字符串
        char str2[] = {'w', 'j', 'n'};  //字符数组
    
    • 字符串输出和输入
      字符串输出: puts(str); 字符串输入: gets(ch);
       /*
         * 字符串输出和输入问题
         */
    
    
        //1. 字符串输出
        char str[] = "lnj";
        //1.1 printf("%s"),%s会从数组的第0个元素开始打印,直到遇到\0位置
        //    这种输出不会自动换行需要\n,还可以添加自定义内容
        printf("%s\n", str);
    
        //1.2 puts输出会自动换行,但是不能自定义添加内容
        puts(str);
    
    
    
        //2. 字符串输入
        char ch[10];
        //2.1 scanf("%s", &ch);接收字符串,输入的数据中不能有空格/TAB/回车,系统会将他们默认为结束字符
        //scanf("%s", &ch);
        //printf("%s\n", ch);
        //2.2 gets接收方式
        //    可以输入空格TAB符号
        gets(ch);
        printf("%s\n", ch);
    
    • 字符串系统函数
      注意点: 使用此类函数必须在头部导入#include <string.h>
        /*
         * 字符串长度计算 strlen();
         */
    
        char str[] = "niuzi";
        //注意点: 这种计算字符串长度不包括\0字符,而且还能计算出字符串中存储字符数,但是使用系统函数需要在头部导入#include <string.h>
        int len = strlen(str);
        printf("%i\n", len); // 5
    
    #include <string.h>
    int main()
    {
        /*
         * 字符串拼接
         * strcat(ch1,ch2),传入两个数组,会将后面字符串数组拼接到前面
         * 注意点: 前面的数组必须足够长,能够容纳两个
         */
        char str1[10] = "niuzi";
        char str2[] = "wjh";
        strcat(str1, str2);
    
        printf("%s\n", str1);
        printf("%s\n", str2);
        
        return 0;
    }
    
    
    include <stdio.h>
    #include <string.h>
    void myStrncar(char dest[], char src[], int count);
    int main()
    {
        /*
         * 字符串拼接
         * strncat(dest, src, count);
         * 会将src中count个字符拼接到dest后面
         */
    
        char str1[20] = "niuzi";
        char str2[10] = "888666";
        strncat(str1, str2, 2);
        printf("%s\n", str1);
        return 0;
    }
    
        /*
         * 字符串拷贝
         * 会将后面的字符拷贝到前面,覆盖前面原有的内容
         */
    
        char str1[20] = "wjh";
        char str2[20] = "haha";
    
        strcpy(str1, str2);
        printf("%s\n", str1);
    
        /*
         * 字符串比较
         * 会依次从第0个索引开始,取出第一个数组和第二个数组中每个元素
         * 如果str1当前元素大于str2当前元素,那么返回一个正数
         * 如果str1当前元素小于str2当前元素,那么返回一个负数
         * 如果str1当前元素等于str2当前元素,那么返回一个0
         *
         */
    
    
        char str1[10] = "124";
        char str2[10] = "124";
    
        int res = strcmp(str1, str2);
        printf("%i\n", res);
    

    指针

    • 指针变量
        /*
         * 指针变量:
         *    指针变量和普通变量一样,都是用来保存数据的,只不过和普通变量有一点区别
         *    普通变量可以保存基本数据类型,指针变量只能保存内存地址,简言之就是保存内存地址的变量
         * 格式:
         *   数据类型  *变量名称;
         */
    
        int num = 7;
        int *p; //定义一个指针变量
    
        //注意点: 所有指针变量占用内存的大小是一样的,与指针数据变量数据类型无关
        //  在32位编译器中,占用4个字节
        //  在64位编译器中,占用8个字节
        //  只要一个变量存储了另外一个变量的内存地址,那么我们可以说这个变量指向了另外一个变量
        //  而且我们可以根据这个内存地址找到另外变量的内存地址,从而操作这部分内存
    
    
        p = &num; // 将num变量占用内存最小的地址存储到指针变量P中
        printf("%p\n", p);
        printf("%p\n", &num);
        printf("%p\n", &p); //取出p自己的地址
    
    • 指针内存


    • 指针变量操作数据

        /*
         * 指针变量操作存储地址数据
         */
    
        int num = 8;
        int *p;
        p = &num;
        //1. 只要一个变量指向了另外一个变量,就可以通过*变量名称的方法,操作另外一个变量的内存空间
        *p = 10; //在指针前面加上*号代表访问指针指向的那块内存
        printf("%i\n", num); //10
        
        
        //2. 指针只能保存地址,不能存储其他的值
        //3. 一个变量地址可以被多个指针指向
        //4. 指针的指向可以改变,后赋值的地址会覆盖前面赋值的地址
        //5. 定义指针变量时候,前面的数据类型,一定要和将来保存的变量前面的数据类型一致
        
        int num2 = 10;
        int *p1; // 正确   错误写法: double *p1;
        p1 = &num2;
    
    • 指针的类型
      注意: 如果函数的形参是数组或者是指针,那么就可以在函数中修改外界传入变量的值
    #include <stdio.h>
    void change(int *num);
    int main()
    {
        /*
         * 指针类型:
         *   由于指针变量指向的是某一个变量占用的存储空间的首地址
         *   所以在获取指向变量中存储数据的时候,指针是不知道要获取多少个字节的数据的
         *   所以指针变量的数据类型的作用,就是告诉指针,在获取指向变量的数据时候,需要
         *   获取几个字节的数据
         *
         * int *p 将来获取p指向的那个变量的数据的时候,需要获取4个字节的数据
         */
    
        int num = 10;
        change(&num); //注意参数如果是指针类型,此处应该传入地址
        printf("%i\n", num); //666
        return 0;
    }
    //结论: 如果函数的形参是数组或者是指针,那么就可以在函数中修改外界传入变量的值
    void change(int *num){
        *num = 666;
    }
    
    • 多级指针
      注意点: 多级指针取值格式: **p,几级指针前面就加几个*
        /*
         * 多级指针:
         *   指针中保存的是其他指针的地址
         * 
         * 如何定义多级指针
         * 在保存的指针变量的基础上加上*即可  int *p --> int **pp
         *
         * 定义指针规则:
         * 1. 将要指向的变量的定义拷贝过来
         * 2. 再将拷贝过来的代码的类型和变量名称中间加上*
         * 3. 修改变量名称
         */
    
        int num = 10;
        int *p; // 一级指针
        p = &num;
    
        int **pp; //二级指针
        pp = &p;
    
        // **pp -> *p ->num  三个相等
        printf("&num = %p\n", &num);  //0028FEB8
        printf("p = %p\n", p);  //0028FEB8
        printf("&p = %p\n", &p); //0028FEB4 一级指针对应本身的地址
        printf("&pp = %p\n", &pp); //0028FEB0  二级指针对应本身的地址
        printf("pp = %p\n", pp);  //0028FEB4  二级指针存储的是一级指针自身的地址
        printf("*pp = %p\n", *pp); //0028FEB8
        printf("**pp = %i\n", **pp); //10  取出num内存的值
    
    
        int ***ppp; //三级指针
        ppp = &pp;
    
    • 指针与数组
       /*
         * 指针和数组
         *
         * 数组名称保存的就是数组占用内存最小的那个地址
         * 既然数组名称是保存地址,指针也可以保存地址,所以指针也可以指向数组
         *
         * 结论: 如果利用指针保存数组的地址之后,那么p = ages = &ages;
         */
    
        int ages[3] = {1,3,5};
        printf("%i\n", ages[1]); //3
    
        int *p;
        p = &ages;
        p[1] = 333;
        printf("%i\n", p[1]); //333
    
    • 指针加减法
    /*
         * 指针加减法
         * 应用场景: 一般都是用在数组中
         * 指针变量+1,加的就是指针变量类型占用的字节数
         * -1操作一般都不会用到
         *
         */
        int arr[3] = {1,3,5};
        int *p = &arr;
        printf("%i\n", *p); // 1  默认指向是数组最小的地址然后取出4个字节
        printf("%i\n", *(p+1)); //3
        printf("%i\n", *(p+2)); //5
    
        printf("%i\n", *p++); //1
        printf("%i\n", *p++); //3
        printf("%i\n", *p++); //5
    
    • 指针和字符串
     /*
         * 指针定义字符串
         * 字符串本身就是数组,所以指针也可以定义字符串
         */
    
    //    char str1[] = "hui";
    //    //char *str2 = "hui";
    //    printf("%s\n", str1);
    //    printf("%s\n", str2);
    
        /*
         * 利用数组和指针定义字符串的区别:
         * 1. 存储位置不同
         *   如果是通过数组定义的字符串,那么存储在内存当中
         *   如果是通过指针定义的字符串,那么存储在内存的常量区中
         * 2.存储空间地址不同
         *   如果是通过数组定义的字符串,每次定义都要重新开辟存储空间
         *   如果是通过指针定义的字符串,重复定义不会重新开辟存储空间
         * 3.由于在内存中存储的位置不一样,所以特性也不一样
         *   如果是通过数组定义的字符串,我们可以手动修改
         *   如果是通过指针定义的字符串,我们不能手动修改
         */
    
        char *str1 = "lnj";
        char *str2 = "lnj";
        str1[1] = 's'; //不能修改
        printf("%s\n", str1);
    //    printf("%p\n", str1); //地址一样
    //    printf("%p\n", str2);
    
    int main()
    {
        //1. 接收字符串的时候,只能通过字符数组不能通过字符指针
        //2. 学习指针之后,建议将过去传入数组类的形参修改位指针类型
        /*
         * 如果函数中返回的字符串类型是通过数组创建的,那么外界无法获取
         * 如果函数中返回的字符串类型是通过指针创建的,那么外界可以获取
         * 这是因为指针类型存储数组存在常量区当中
         */
        char *str;
        scanf("%s",str); //这种错误
        return 0;
    }
    
    void test(int *arr){ //这样方式接收数组类型参数
        
    }
    
    char* demo(){
        char *str = "wjh";
        return str;
    }
    
    • 指针变量特点
    1. 可以用来保存数据
    2. 可以当做形参
    3. 可以用来当做返回值
    

    相关文章

      网友评论

          本文标题:Day09

          本文链接:https://www.haomeiwen.com/subject/agbqgftx.html