Linux和C语言基础学习笔记

 #### 计算基础 #########
    CPU(核心)        内存条(RAM)        固态硬盘(flash)     设备 
    
        CPU:                 运算能力强
        内存条(RAM):        速度快XX Gbps,掉电丢失数据        贵            运行内存    8G   16G
        固态硬盘(FLASH):    速度慢 5Gbps,掉电不丢失数据      便宜        存储内存    256G 512G
    
    程序是如何运行的:
        程序是存储在 flash里面,当需要运行的时候,拷贝到RAM,然后运行.
        

#######    unix 和 C语言发展史 ##########

        unix--------|----------------------> linux            免费开源,强大
                    |----------------------> Mac OS
                    |----------------------> IBM os 
                    |_---------------------> HP OS
                    |----------------------- xx
    
    
    linux和windows:
        linux :        免费 开源 安全性高  可以自己定制    服务器  嵌入式            真多用户
        window:        收费 闭源 不是很好  不能定制        PC(perison computer)    假多用户
        
        目录结构:
            windows:    G:\smartlock\smartlock    
                     盘符:\目录1\目录2\目录3\xxx.out
                     有很多棵树构成,每个盘符都是一棵大树.
            linux:
                     /usr/include/misc
                     /home/lsf/linux-4.7/drivers/char
                     
                     linux所有文件的起源都是  "/"   根目录
                        只有一棵树.
命令:   
        
    ls , list-列出  
        ls 目录:列举该目录下内容        ls testdir/ 
        ls 不家目录: 列举当前目录         ls 列举当前目录下内容
        
        选项
        -l   详细的列举出当前 文件夹内容    ls -l 
        -h   human人性化的    ,配合-l使用        ls -l -h  主要作用是显示 文件大小单位
        -a     --all,显示所有                    ls -a
            linux的隐藏文件,以 "."开头.
            
            
    cd 目录名    ,进入该目录
        cd: change directory  
        
        "..",表示上一级目录        cd ..  回到上一节
        "." ,表示当前目录        cd .    切换到当前目录
        cd /usr/include  切换到指定目录
        
    家目录:
        linux支持多用户同时使用,那么每个用户 必须有一个 自己的 工作文件夹.
        家目录 存在于  /home/
        每个人 都有一个目录,存在与 /home/用户名  
            ~ 符号,表示 当前用户的家目录  /home/lsf 
    
    
    pwd:  显示当前所在的 位置        Print Working Directory
    
    
    touch  filename : 创建普通文件
        touch good.c 
    rm  filename    :  删除普通文件, rm remove移除    
        rm good.c 
    rm -r  目录名  : 要删除目录
            rm -r testdir 
    
    mkdir  dirname :          make-制造 directory-目录  
        mkdir testdir 
    rmdir  dirname :        remove directory 
                        只能删除 空目录
        rmdir testdir 
                        
                        
    cp    原文件名    目的路径                    :copy    
        cp test.txt  /home/lsf/dir                 拷贝到制定目录
        cp test.txt  /home/lsf/dir/xx.txt        拷贝并且重命名   
        
    mv  原文件名   目录路径   : mv move 搬运
        mv test.txt ../testdir/                搬运 
        mv test.txt ../testdir/xx.txt        搬运并且重命令    
        
        重命名:  mv 原文件名字 目的文件名字
                mv hello.c  good.c
                
    vi filename        ##打开该文件########
    
    
    
############  第一个C程序 ###################

    C程序文件后缀都是 .c 
    头文件后缀都是    .h 
    
    #include <stdio.h>            包含C语言的头文件         stdio.h 
    
    int main(void)                C程序的 入口函数
    {
        printf("hello world\n");        很多条语句,语句之间使用";"分割
        printf("good night\n");            执行顺序,从上到下以此执行
        return 0;                        函数结束,并返回0
    }

    上述程序是不能够直接执行的,因为计算机只认识 二进制   01
    我们需要将上述代码 翻译为 二进制, 这个过程称之为 编译 compile
    
    编译:        将.c程序翻译为二进制,可以直接被计算机执行的文件.
        
                        gcc编译器 
            main.c   --------------->  main.out 


        命令:        gcc  main.c      -o main.out
                        -o:  --output  后面跟 输出目标文件的名字
                        
            执行呢:        ./main.out

    ###### 文件类型和后缀#########
        window上 使用文件后缀作为 识别文件类型的一种方法
        linux:    linux系统并不会使用 后缀 区分文件类型.
                    后缀本身就是文件名称的一部分.    
        
        当时我们还是建议,使用 后缀来区分文件类型.


##### 变量 ,可变的量   ##########
    variable--善变的,易变的        
    
    int         aa             =     5;
    数据类型  变量名字        =     变量值
    
    计算机内部做了什么事情:
        
    
    
    aa=8;aa=12;aa=100;aa=420000000;
    
    
    ####数据(变量)类型###
        long     :    long int         长整形            4B/8B=64bit        未知的大小
                    unsigned long ll;
                    signed long ll;
        int:         integer            整形            4B=32bit        
                    signed int ii;                                    -20亿   20亿
                    unsiged int ii;                                    大概0-42亿的样子
        short:        short int        短整型            2B=16bit        
                    signed short ss;                                -3w~3w
                    unsiged short ss;                                  0~65535    
        char:        charator int    字符类型        1B=8bit            
                       char cc;            默认是有符号
                signed char cc ;                                    -128->125
                unsigned char cc;                                       0-255
    
        
    
        浮点型:
        float    4B, 单精度浮点,可以精确到 小数点后  7位的样子
        double  8B ,双精度浮点,    ...                     14的样子
    
    
    有符号和无符号:        +    -
        signed-有符号的, unsigned-无符号的
        
        一个数据,占据一定的bit数量,用来存放数据.    范围0~ ( 2^位数-1  )
        但是无法表达 负数, 那么如何表达负数呢?
            我们 要去 数据的最高位,当做符号位        1-表示负数, 0-整数
        
    ###变量的命名规则########
        int  aa ;        aa是变量名字,名字是否 有一定的规则.
        
            
        命名规则:
            1.  只能有"字母a-z" "数字0-9"  "_"构成
                int a$b;  X
            2. 数字不能打头
                34abc   X 
            3.区分大小写
                int aa; int AA;  是两个不同的不变量
            4.命名不要和关键字冲突
                int int = 8;
    
        练习:    $abc    aa?dd  _abc   _abcA   _23dd   34adb    T_abc   t_abc    *_abc    double  doublea  a&b     a=d  
                 X        X                             X                         X         X               X       X
                 
  
########  字符和字符串###########                 
        
    字符:        符号, 'A'  'a'  '*'  '('  '['   '`'   '|'    '0'  '7'        '$'   '#'
                手工输入字符的时候,使用 ' '裹起来.        '用来裹字符的.
    字符串:        字符构成的串        "hello world\n"
                字符串使用 "  " 裹起来.
    有哪些符号:    
            总共256个符号.        使用 字符类型 来存储 字符.
            
            char  cc =     65;
            char  cc =  'A';    gcc编译器在编译的时候,会将 'A'转换为65;
            
            printf("cc=%d %c\n",cc,cc);
            
            cc = cc + 1;    
    
    如何存储,计算机只能存放 数字, 无法直接存放 符号.
            我们 给每个符号 安排 一个对应的数字, 存的是 该数字.
            
        如何产生对应关系:
            assccii码表, 美国通用的字符表
    
    
    练习:
        char  cc ; 请你将他转换为 小写
            cc = cc+32;
            请你将他转换为大写:
            cc = cc-32;

        已知char cc='5';  请你将他转换为 数字 5

            cc=cc-'0';
            
    ### 转义字符 ##########
        转变 意义 的字符
        
        有很多符号,人眼看不到的    比如 换行符 删除符  上下左右
        
        代码中如何 使用他们呢?
        
            printf("hello world");
            printf("%c",10);
            
            char cc = 10;    //记录了一个换行符
    
            很难手工输入到计算机中,如何简化输入方式呢:        a --- z  0-9 
            可否   '\n'            对'n'进行转义,变为 换行 
                \表示 转移,即 '\'后面的一个字符被转义 
                printf("hello world\n"):
                
        '\n'        : 换行的意思        ,编译器遇到  \,会将后面得字符表达为另一种意思
        
        '\r'        :    回到行首    
        
        '\t'        :    tab
        
        '\''            :    如何输入一个 正宗的'  ,  char cc = '\''
                    
        '\"'            :  如何输入一个 正宗的 " ,  char cc = '\"';
                        printf(" the present says:\"the world belong to us.\"...\n");
        '\\'            :  如何纯粹的 打印 '\'
                        printf("the char \\ is very good \n");
                        
#########    字符串     string   ####
        字符在一起形成的 串        
        
        "hello world\n";
        "good good study,day day up"
        "welcome to our home."
        
        
        计算机如何存储字符串呢:
            按照字符的格式以此存储, 每个字符占据 1B(char)
                注意,字符串 必须以 '\0'作为结束.
            
########        进制 ############
    十进制
    二进制
    十六进制 
    八进制
    
    
    生活中,使用的          十进制
        古时:        一打 12进制
                    星期 7
                    时间:    30天 一个月        24小时  60sec
                            1sec=1000ms 1ms=1000us 
                            
    十进制:        0-9    十个数  逢十进一
    
                1789= 1*103 + 7*10^2 + 8*10^1 + 9*10^0  ;
    
    
    二进制:        0-1 二个数    逢二进一
            
            二进制转换为十进制
                (1010) =  1*2^3 +     0*2^2    + 1*2^1 + 0*2^0 = 10
            十进制转换为 二进制:
                除余法即可.
                
                
        小技巧:        8421码
        
                         8421
            规律    1100 1101 
        
        
                
            11 0011 =     32+16+2+1= 
            14 = 1110
            
            9 = 1001
                

        二进制主要用在计算机领域,

        
    十六进制:
        二进制 表达太麻烦,十进制和二进制隔阂太大
        我们使用十六进制来代替 二进制.
        
        0-9 A B C D E F, 逢 十六 进制
        
            十六进制 转换为 十进制:        0x1AB5 = 1*16^3 + 10*16^2 + 11*16^1+5*16^0 
            十进制如何转换为 十六进制:
                除余法 
        
        
        最常见的用法:
            十六进制 <--->二进制 
        
            二进制->十六进制        将二进制分为4bit一组 ,4bit转换为一个 16进制
            0110 1100 0110 1101
              6   C    6    D 
        
            十六进制-->二进制         每个16进制数据,都要转换为 4bit二进制 .
              6        C        6    D   
              0110  1100  0110   1101
        
    八进制:    
            0-7    逢八进一    
            
            八进制和十进制转换:
                0125 = 1*8^2 + 2*8^1+5*8^0    
            十进制转换为 8进制:
                除余法 
    
            八进制和二进制 转换:
                110  101  011  111
                6     5    3    7
                
                
                
#### printf 的用法###########

    printf("hello world\n");
    int aa = 456;            printf("int counter = %d\n", aa);        //    %d:decimal     十进制 
                            printf("octuber aa  = 0%o\n");            //  %o: octuber 八进制 
                            printf("hex     aa  = 0x%x\n");            //  %x: hex     十六进制
    unsigned int aa=12586;    printf("uint counter= %u\n", aa);        //    %u, unsigned 无符号打印,也可以使用%d,建议%u 

    short int aa;            printf("short int aa= %d\n",aa);        //   %d 
    unsigned short aa;        printf("short uint aa=%u\n",aa);        //   %u
                
    long int aa;            printf("long  int aa=%ld\n", aa);        //   %ld    long decimal     
    unsiged long [int] aa;    printf("ulong     aa=%lu\n", aa);        //   %lu     long unsigned int
                
    char    aa ;            printf("char      aa=%c\n",  aa);        //     %c      charator

    float    aa;             printf("float     aa=%f\n"    ,aa);        //  %f:   float浮动的
    double  aa;                printf("double    aa=%lf\n" ,aa);        //  %lf:  long float

    "hello"                    printf("string hello=%s\n", "hello");    //  %s:    string 
    
    
    高级用法:
        printf(" %[flags][总宽度][ . 小数位精度]X");                    X=d/o/x/u/lf/f/c/...
        
            总宽度:        如果没有指定数据的宽度,那么按照真实的数据宽度来显示
                printf("%8d");        如果你指定的宽度,小于数据真实宽度,则按照真实的来.
                使用空格' '来填充 
            flags:    指定 填充的字符
                    flags 要么为0,要么不写,不写则以' '填充.
                    
                printf("%08d");        0表示填充,8表示宽度
            .小数宽度
                指定小数位的宽度
                printf("%08.4f");
                printf("%.4f");
                
##########        运算符  #############
  #### 算术运算符########
    +-*/%    =    
    
    "+"    :    两个数相加            5+6        a+8        2.3+6.6        5+6.3            cc = 5+3.69    
    "-" :    两个数相减            5-6     a-b     2.6-9.9        5-6.1    8-c     cc = a-5 
    "*"    :    两个数相乘            5*6        a*b     3.6*9.5        5*6.2            cc = a*5;    
    "/" :   两个数相除            3/6        5.2/2    6/3.2                        
    
                            两个整数相除,结果还是整数 ,称为 #整除#
                                3/6 == 0        5/6==0        19/2=9
                                
    %    :   取余        3%2
                取余,只能用于 ###整数间求余####
                
                
    '=':    赋值运算符        动作,  a=5;    将 '='右边的结果(先进行运算),交付给 左边的变量
                    a=5+6+9+8+9;
    
    
    ####运算符的简化##########
        
        a=a+5;        a += 5;            
        b=b-3;        b -= 3;
        c=c*2;        c *= 2;
        d=d/4;        d /= 4;
        f=f%5;        f %= 5;
    
    
        a=a+1;        a += 1;        a++;    b=-++; 先将a的值给b,然后a++;    b=++a;先讲a的值++,在交付给b     无论如何,a都是++了的.
        a=a-1;        a -= 1;        a--;    b=a--; 先将a的值给b,然后a--;    b=--a; ..................
    
    
    
        (a++) 的结果是 a原始的值    ,a的值+1;
        (++a) 结果 a的+1的结果         a的值+1
    
    
    #########        比较运算符            >      <      >=      <=       ==    !=

    a = 5 + 6;
    a =    5 > 6;            比较运算符,对两个数进行比较,得到结果        如果成立结果为1-true-真    否则结果为0-false-假 
    a = 34<38;
    a = 45==55;
    
        if(a=5){
            printf("相等");
        }else {
            printf("不相等");
        }
    
    小明 int ming_score=88; 小红 int hong_score=99;
    
    if(      ming_score > hong_score    ) {            //如果判断为真,即  结果为1 ,执行 下一条语句
        printf("xiaoming is good\n");
    }else {                                        //如果为假,  即 0,则执行 该语句.
        printf("xiaohong is good\n");
    }
    
    
    
    if用法:
        if( 条件判断 ) {
            如果条件合适,则执行这里
        }
    
    
        if(条件判断){
            如果条件合适,则执行这里 
        }else {
            如果条件不合适,则执行这里
        }
    
        小丽的成绩 int score = 99;        A:90-100  B:80-90  C:60-80    D:60以下
        if(score >= 90){
            printf("A\n");
        }else if(score >=80){
            printf("B\n");
        }else if(score >=60){
            printf("C\n");
        }else {
            printf("D\n");
        }
    
    
        注意问题:
            if后面如果没有 {},则 if的作用范围是 第一条语句.


        练习题:
            已知三个数: int a=5, b=54,c=12;        
            请你找出 其中的最大值,并打印出来.
            
            if(a>b){
                //b 淘汰,  a  c
                if(a>c){
                    printf("max=%d\n",a);
                }else {
                    printf("max=%d\n",c);
                }
            }else {
                //a淘汰        b c 
                if(b>c){
                    printf("max=%d\n",b);
                }else {
                    printf("max=%d\n",c);
                }
            }
            
            
            
        ####    条件组合  ######

                语文      数学      英文 
        优秀    >=90      >=90      >=90
        尖子     只要有一门成绩>=95
        良民    >=60   >=60     >=60
        

        已知某个学生成绩:   int yuwen=95; int shuxue=90; int yingyu=82;
        
        
        条件组合:        
                &&--与    ||--或      !--非
                
                &&:  都成立才可以 
                ||:  只要有一个合适就是合适的
        
            优秀:        (yuwen >= 90 )   &&        (shuxue>=90 )   &&  (yingyu>=90)
            尖子:        (yuwen >=95  )     ||     (shuxue>=95 )     ||    (yingyu>=95)
                
                    if(     (yuwen >= 90 )   && (shuxue>=90 ) &&      (yingyu>=90)    ){
                        printf("you are good\n");
                    }
                    
                    if( (yuwen >=95  )    ||     (shuxue>=95 ) ||    (yingyu>=95) ){
                        printf("you are top\n");
                    }


            爱国者:        yingyu <60 
            
                    if(   !( yingyu >= 60 )   ){
                        printf("re ai guo jia\n");
                    }

        
        
        练习题:        已知一个年份    int year=2065;    
            请你判断他是不是 瑞年.
            
             闰年的规则:能被4整除,但不能被100整除,或者直接能被400整除
             
                        (year%4==0  &&   year%100!=0  )  ||      ( year%400==0)        闰年 
        


                    !( (year%4==0  &&   year%100!=0  )  ||      ( year%400==0)  )    


            中国足球来你校招聘 运动员
            
            (    (yuwen>=60 &&    shuxue>=60 )    || (height>185cm)         )     &&         (sex!=woman)


    ####三目运算符:        ? :            
        两目运算符:    +-*/ >< ==            5+6
        
        
        
        作用:        
                if( 条件判断 ) {                    if(a>b) {
                    如果条件成立,执行这里                max=a;
                }else {                                }else {
                    条件不成立,执行这里                 max=b;
                }                                    }
            
            
            
            上述的语句功能非常简单,但是我却写了5行.        我们可以使用 三目运算符 取代.
            
            max =  a>b          ?  a          : b;
            max =  条件判断  ? 成立结果 : 不成立结果 ;

             
        举例:    小明 考试得了 int score=65;
            
            请你判断合格了吗:
            
            score >=60 ? printf("合格")  : printf("不合格");
            
            int daoshoumomey = salary >5000 ? salary-300 : salary;

        练习: 使用三目运算符 求取三个数中最大的那个
            int a=45,b=43,c=23;
            
            
                    条件     a>b代码         a<=b代码
            max=    a>b  ?  ( a>c?a:c  )  :   b>c?b:c   ;
                

    ######   位运算符  ############
        
        数电    :  按位与  按位或  按位取反  
        位,即一个bit,要么为0  要么为1
        
        
    与& :        与, 和  并且              都为真(1)结果才为真(1)
    
        1 & 1 = 1
        0 & 1 = 0
        1 & 0 = 0
        0 & 0 = 0
            
            规律:   a & 1 = a            a=[0  1]        和1相与则不变
                    a & 0 = 0            a=[0  1]        和0相与则置零
        
    
        short aa = 1100 0011 1010 0101
        &      bb = 0101 1110 0111 1100
             ----------------------------
        =          0100 0010 0010 0100  
    

        练习: 已知 一个 short int aa, 请你 将它的 0-3位 置零,其他位保持不变
        
            aa  = xxxx xxxx xxxx xxxx 
            &     1111 1111 1111 0000 
            =      xxxx xxxx xxxx 0000 

        总结:   与操作主要目的 是将一个数据的某些位 置零.
            

    按位 | :        有一项为真就是真
    
        1 | 1 = 1
        0 | 1 = 1
        1 | 0 = 1
        0 | 0 = 0
            规律: 和 1 相或 为1                a | 1 = 1
                  和 0 相或 不变            a | 0 = a
    
        short aa = 1100 0011 1010 0101
        |      bb = 0101 1110 0111 1100
             ----------------------------
        =          1101 1111 1111 1101

        练习:  已知一个数 aa ,请你将他的 4-7位 置一,其他位保持不变
        
            aa  = xxxx xxxx xxxx xxxx 
            |     0000 0000 1111 0000
            =     xxxx xxxx 1111 xxxx
            
        总结: 用于将数据的某些位 置一.
        
        
        
        思考题:  有一个数据aa  ,请你将 aa 4-7位,修改为 0101 
                aa  = xxxx xxxx xxxx xxxx 
                &     1111 1111 0000 1111        先进行 &,清零
                =     xxxx xxxx 0000 xxxx 
                
                |     0000 0000 0101 0000        在进行 |, 置一
                
                =     xxxx xxxx 0101 xxxx
            
            
        按位取反 ~  :            
        
            ~0=1
            ~1=0
            
            ~ 1010 1100 1101 0101             
            = 0101 0011 0010 1010
                
                作用:将一个数所有的位都进行取反

        异或^ :
            
            相异为1,相同为0
            
            1 ^ 1 = 0
            0 ^ 1 = 1
            1 ^ 0 = 1
            0 ^ 0 = 0
            
                规律:  和1异或取反        a^1=~a 
                        和0异或不变     a^0=a
        
            作用: 取反数据的某些位 

        练习,  请你 将 aa的 8-11位取反,其他位保持不变 
        
                aa = xxxx xxxx xxxx xxxx
                ^    0000 1111 0000 0000 
                =    xxxx XXXX xxxx xxxx 


     <<左移   >>右移 : 位的左移和右移 
     
        0011 << 1 = 0110        使用0来补充
        0011 >> 1 = 0001        使用0来填充
        
        
        char aa = 0x3C;                   60 
        aa = aa << 1;    // aa = 0x78 = 120
        aa <<= 1;        // aa = 0xF0 = 240
        ####        发现 <<1,等于 *2         <<2,*4  ####
        ###            类似, >>1,等于/2 整除的效果 ####
        
        通过 << >>,取代部门 * 和除法 ,从而提高代码执行效率
        
        
        
####    类型转换 ############
        int double float char short ...数据有很多类型
        
        short aa =5; int bb=6; float cc=7.78925;
        不同类型的数据,有时候需要 进行互操作        5+6.3  
        
        但是 CPU在硬件上 不支持 不同类型数据的运算.        硬件上不支持 6+3.6 
        但是 C语言是支持的:        如何做到的 
            C语言 会偷偷的 将你的数据,进行 隐式的类型转换        6+3.6--->6.0+3.6        short a=5;int b=56; a+b
            
            
    隐式类型转换:        C语言发现两个类型不同的数据进行运算的时候,会进行 隐式类型转换.
                    规则:
                        1.  小类型向大类型转换                 避免数据被破坏.
                                5+6.6        int->double        5.0+6.3
                                short a;    int b;        a+b     short->int
                                char ch='A'; int b;        b+ch;    char-->int
    
                        2. 运算符 右边的类型无条件转换为 左边的类型.
                            int aa = 6.9;        取整 
                            short cc = 216456645;
                        3.    有符号和无符号 相互操作
                            int aa=-34;        unsiged int bb=123;
                            
                            有符号无条件转化为 无符号 
                            
            隐式类型转换是 C语言自动进行,我们无法控制.我们可否按照自己的需求进行类型转换
    强制类型转换:        按照程序员的 想法去转换 
                
                (转换后的类型)转换前的数据        (int)5.689 
    
    
    举例:
        工程今天生产了 5.8L 牛奶,    6.8L果汁    , 3桶  
        
        请问 今天的量是多少            
                (隐式)         5.8+6.8+3.0 =  15.6 
                (强制)        (int)5.8  + (int)6.8 + (int)3 = 14
        


########  homework        练习#############

    1.定义一个三位数变量,最后编程输出该变量的个、十、百位上的数值
        int aa=789;

        个位:    = aa % 10    ;
        十位:    = aa /10 %10;
        百位:    = aa/100;


    2.定义两个变量,编程交换两个变量的值,最后输出交换后的数据
        int aa=44; int bb=55;        请你交换他们的数值
        
        int cc = aa; aa=bb; bb=cc;        需要借助第三个数值
        
    3. 已知 五个数,int aa=33,bb=-4,cc=0,dd=-343,ee=23;    
        请你求取     正数的个数     0的个数      负数的个数
    
            int positive=0;         //积极地,正面的 
            int zero = 0;    
            int negtive=0;            //消极的,负面的 
            
            
            if(aa ==0){
                negtive++;
            }else if(aa>0){
                positive++;
            }else if(aa<0){
                negtive++;
            }
    
            ....
            
            printf("positive=%d zero=%d negtive=%d\n",positive,zero,negtive);
    
    4. 请你用三目运算符完成 :
        score >=90使用 输出 A 
             60-89之间 输出 B
             其他的输出     C
    
    
        score > 90 ?  printf("A") :   (   score>=60 ? printf("B") : printf("C");   )      ;
        
        
        

###########        运算符的优先级 #############


    int aa = 5*4  + 6* ( 5+9)  ;        *运算符优先级高于+ , ()优先级是最高的
             ++y*5 ;        --> (++y)*5
             
    
    
    要求:  尽可能的使用() 避免歧义的问题.
            
        ()[]      >          ++ --       >      */           >      + -  


#########    scanf #############
    printf("%d %c %u %ld %f",    23,'A',234,2342,25.36);        程序    -------> 终端
    scanf();                                                终端    -------> 程序 

    int aaa;
    scanf("%d", &aaa);            &,取地址运算符        scanf会等待终端输入一个整数(%d),scanf得到整数后会存到aaa中.
    
    int age; char sex; int id; double weight;
    scanf("%d %c %d %lf",  &age,&sex,&id,&weight );        scanf会以此从终端读取 %d整数 %c字符 %d整数
                                                                %lf浮点,以此存入后面的&age,&sex,&id,&weight 
                                                多个输入,以空格作为间隔.
        
    scanf有很多的bug
    
    如果输错,可以通过    ## ctrl+c ##  的方式结束程序.
    

#########        if 和 switch ####################

    if的用法:            所有的if都建议 使用 { }
        
        if(条件判断){
            成立则执行.
        }

        if(条件判断){
            成立则执行
        }else {
            不成立执行
        }
    
    
        if(条件判断1 ){
            如果成立执行
        }else if(条件判断2){
            ...
        }else if( ...){
        
        }
    
    
        ### if的缺点, 如下 ############
        char keynum = getKeyboard();
        if( keynum=='A'){
            ...
        }else if(keynum=='B'){
        
        }else if(keynum=='C'){
        
        }else if(keynum=='D'){
        
        }
        ...... 太长了 ....
        }else {
        
        }
    
    
    ###  switch 用法 ####
    
    char keynum = getKeyboard();
    
    switch(keynum){                            switch根据变量keynum, 依次去匹配每一个 case 项,如果配上则 执行对应代码. 
    case 'A':                                    遇到break则终止本次swtich, 代码继续执行.....
        如果是A,则处理这里代码.                    如果没有遇到break,会继续以此执行.
        break;
    case 'B':
        如果是B,则处理这里代码;
        break;
    case 'C':
        如果是C,则处理这里代码 
        break;
    ......
    
    
    default:        
        如果以上都没有匹配的,则执行这里            如果一个case 都没有匹配上,则执行default的操作
    };
    
    
    注意1,switch只能 用于 ##相等##判断的情况,不能用作范围匹配.
    
            比如以下,无法完成.
            if(score>90){
            
            }else if(score >80){
            
            }else if(score >60){
            
            }else {
            
            
            }
    注意2: switch 进入某个选项后,如果没有遇到break,则继续 执行.
    
            练习题: 根据成绩 打印 等级  ,使用switch完成
            
                int score;
                printf("input score:");
                scanf("%d",&score);
            
                90---99  和 100     A              9, 10         
                
                70--89              B             7  ,8     
                    
                60-69               C             6    
                其他                D         
                
                swtich(score/10){
                case 10:
                case 9:
                    printf("A");
                    break;
                case 8:                
                case 7:
                    printf("B");
                    break;                    
                case 6:
                    printf("C");
                    break;                    
                default:
                    printf("D");
                
                }
            
        练习:    从终端输入 月份 [1-12],打印出 春夏秋冬 
        
            int month;
            printf("input the month:");
            scanf("%d",&month);
            switch(month){
            case 1:
            case 2:
            case 3:
                printf("spring festvol\n");
                break;
            case 4:
            case 5:
            case 6:
                printf("summar festvol\n");
                break;
            case 7:
            case 8:
            case 9:
                printf("autumn festvol\n");
                break;
            case 10:
            case 11:
            case 12:
                printf("winter festvol\n");
                break;
            default:
                printf("unkown month=%d\n",month);
            
            }
            
    注意3:
            请你输入一个浮点,使用switch处理.  switch不能用于浮点处理.
            以下是错误 用例:
            double weight ;
            scanf("%lf",&weight);
            
            switch(weight){
            case 75.23564544 :
            
            case 75.23564545:
            
            
            
            case 86.2634554564564646:
            
            case 
            
            
            
            }
            
            


#####        原码 反码 补码 ##########

    研究数据到底在计算机中是如何存储的.        ##补码###
    
    原码:    原始存储/表达方式 
    
        正数  原码   int a = 5;                0000 0000 0000 0000 0000 0000 0000 0101
        负数  原码   int a =-5;                1000 0000 0000 0000 0000 0000 0000 0101

    反码:        正数的反码和原码相等        负数的反码,符号位不变, 其他取反.
        正数  反码   int a = 5;                0000 0000 0000 0000 0000 0000 0000 0101
        负数  反码   int a =-5;                1111 1111 1111 1111 1111 1111 1111 1010

    补码:     正数, 原码=反码=补码      负数的补码=反码+1
        正数  补码   int a = 5;                0000 0000 0000 0000 0000 0000 0000 0101
        负数  补码   int a =-5;                1111 1111 1111 1111 1111 1111 1111 1011
        
    

    
练习:
            0.分段函数:
                键入一个整数x,
            如果小于3则执行x+=3操作,

                如果大于等于3且小于等于9则执行x=3*x+9

                如果大于9则执行x=9*x-10

                int value;
                printf("input the value:");
                scanf("%d",&value);
                if(value<3){
                    value = value + 3;
                }else if( value>=3 && value <=9 ){
                    value=3*value+9
                }else {
                    value=9*value-10
                }
         

            1.输入三个值判断这三个值是否构成三角形

                如果是:
                    (是否是直角 等腰 等边 普通 不能)


                三角形:最小的两边之和大于第三边    可以使用  &&  &&
                    int b1,b2,b3;
                
                    if(b1>b2){        //b2不是最大的
                        if(b1>b3){    //b1 is max 
                            if(b2+b3 > b1){
                                printf("可以");
                            }else {
                                printf("不可以");
                            }
                        }else {        //b3 is max
                            if(b1+b2>b3){
                                printf("可以");
                            }else {
                                printf("不可以");
                            }
                        }
                    
                    }else {            //b1不是最大的
                    
                    
                    }
                

                直角:a*a+b*b==c*c


                等腰:任意两条边相等
                

            等边:三边相等

            2.输入三个整数x,y,z,请把这三个数由从小到大输出(两两交换,三次)

            

            3.从scanf输入一个成绩,判断成绩的等级:     学习成绩>=90分的同学用A表示,60-89分之间的用B表示,小于60用C表示

            5.停车场收费系统,3小时以内,收费每小时30元,超出部分每小时50元,输入一个时间,计算 费用.
                int hour;int money;
                printf("input park time hour:");
                scanf("%d",&hour);
                if(hour<3){
                    money = hour*30;
                }else {
                    money = 3*30;
                    hour-=3;
                    money +=   hour *50;
                
                }
                printf("momey is %d\n",money);
                


            6.判断输入的4位数是否是回文数(1221是回文数, 1234不是)

                    int value;
                    int qian,bai,shi,ge;
                    ge= value%10;
                    shi = value/10 %10;
                    bai = value/100 %10;
                    qian = value/1000;

                    if(  (qian==ge) && (shi==bai)  ){
                        printf("shi");
                    }else {
                        printf("fou");
                    }
                    

            7.输入年份判断该年是否是闰年
            //闰年
            //能被4 整除但是不能被100整除     或者能被400整除


            8.输入一个整数,判断是否既是3 也是5 又是7的倍数

                if(  (value%3==0)  &&  ( value%5==0)&& ( value%7==0 )    ){
                    
                
                }


########### 循环 loop ############
    
    有时候我们需要 一段代码,重复 循环 执行很多次.


    案例:    从键盘输入10个数,输出0的个数.
    
        int counter = 0;
    
        int aa;
        
        loop:                标签
            scanf("%d",&aa);
            if(aa==0){
                counter++;
            }
    
            goto loop;
    
    
    ##### 第一种循环结构 goto ########
    
        练习:    实现 1+2+3+4+....+100的和
        
                int i =1;    //    i=1 2 3 4.. 100 
                int sum=0;    // sum += 1 2 3 4 5 ... 100
                
                loop:
                    sum = sum+i;
                    i = i+1;
                    if( i  <= 100){            //边界问题,走两步
                        goto loop;            
                    }
                    
                printf("sum=%d\n",sum);
                
        练习: 实现阶乘, 从键盘中输入n, 打印n!=1X2X3X4X5X6X7
            int --  32bit --42亿 
            
            n!=1X2X3X4X5X...Xn
            
        
        总结:
            对于一个非死循环,            三要素: 起始值,    每次循环修改, 每次循环都需要判断
            
            
    ####    while循环    ############
        条件起始值
        
        while(  条件判断 ){
            条件成立,进入循环体
            修改条件值
        }
        
        一旦条件不满足,立即结束循环
    

        案例:    累加    1+2+3+....+100
            int sum=0;
            
            int i=1;
            while( i<= 100 ){
                sum+=i;
                i++;    
            }
            printf("sum=%d\n",sum);
            代码执行到这里,i==101
            
            
        案例2:    n!  从键盘中输入n,求取n的阶乘
            n!=1x2x3x...xn 
            int val = 1;
            
            int i = 1;
            while( i<= n ){
                val *= i;
                i++;
            }
            
            printf("val=%d\n ",val);
            
            
        ##### break中止  continue继续  ############
    
        while( 条件判断 ){
            循环体        
                break;    中止当前的循环,结束while, 继续执行后续代码
            条件变化
        }
        
        .......
        
        案例:    从键盘输入 数据,计算它们的累加和,遇到 -1则结束循环.
        
            int sum=0;
            int val;
        
            while( 1 ){ 
                printf("input val:");
                scanf("%d",&val);
                if(val == -1){
                    break;            break中止当前循环,继续执行后续代码
                }
                sum+=val;
            }
            
            printf("sum=%d\n",sum);
            
            
            
        ##continue 
            案例  实现累加和 0+2+4+6+... +100
            
            int sum=0;
            int i = 0;
            
            while(i <= 100){
                i++;        
                if(i %2 == 1){
                    continue;        //放弃后续代码,直接开始下一次循环
                }
                
                sum+=i;
            }
            
        ### while的变体  #########
        
        
            条件起始;
            do {
                循环体,   循环体第一次无条件执行的,后续 如果条件判断成立,才成立
                条件变化;
            }while(条件判断) ;
            
            
            案例:  累加和 1+2+3+...+100
            
                int sum = 0;
                int i = 100000;
                
                
                do {
                    i++;
                    sum+=i;
                }while( i  < 100  );
                
                printf("sun=%d i=%d\n",sum,i);
                
    
        ## 练习:        从键盘输入一个整数,判断他是否是 素数/质数  
        
        
            质数 :        一个数 只能被1和自身整除.
            
                   具体该如何做:   比如 n 
                        从 2 ..... n-1,这些数都不能被整除,则认为他是素数 
                        
                        
                int n;
                printf("input the value:");
                scanf("%d",&n);
                         
                int i=2;
                while( i<= n-1 ) {
                    if(n%i == 0){
                        break;        //中间中止,   i<= n-1
                    }
                    i++;
                }
                
                //不论如何,代码会抵达这里         中间中止 i<=n-1,  如果是 正常中止i==n 
                if(i==n){
                    printf(" n=%d is zhishu\n");
                }else {
                    printf(" n=%d is not zhishu\n");
                }
                
            挑战###
                请你找出 1000以内的所有质数:
                
                
                val = 2 3 4 5 .........  ,1000
            
                int val = 2;
                while(   val <=1000  ) {

                          //判断val是否是质数        i =     2   3  4    .........   (val-1)
                         int i = 2;
                         while(  i<= val-1  ){
                                  if(val%i == 0){
                                        break;
                                  }
                                   i++;
                          }
                         if(i == val ){
                               printf(" %d ",val);
                        }

                       //寻找下一个val
                       val++;  
                }
                
    #### 第三种循环 for ##############
    
        不死循环:    三要素  1起始条件  2条件改变 3条件判断
        
        for(起始条件;  条件判断;  条件变化 ){
            循环体
        }
    
        工作过程:
            1. 执行起始条件,执行一次即可.
            
            2. 条件判断,如果成立 执行循环体,  如果不成立 结束for循环
            
            3.条件变化 ,goto 2;
            
        案例:    累计和    1+2+3+....+100
        
            int i; int sum=0;
            
                起始条件 
            for( i=1  ;   i <=100        ;  i++   ){
                //i = 1 2 3 4 5 6 .....
                sum += i;
            } 
        
        
        练习: 判断一个数,是不是素数
            int num;
            int i;
            printf("input num:");
            scanf("%d",&num);
            
            // i=2 3 4 5 6 .. num-1            num%i==0
            for( i=2 ;    i<= num-1  ; i++  ){
                //i = 2 3 4 5 6 7 .. .. num-1 
                if(num % i == 0){
                    break;
                }
            }
            //代码到了这里        i==num 是质数  i<=n-1不是质数
            i == num ?  printf("yes") : printf("yes");
        
        
        练习2: 找出1000以内所有的质数
        
            val = 2 3 4 5 ............. 1000
            
            int val;
            int i;
            for(val=2;  val<=1000; val++ ){
                //val = 2 3 4 5 6 7 ... 100
                //判断val是否为 质数   i=2 3 4 5 6 ... val-1  
                for(i=2; i<=val-1;i++){
                    if(val%i == 0){
                        break;
                    }
                }
                if(i==val){
                    printf(" %d ",val);
                }
            }
            

        死循环:
            while(1){
                
                
            }

            for(; ; ){
            
            
            }


        练习:
        
          要将5张100元的大钞票,换成等值的50 20 10 5小钞票,每种面值至少一张, 
            有多少种换法,把所有的可能性的东西,全部列举
            
            50元  范围        a [ 1  10  ]
            20元            b [ 1  25  ]
            10                c [ 1  50  ]
            5                d [ 1  100 ]
            
            int a,b,c,d;
            int counter = 0;
            for(a=1;a<10;a++){
                //a=1 2 3 4 .. 9
                for(b=1;b<25;b++){
                    // b =1 2 3 4 .. 25
                    for(c=1;c<50;c++){
                        //c = 1 2 3 4 .. 50 
                        for(d=1;d<100;d++){
                            if(  a*50 + b*20 + c*10 +d *5   == 500 ){
                                printf(" %d %d %d %d \n",a,b,c,d);
                                counter++;
                            }
                        }
                    }
                }
            }
            
            
            
        练习:    
            从键盘输入 行和列,打印如下形式
            
            int hang = 4;    int i;    //i=1 2 3 4
            int lie  = 5;    int j;    //j=1 2 3 4 5
        
            *****        1
            *   *        2
            *   *        3
            *****        4
            
            printf("input hang lie:");
            scanf("%d %d",&hang,&lie);
            
            for(i=1;i<=hang;i++){
                //i=1 2 3 4 .. hang 
                //要区分 第一行,最后一行  和其他 行 
                if( i==1 || i==hang){        //全部打印*
                    for(j=1;j<=lie;j++){
                        printf("*");
                    }
                }else {                        //打印*    *
                    for(j=1;j<=lie;j++){
                        if(j==1 || j==lie){
                            printf("*");
                        }else {
                            printf(" ");
                        }
                    }
                }
                
                printf("\n");
                
            }
            
            
        从键盘输入行数,打印如下形式:
        
            输入n的值,n代表行数,输出如图所示的图形 
                                    行号    空格        *
                     *                1         3            1
                  *  *  *            2         2          3
               *  *  *  *  *        3         1            5
            *  *  *  *  *  *  *        4         0          7
            
                                    i           n-i           2i-1           
                                    ..
                                    n      
            
                        (此图为n=4时的输出结果)
                        
            int n;    
            printf("input n:");
            scanf("%d",&n);
            
            for(int i=1;i<=n;i++){
                //i 行, i= 1 2 3 4 5 ........ n 
                //先打印 n-i 空格 
                for(int j=1;j<=n-i;j++){
                    printf(" ");
                }
                //在打印 2i-1个 *
                for(int j=1;j<=2*i-1;j++){
                    printf("*");
                }                
                //打印\n
                printf("\n");
            }
            
    ### 小游戏  ####
        
        
        产生一个随机数 1~100以内
        
        srand(getpid());
        int randval = rand() %100  ;        //rand()返回的随机数 范围 0--42亿
        
        while(1){
            printf("input val:");
            scanf("%d",&val);
            if(val < randval){
                printf("your input is little\n");
            }else if(val > randval){
                printf("your input is bigger\n");
            }else if(val == randval){
                printf("congratulations \n");
                break;
            }
            
        }
        
        
        
        int i ;     //行 1 2 3  4 5 6 7 8 9 
        int j;         //   1 2 3 .. i  
        
        for(i=1;i<=9;i++){
            // i = 1 2 3 4 5 ...  9 
            for(j=1;j<=i;j++){
                printf("%d X %d = %d ",j,i,i*j);
            }
            printf("\n");
        }
        
        
######      数组     array  ###############
    以前:  int a ,b ,c,d ,e   ...;         如何一次定义100个变量.
    数组允许你一次定义N个变量.
    
        int aa[10];        //int a,b,c,d,e,f,g,h ,i,........
        
        如何使用某个成员:    aa[0]~aa[9]            下标范围 0-9
        
    定义并赋值:
        int a=4,b=3;
        int aa[10] = {12,34,345,32,23,23,4,23,23,233 };        依次赋值
        int aa[  ] = {12,34,345,32,23,23,4,23,23,233 };        如果不指定数组个数,那么 会根据 赋值的个数来确定.
        int aa[10] = {12,34,345,32,23,23,4,23        };        依次赋值     ,未赋值处置零
        
        求取数组占据的空间,单位 B :        
            printf( "sizeof a   = %d\n",sizeof(a) );
            printf( "szieof aa[]= %d\n",sizeof( aa)            ");        ## sizeof(数组)
            求 数组元素的个数:
                sizeof(aa)/sizeof(aa[0])
                
        数组名aa,记录了整片空间的地址. 类似指针 .
    
        例子:    定义一个数组,内有10个整形数据;  从键盘输入10个数据,存入其中.
        
                int aa[10];
                //从键盘读取数据 以此存入 aa[0] aa[1] ... aa[9]
                for(int i=0;i<10;i++) {
                    printf("input num%d:",i);
                    scanf("%d",  & aa[i]    );
                }
 
                printf("travel array:");
                for(int i=0;i<10;i++){
                    printf("%d ",aa[i]);
                }
                printf("\n");
                
            //继续: 请你算出他们的   总和 平均值
                int sum=0;
                for(int i=0;i<10;i++){
                    sum += aa[i] ;
                }
                printf("sum=%d average=%lf\n",sum,sum/10.0);
                
                
        ## 定义两个数组,你从键盘 给一个数组输入数据.
            将数据拷贝到另一个数组.打印出
            
                int aa[10] = {23,43,52,63,78,90,93,99,100,105};
                int bb[10];
            
                for(int i = 0;  i< 10 ;  i++){
                    bb[i]=aa[i];
                }
        
        #######        已知数组 
            int aa[  ] = {23,43,52,63,78,90,93,99,100,105};
            
            //请你设计算法,将他逆序:
            ##方法1:
                //    i = 0  1 2 3 4 ...    cnt/2 -1
                //    交换     a[i]      aa[cnt-i-1]
                
                int cnt =  sizeof(aa)/sizeof(aa[0]) ;
                
                for(int i=0;i<cnt/2 ;i++ ){
                    int temp=aa[i];aa[i]=aa[cnt-i-1];aa[cnt-i-1]=tmp;
                }
                
                for(int i=0;i<cnt;i++){
                    printf("%d ",aa[i]);
                }
                printf("\n");
            ## 方法2:
                int aa[  ] = {23,43,52,63,78,90,93,99,100,105};
                int cnt =  sizeof(aa)/sizeof(aa[0]) ;
                int i=0; int j=cnt-1;
                
                
                while(  i< j ){
                    int tmp = aa[i];aa[i]=aa[j];aa[j]=tmp;
                    i++;j--;
                }
                for(int i=0;i<cnt;i++){
                    printf("%d ",aa[i]);
                }
                printf("\n");    
    

    ### 字符串数组##############
          "hello world"  == "hello world\0"                编译器帮你添加伪0
          
          
          char str[16];        
          char str[] = {'h','e','l','l','o',' ','w','o','r','l','d' };
                    这是一个#字符数组#,因为没有\0,不是字符串 
          char str[] = {'h','e','l','l','o',' ','w','o','r','l','d','\0' };
          char str[] = "hello world";        是上面的简写方式.
          char str[16] = "hello world";
          
            访问某个字符:  str[i]
          
          printf("string %s  %s ","hello world", str);
          
         C语言中,使用  字符数组来存储 字符串. 
         字符串是一个特殊的 字符数组,特殊在 尾部\0.
         
        
        
    练习:  已知一个字符串 char str[] = "hello world";    
        请你求出他的长度?
        
    
        char str[] = "hello world";    
        int i; // 0  1 2 3 4 ..
        i=0;
        while( str[i] ) {
            i++;
        }
        printf("string length=%d\n", i);
        
    练习:1. 已知字符串 char str[] = "hello world";
        请你 将他们转换为 大写 "HELLO WORLD"
            
            int i = 0;
            char str[] = "hello world";
            while(str[i]){
                if(str[i]>='a' && str[i] <= 'z'){
                    str[i] -= 32;
                }
                i++;
            }
            
            

        2.已知字符串 char str[] = "123 hello world 345 ";
                请你 将他们转换为 大写 "123 HELLO WORLD 345 "
                
                
        3. 已知字符串, char str[] = "Hello world";
            请将他们的大写转小写 小写转大写
            
        
        4. 将  char str[] = "I love china";  修改为 "anihc evol i"
        
            char str[] = "I love china";
            int i=0; int j=0;
            
            while( str[j] ){
                j++;
            }
            //代码到这里了,说明了什么    str[j]=='\0'
            j--;
        
            while( i<j ){
                int temp= str[i];str[i]=str[j];str[j]=temp;
                i++; j--;
            }
            printf("%s\n",str);
            
    

#######    二维数组 ##########
    一维数组:  int aa[10] = {23,243,44,23,45,24,53,23,23};
    二维数组:  int aa[5][6];        计算机会分配 5*6个 int单元,他们是连续的空间.
    
    
    定义赋初值:
        int aa[10]   = {23,243,44,23,45,24,53,23,23};
        int aa[3][4] = {   {1,2,3,4},  {23,23,4,2}, {432,23,123,24}     }
        
        int aa[3][4] = {     {1,2,3}, 23,23,4,2,   432,23              };        其中 1 2 3 0放第一行 ,23,23,4,2 第二行
        
    访问某个成员:
        aa[行号][列号]            行号: 0--- ,列号:0----
        
        for(int i=0;i<3;i++){        //i 行 = 0 1 2
            //针对第i行,扫描列 
            for(int j=0;j<4;j++){    //j列 0  1 2 3
                printf("%d ",aa[i][j]);
            }
            printf("\n");
        }
    
    二维数组的应用:
        #字符串数组#
        
            字符串:         它是字符构成的数组.
            字符串数组:        字符构成的数组 数组,    其实就是个 字符的 二维数组
                    {'x','i','a','o','w','a','n','g','\0'}
            
        char names[4  ]     [16      ] =    { "xiaowang","xiaohong","xiaoming","xiaoli"  };
        char names[可以省略][不可省略] =    { "xiaowang","xiaohong","xiaoming","xiaoli"  };    
            
            
            char str[] = "dawang";        printf("%s",str);
            char name[][] = {}            printf("%s", name[i=0 1 2 3]  );
        
    
        遍历字符串数组:
            char names[4]     [16] =    { "xiaowang","xiaohong","xiaoming","xiaoli"  };
            for(int i=0;i<4;i++){
                printf("%s ",names[i]);
            }
            
    ## 二维数组练习题:
    
        使用二维数组,打印如下方阵 
            *
            * *
            * * *
            * * * *                    特性: i>=j   *       i<j ' ' 
                    
    
    
        char aa[4][4];
        
        for(int i=0;i<4;i++){
            for(int j=0;j<4;j++){
                aa[i][j] =    (i>=j )?  '*' :' ';
            }
        }
    
        for(int i=0;i<4;i++){
            for(int j=0;j<4;j++){
                printf("%c",aa[i][j])  ;
            }
            printf("\n");
        }
        
    练习:
            
            *****
            *   *
            *   *
            *****


    练习1:
        给定一个字符串 char str[] = "good doog";
        判断他是不是回文;
        
        int i=0;int j=0;
        
        while(str[j]!='\0'){
            j++;
        }
        j--;    //str[j] == \0
        
        while(i<j){
            if( str[i] != str[j]){
                break;        //
            }
            i++;j--;
        }
        //  i<j,中途终止,不相等            
        if(i<j){
            printf("not equal\n");
        }else {
            printf("equal\n");
        }
        return 0;
        
        
        
        
    练习2: 
        完成字符串的拷贝 
        char src[] = "hello world";
        char dst[16];
        
        int i  = 0;
        
        while( src[i] ){
            dst[i]=src[i];
            i++;
        }
        // src[i]== \0
        dst[i]=src[i];    //最后一步, 将dts尾部置零
        printf("%s\n"dst);
        
        
    练习3:
        比较两个字符串,是否相等            
        
        char str1[] = "hello world";
        char str2[] = "hello wor"
        
        
        方法1: 先求 各自的长度,长度不一致  go out 
                长度一致,以此比较...
    
    
        方法:
        int i=0;
        while(  str1[i]  && str2[i]  ){
            if( str1[i]-str2[i] ){
                break;
            }
            i++;
        }
        //如果长度一致        str1[i] == str2[i] == \0         相等的
        //如果长度不一致    只有一个 为0                     不相等 
        if(  str1[i] - str2[i]   ){
            printf("不相等\n");
        }else {
            printf("相等\n");
        }
        
    
    挑战:
        将一个字符串 char str1[] = "12345";
        转换为 整数. 
        
        int aa = 12345;
        char str1[] = "12345";
        int sum = 0;        //最终结果
        int i=0;
        while( str1[i] ){
            char v = str1[i] - '0';        
            sum = sum*10;
            sum+=v;
            i++;
        }
        printf("sum=%d\n",sum);
        
        
##########        函数     function ###############
    function: 功能    
    函数:    在英文中,函数翻译为 function             rst=sin(30)
    
    函数,就是为了完成 特定功能的代码段
    
        int len  = strlen( "hello world." );
        int size = sizeof(aa);                //暂时可以认为是函数
        int maxa = min(45,65.25);
        
        
    函数构成:    
        返回值类型  函数名   (类型1 参数1, 类型2 参数2 )
        {
            对输入的参数进行加工,将结果返回
            return 结果;
        }
    
        int  main( int argc, char argv[][] )
        {
            加工
            return 0;
        }
        
        
        // mymax函数,对输入的 两个int类型数据 a,b进行加工,输出 最大值(int)
        int mymax(int a,int b)
        {
            if(a>b){
                return a;        //return 结束当前函数,并返回结果.
            }else {
                return b;
            }
            
            return -1;
        }
        
        
        int main(void)
        {
            int c = mymax(55,66);
            printf("max c is %d\n",c);
            int d = mymax(1001,1098);
            printf("max d is %d\n",d);
        }
        
        
    特殊的函数:
        有的函数 没有返回值
        
            sleep(1);                 void sleep(int sec);
                                         sleep(int sec); 如果不写,默认 int
        有的函数 不需要参数 
            int r = rand();            int rand(void);
    
        有的函数,既没有 有没有 
            
            sleep1s();                void sleep1s(void)
    
    
    小练习:
        实现一个 abs函数    ,返回 绝对值   
                int myabs(int val)
                {
                    int rst = val>0?val:-1*val;
                    return rst;
                }
        求三个数据最小值    
                int mymin(int a,int b,int c)
                {
                    int min;
                    
                    if(a>b){        //a 被淘汰
                        if(b>c){
                            min=c;
                        }else {
                            min=b;
                        }
                    }else {
                        if(a>c){
                            min =c;
                        }else {
                            min =a;
                        }
                    }
                    return min;
                }
                int main(void)
                {
                    printf("the min is %d\n", mymin(45,64,23)  );
                    return 0;
                }
            
            
        ##数组的传参:                    参数,argument   传递: pass ,    传参     pass argument
            char str[] = "hello world";
            实现函数,求取字符串长度
            
            char str[] = "hello world";
            int mystrlen(  char s[] )                            //##参数定义 数组 
            {
                int i = 0;
                for( ; s[i];i++ ){    //while(s[i]){
                                            //    i++;
                }                        //}
                return i;
            }
            int main(void)
            {
                printf("stringlen = %d\n", mystrlen (  str )    );    //###传参的时候,只需要指定数组名即可
            
            }
            
            
            练习:    判断字符串是不是回文    如果是返回1,否则返回0
                int str_loop(char s[])
                {
                    int i=0;int j=0;
                
                    while(s[j] ){
                        j++;
                    }
                    j--;
                    
                    while(i<j){
                        if(s[i] != s[j]){
                            break;
                        }
                        i++;j--;
                    }
                    if(i<j){
                        return 0;
                    }else {
                        return 1;
                    }
                }
            
                int main()
                {
                    char str[] = "good doog";
                    int cc = str_loop(   str );
                    if(cc){
                        printf("yes");
                    }else {
                        printf("no");
                    }
                
                }
                
            ##练习:    
                int  str2num(char str[])
                {
                    int sum = 0;        //最终结果
                    int i=0;
                    while( str[i] ){
                        char v = str[i] - '0';        
                        sum = sum*10;
                        sum+=v;
                        i++;
                    }                    
                    return sum;        
                }
                
                int main(void)
                {
                    char string[16];
                    
                    printf("input num:");
                    scanf( "%s", string );         
                    
                    int num = str2num(string);
                    printf("number = %d\n");
                    return 0;
                }
                
    ### 函数的 声明####
        函数可以 先定义,后使用.              即,在使用函数之前 定义函数            main函数要在文件的尾部
        函数如果 先试用,在定义.                gcc在编译的时候,会给出警告    implict declare function of xxxxx :
        
                int str2num(char s[]);        //声明该函数, 告诉编译器, 发现先试用后定义的情况也不要给警告
                
                int main()
                {
                    str2num("123456");        //gcc编译的时候,发现没有定义....
                }
                
                int str2num(char s[])
                {
                    ....
                }
                
    ###        全局变量 和    局部变量            
        #include <stdio.h>
        
        int gg = 10086;
        
        int main(void)
        {
            int gg = 5;
            printf("gg=%d\n",gg);        使用的肯定是 局部变量 
        
        }
        
        
        局部变量:   定义在 {}内部的变量称之为 局部变量.  有效范围在{}内部 
                        在函数执行的时候,才分配空间.  当退出函数理解释放空间.
                        
        全局变量:    定义在{}外部的变量,称为  全局变量     有效范围是 全局    
                        在程序执行之处就已经分配空间,程序结束才释放空间.        周期是全局的
        
        
        
        
    ###### 形参 和实参 #############
        实参: 实际存在的参数,确定数值的参数
        形参: 形式上的参数,值也是不定的
        
        
        ### 实现函数,交换两个变量的值
        void myswap(int ax, int bx)
        {
            int tmp=ax; ax=bx; bx=tmp;
        }
        
        int main(void)
        {
            int aa = 56; int bb = 78;
            myswap(aa, bb);                    ### 形参的改变 没有影响到实参
            printf("aa bb=%d %d\n",aa,bb);
            return 0;
        }
    
    
    
    
        再来一个:
        void myadd(int ax)
        {
            ax++;
        }
        int main(void)
        {
            int aa=55;
            myadd(aa);
            printf("aa=%d\n");
        }
        
        
        如何通过修改形参来影响实参呢:    数组的传参
        
            void array_swap(int arr[] )                //C语言禁止 函数内定义函数:  嵌套定义
            {
                int tmp= arr[0];arr[0]=arr[1];arr[1]=tmp;
            }
        
            int main()
            {
                int aa[2] = {12,34};                //通过调用函数 完成 aa[0]  aa[1]的交换
                array_swap(aa);
                printf("aa[0 1] = %d %d\n",aa[0],aa[1]);
                return 0;
            }
            
            发现通过 数组的传递,可以改变实参的值.    


##########  变量和常量##########
        变量: variable 可变的量  
                int aa = 55;    aa=543; aa=23243;
        常量: const   恒定不变的量.    
        
            const double PI = 3.141592654;        定义的时候,使用const修饰变量,则 该变量是#只读#的.
                一般const修饰变量, 定义就必须初始化.
                PI=3.14;            非法,编译器报错.    error: assignment of read-only variable ‘PI’
            
        


#######  宏定义        #define             ################
    宏替换
    

    #define PI    (+3.1415926)                        // # 预处理指令,告诉gcc 以后遇到 PI这个符号,统统都替换为 后面的##东西##
    #define PRINT     printf("nice hello world\n") 
    #define SECOND_PER_YEAR        365*24*60*60

    double circle_square(double r)
    {
        PRINT ;
        return PI*r*r;
    }

    double circle_length(double r)
    {
        PRINT;
        return PI*2*r;
    }
    double circle_xxx(double r)
    {
        PRINT;
        return PI*xxx ;
    }


    ######宏参数/宏函数    #######
    
    求最大值
        #define     MAX(A,B)        A>B?A:B 
        
        
        int cc =    MAX(5,6);        
        被替换为    5>6?5:6   

        #define  MAX3(A,B,C)        A>B?   A>C?A:C         :    B>C?B:C    

        printf("max is %d \n",  MAX3(33,44,55)   );

    乘法:
        #define    MUL(A,B)                A*B 

        int cc =  MUL(5+3,6+8);               5+3*6+8        发现有问题
        解决方法:
            #define    MUL(A,B)                (A)*(B) 
                       MUL(5+3,6+8)            (5+3)*(6+8)
        
        
        #define   ADD(A,B)            (A)+(B)
                  ADD(5+1,6+2)*2      (5+1)+(6+2)*2
                  
        解决方法:
                #define   ADD(A,B)            ( (A)+(B)  )
                        ADD(5+1,6+2)*2      ( (5+1)+(6+2)*2   )
        
        
        
        #define MAX(A,B)        ( (A)>(B)?(A):(B)  )
                MAX(++a,8);        ( (++a)>(8)?(++a):(8)  )
            出问题了,没有解决方法,不要 这么用 
        
        
    宏函数使用注意事项:
        1.所有的 参数,都必须使用 () 裹起来 
        2.整个宏函数必须被() 裹起来 
        3.参数不要++ -- 
        
    

    宏参数 和 函数的区别:
        都是代码段,可以实现相同的功能
        
        区别:
            #define MAX(A,B)    ((A)>(B)?(A):(B))
            
            int max(int a,int b)
            {
                return a>b?a:b;
            }
        
            main()
            {
                int cc = max(344,234);
                max(45,234); max(123,253);
                
                int dd = MAX(234,2344);//  替换为int dd = ((A)>(B)?(A):(B)); 
                MAX(234,2323); MAX(234,3532);
            }
             

        1. 函数参数返回值都有类型,宏函数没有类型
        2. 函数调用会发生跳转,而宏函数本地直接替换执行,执行效率高.
        3. 函数多次调用,只有一份代码.宏函数在每次使用处展开一份,消耗空间.


编译过程:
            gcc
    main.c --------> main.out
            编译

        编译是一个很复杂的过程:
            1. 预处理          
                代码中 有#开头的,都是在预处理阶段进行的.    gcc 会对你的代码进行改动.
                1) 将所有的 宏定义替换为 具体的内容 
                    #define PI     3.14
                2) 将#include 包含的头文件,在当前文件 中展开.
            
            2. 编译 
                将C语言翻译为汇编语言
                
                符号语言
            
            3.汇编 
                将汇编语言转换为 二进制语言 
                
            4.链接
                    main.c  aa.c   bb.c cc.c dd.c .......
                      |         |     |   ....                    预处理
                    main.x  aa.x   bb.x                          
                      |      |      |                        编译 
                    main.S   aa.S  bb.S .....
                      |      |      |                        汇编 
                    main.o   main.o bb.o                         很多二进制文件 
                        \    |      /
                         \   |    /                            链接, 将众多二进制文件合并为一个 可执行文件.
                            main.out
                            
                            


练习:
    实现一个函数,比较两个字符串是否相等. 如果相等返回0,否则返回 其他值
        int mystrcmp(char s1[],char s2[])
        {
            int i=0;
            
            while(s1[i] && s2[i]){
                if(s1[i] - s2[i] ){
                    break;                //中止 
                }
                i++;
            }
            //代码到这里,   1) 两个都不为空,不相等  2) 只有一个为空,不相等  3) 两个都为NULL 
            return s1[i]-s2[i];
        }
    

    实现一个函数,完成字符串的拷贝:
    
        char s1[]="hello wrold";
        char s2[18];
        
        mystrcpy(s2,s1);
        printf("s2 = %s\n",s2);
        
        
        void mystrcpy(char dst[],char src[])
        {
            int i = 0;
            while(src[i]){
                dst[i]=src[i];
                i++;
            }
            //结束了,为什么 src[i]==NULL
            dst[i] = '\0';
        }
        
    显示一个函数,完成字符串的拼接
        "hello world" = "hello "+"word"
        
        
        char s1[]="world";
        char s2[32] = "hello ";
        mystrcat(s2,s1);
        printf("%s\n",s2);
        
        
        void mystrcat(char s2[],char s1[])
        {
            int i=0,j=0;
            //j移动到s2的\0位置
            while( s2[j] ){
                j++;
            }
            //j已经抵达 对应位置
            
            while(s1[i]){
                s2[j] = s1[i];
                i++;j++;
            }
            // s1[i]已经抵达了 \0位置,但是  s2[j]还没有赋值
            s2[j]='\0';
        }
        
        int main(void)
        {
        
            char s1[]="world";
            char s2[32] = "hello ";
            mystrcat(s2,s1);
            printf("%s\n",s2);
        }
                            

  • 9
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值