精华内容
下载资源
问答
  • mysql复合语句

    2021-02-06 14:28:14
    1 索引create index ondrop index on2 视图 view 虚表 存放某一个查询的结果create view 视图名称 as select 语句对视图进行操作1查询 select * from 视图名称更新操作时候需要判断以下条件1 不能有聚集函数 不能有 ...

    1 索引

    create index on

    drop index on

    2 视图 view 虚表 存放某一个查询的结果

    create view 视图名称 as select 语句

    对视图进行操作

    1查询 select * from 视图名称

    更新操作时候需要判断以下条件

    1 不能有聚集函数 不能有 group by

    create view v1 as select max(age) from emp

    2 不能有子查询

    3 不能有计算结果列

    2 执行 更新操作

    insert

    delete

    update

    3 drop view 视图;

    -----------------------------------------

    复合语句 (必须放在存储过程或者函数里面)

    存储过程 实现特定功能的一组SQL语句 根据需要可以传参数

    语法

    BEGIN

    复合语句

    END;

    #1 声明变量

    # 声明变量 declare 变量名称 变量类型

    # 变量声明必学写在 其他复合语句之前

    declare i int; #定义一个int的变量i

    declare name varchar(20);#定义一个varchar的变量name

    #声明变量的时候指定默认值

    declare address varchar(50) default '无锡';

    #2 赋值

    set i = 100;

    set name = '蔡亦超';

    #3 分支语句

    #1) if-else-then

    if i > 90 then

    # 结果设置为 优

    set result = '优';

    end if;#注意结束

    if i > 90 && i <100 then

    # 结果设置为 优

    set result = '优';

    else if i > 80 then

    set result = '良';

    else

    set result = '及格';

    end if;

    end if;#注意结束

    # 2) case when

    select

    address as '目的地',

    case address

    when '重庆' then '火锅'

    when '海口' then '水果'

    when '贵阳' then '丝娃娃'

    end

    as '特产'

    from emp;

    BEGIN

    declare emp_id int; # 临时变量存放id

    declare emp_salary int;# 临时变量存放salary

    declare done int default false;# done表示还有没有数据

    BEGIN

    循环

    #1)while 循环

    declare i int;

    declare sum int;

    declare temp_salary int;

    # 获取当前工资 存入 temp_salary

    select salary into temp_salary from emp where id=1001;

    while temp_salary <1000000 do

    set temp_salary = temp_salary +5000;

    end while;

    # 更新最新的工资

    update emp set salary = temp_salary where id=1001;

    #2)loop 循环 temp_salary=1000000

    loop1 : loop # loop1 是循环的标签

    set temp_salary = temp_salary -2000;# 循环的内容

    if temp_salary > 500000 then

    iterate loop1; # temp_salary > 500000 继续循环 让代码再回到loop1位置

    end if;

    leave loop1; # 结束循环

    end loop;

    update emp set salary = temp_salary where id=1001;

    #3)repeat

    set i=1;

    set sum=0;

    repeat # 重复执行以下代码

    set i = i+1;

    set sum = sum +i;

    until i>10 # 直到 i>10为止

    end repeat;

    END

    BEGIN

    #异常处理

    # 1 sqlstate 标准SQL的错误代码 5

    展开全文
  • 复合语句以整个块为单位,能够用在任何一个单独语句可以用到的地方,并且在复合语句中还可以嵌套复合语句 在使用复合语句时要注意,复合语句为局部变量创造了一个作用域,该作用域为程序的一部分,在该作用域的某...

    Java初步语法(4)之流程控制

    复合语句:

    分为:if条件语句、switch多分支语句、

    概念:以整个块区为单位的语句,所以又称为块语句。

    复合语句中的每个语句都是从上到下被执行。复合语句以整个块为单位,能够用在任何一个单独语句可以用到的地方,并且在复合语句中还可以嵌套复合语句

    在使用复合语句时要注意,复合语句为局部变量创造了一个作用域,该作用域为程序的一部分,在该作用域中的某一个变量被创建并使用。如果在某个作用域外使用该变量则会出现错误。

    if条件语句分别分为三种语句结构,分别是:

    1.简单的if条件语句

    2.if……else语句

    3.if……else if多分支语句

    用途:用于告诉程序在某个条件成立的情况下执行某段语句,而在另一种情况下执行另外的语句。

    首先我们先来说一下最简单的 if条件语句

    语法如下;

     if(布尔表达式){
     语句序列
     }
    

    1. 布尔表达式:必要参数,表示最后返回的结果必须是一个布尔值。它可以是一个单纯的布尔变量或常量也可以是使用关系或布尔运算值的运算式。

    2. 语句序列:可选参数。可以是一条或者多条语句,当表达式的值为true时执行这些语句。若语句序列中仅有一条语句,则可以省略条件语句中的“{ }”

    注意:尽管if后边的复合语句只有一条可以省略“{ }”,但是为了增强程序的可能性最好不要省略。

    条件语句后的语句序列省略时,则可以保留外边的大括号,也可以省略大括号。然后在末尾添加“;”如下所示的两种情况都是正确的。

    Boolean b = false;
    if (b);
    Boolean b=false;
    if(b);
    

    if条件的执行过程如下:
    在这里插入图片描述

    2.if … else语句

    if ……else 语句是条件语句中最常见的一种形式,它会针对某种条件有选择地做出处理。通常表现为“如果满足某种条件,就进行某种处理,否则就进行另一种处理。

    语法如下:

    if(表达式){
    若干语句
    }
    else{
    若干语句
    }
    

    if后面“()”内的表达式的值必须是Boolean型的。如果表达式的值为true,则执行紧跟if语句的复合语句;如果表达式的值为false,则执行else后边的复合语句。if ……else语句的执行过程如下图:

    在这里插入图片描述

    注意:if……else可以用三元运算符简化:

     if(a>0)
         b=a;
     else
         b=-a;
    

    可以简写成

     b=a>0?a:-a;//a 是否大于零?如果a大于零就把a的值赋值给变量b,否则将-a的值赋值给b;
    

    3.if ……else多分支语句

    if ……else if多分支语句用于针对某一事件的多种情况进行处理。通常表现为“如果满足某种条件,就进行某种处理,否则如果满足另一种条件则执行另一种处理”如果两者都符合就执行首先满足的那个。

    语法如下:

      if(条件表达式1(Boolean1)){
     语句序列 1
     }
    else if(条件表达式2){
    语句序列2
    }
    else if(表达式n){
    语句序列n
    }
    

    1. 条件表达式1~条件表达式n;必要参数。可以有多个表达式组成,但是最后返回的结果一定要为Boolean类型。

    2. 语句类型:可以是一条或者多条语句,当条件表达式1为true时执行语句序列1,当条件表达式2的值为true时,执行语句序列2,以此类推。当省略任意一组语句序列时,可以保留其外边的{ },也可以将“{ }”替换为“;”

    Switch多分支语句:

    主要用于检测一个变量是否符合某个条件,如果不符合再用另一个值来测。

    当然 这种功能用if语句也可以实现,例如:

      If(grade==’a’){
     System.out.println(“true”);
     }
    
     If (grade==’b’){
    System.out.println(“false”);
    }
    

    当然这个程序相较于switch语句笨重的多。

    Switch语法如下:

     switch(表达式)
     {
    case  常量值1;
    语句块 1
    [break;]
    ……
    case  常量值n;
    语句块 n
    [break;]
    default:
    语句块 n+1
    [break;]
    }
    

    限制条件:switch语句中表达式的值必须是整形、字符型或字符串类型。

    注意:witch语句中,case语句后常量表达式的值可以是整数,但绝不可以是实数。

    展开全文
  • if类型的分支语句

    2021-08-08 21:14:18
    if分支语句 做任何事情都需要遵循一定的规则,例如:一个公司的员工全月都无缺勤记录,符合条件则可获得该月份的满勤奖金。程序设计也是这样的,例如某个条件成立执行A流程,否则执行B流程等等。 C语言程序设计...

    if分支语句

    做任何事情都需要遵循一定的规则,例如:一个公司的员工全月都无缺勤记录,符合条件则可获得该月份的满勤奖金。程序设计也是这样的,例如某个条件成立执行A流程,否则执行B流程等等。

    C语言程序设计中的流程控制,可以分为三种结构模型:顺序结构、分支结构和循环结构。

    图4-1 分支语句的三种结构模型

    单分支if语句

    单分支if语句将原本的顺序结构,当某个条件成立时多执行一个额外语句模块。

    单分支语句采用if…的格式编写:

    if(表达式)

    {语句块一}   //符合表达式执行的代码       

    如图4-1所示,如果表达式的值为true(真),则执行语句块一中的语句;如果表达式的值为false(假),则不执行语句块一中的语句。例如,公司制定的员工销售提成规则为:

    公司的员工的销售提成为每销售一件提成20元,如果销售量大于100件则额外奖励500元。

    [例4-1]测试单分支if语句

    #include<stdio.h>

    int main()

    {

    int n = 0,sal = 0;

    puts("请输入你本月的销售量:");

    scanf("%d",&n);

    sal = n*20;

    if(n>100)

    sal += 500;

    printf("你本月的销售提成为:%d\n",sal);

    return 0;

    }

    将以上代码输入到C语言编译器中进行编译、运行并查看打印结果:

    a)输入大于100的数、100或小于100的数,观察打印出的销售提成中是否包含额外的500元奖励;

    b)最好能在调试模式下单步执行,观察输入不同的销售量之后程序是否进入单分支语句执行。

    双分支if语句

    双分支if语句采用if…else…的格式编写:

    if(表达式)

    {语句块一}    //符合表达式执行的代码

    else

    {语句块二}    //不符合表达式执行的代码

    如图4-1所示,当条件成立时(表达式的值为真)执行语句块一内的代码,否则(表达式的值为假)执行语句块二内的代码。双分支语句必须在两个语句块之中二选一,而不可以多选或不选。

    例如,公司制定的员工销售提成规则为:若每月销售量小于100件,每销售一件提成20元;如果每月销售量大于等于100件,每销售一件提成30元。

    [例4-2]测试双分支if语句

    #include <stdio.h>

    int main()

    {

    int n = 0,sal = 0;

    puts("请输入你本月的销售量:");

    scanf("%d",&n);

    if(n<100)

    sal = n*20;

    else

    sal = n*30;

    printf("你本月的销售提成为:%d\n",sal);

    return 0;

    }

    将以上代码输入到C语言编译器中进行编译、运行并查看打印结果:

    a)输入大于100的数、100或小于100的数,观察打印出的销售提成中是按照什么比例计算的;

    b)最好能在调试模式下单步执行,观察输入不同的销售量之后程序进入哪个分支语句执行。

    多分支if语句

    多分支if语句采用if…else if…else…的格式编写:

    if(表达式一)

    {语句块一}    //符合表达式执行的代码

    else if(表达式二)

    {语句块二}    //符合表达式执行的代码

    else if(表达式三)

    {语句块三}    //符合表达式执行的代码

    ……

    else

    {语句块n}    //符合表达式执行的代码

    例如,公司制定的销售提成规则是多级制:

    a)每月销售量小于100件每件提成20元;

    b)每月销售100-200件则每件提成25元;

    c)每月销售200-300件则每件提成30元;

    d)每月销售达到超过300件则每件提成40元。

    [例4-3]测试多分支if语句

    #include <stdio.h>

    int main()

    {//&&是而且的意思,当两边的条件同时为真结果才是真

    int n = 0,sal = 0;

    puts("请输入你本月的销售量:");

    scanf("%d",&n);

    if(n<100)

    sal = n*20; //销售100件以内,每件按20元提成

    else if(n>=100 && n<200)

    sal = n*25; //销售100-200件,每件按25元提成

    else if(n>=200 && n< 300)

    sal = n*30; //销售200-300件,每件按30元提成

    else

    sal = n*40; //若能销售300件以上每件按40元提成

    printf("你本月的销售提成为:%d元\n",sal);

    return 0;

    }

    将以上代码输入到C语言编译器中进行编译、运行并查看打印结果:

    a)输入小于100、200、300以及大于300等不同范围的数,观察打印的提成结果是按照什么比例计算的;

    b)最好能在调试模式下单步执行,观察输入不同的销售量之后程序进入哪个分支语句执行。

    如图4-2所示:

    多分支语句依次判断表达式的值,当出现某个表达式的值为真时则执行其对应的语句,然后跳到整个if语句之外继续执行后面的程序。 如果所有的表达式均为假则执行语句n,然后再继续执行后续程序。

    图4-2 多分支if语句的执行流程

    根据以上对else if多分支语句图解和推理,你是否已经发现了例4-3中有一些代码是多余的呢?对,第一个条件表达式的n<100,else已经否定了第二个表达式中n<100的可能了。else if语句应该拆开来看,else是跟前一个条件表达式中的if配对的,然后在剩余的补集内再找出<200的子集。依次类推,我们可以这样简化例4-3中的代码。

    [例4-4]简化else if多分支语句

    #include <stdio.h>

    int main()

    {

    int n = 0,sal = 0;

    puts("请输入你本月的销售量:");

    scanf("%d",&n);

    if(n<100)

    sal = n*20; //销售100件以内,每件按20元提成

    else if(n<200)

    sal = n*25; //销售100-200件,每件按25元提成

    else if(n< 300)

    sal = n*30; //销售200-300件,每件按30元提成

    else

    sal = n*40; //若能销售300件以上每件按40元提成

    printf(“你本月的销售提成为:%d元\n",sal);

    return 0;

    }

    将以上代码输入到C语言编译器中进行编译、运行并查看打印结果:

    a)输入小于100、200、300以及大于300等不同范围的数,观察打印的结果是否与例4-3完全一致;

    b)最好能在调试模式下单步执行,观察输入不同的销售量之后程序进入哪个分支语句执行。

    复合语句

    无论是单分支、双分支或多分支的if分支语句,每个条件表达式通常情况下只能控制到其后第一个分号为止。如果某个条件表达式需要控制到其后的多行语句,则需要使用一对大括号{}将要控制的多行语句括起来。

    这种由一对大括号括起来的多行语句,就叫做复合语句。复合语句,也就是由多行语句组合而成的代码模块,经常被用于各种分支和循环语句当中参与程序流程管理。

    对例4-4程序做增强功能的改造,每个分支成立不但要打印提成金额而且还要打印出A-D的评分等级。

    [例4-5]测试复合语句的用法

    #include <stdio.h>

    int main()

    {

    int n = 0,sal = 0,ch=0;

    puts("请输入你本月的销售量:");

    scanf("%d",&n);

    if(n<100)

    {

    ch = 'D';

    sal = n*20;

    }

    else if(n<200)

    {

    sal = n*25;

    ch = 'C';

    }

    else if(n< 300)

    {

    sal = n*30;

    ch = 'B';

    }

    else

    {

    ch = 'A';

    sal = n*40;

    }

    printf("你本月的销售成绩是%c级,提成为:%d元\n",ch,sal);

    return 0;

    }

    将以上代码输入到C语言编译器中进行编译、运行并查看打印结果:

    a)输入小于100、200、300以及大于300等不同范围的数,观察打印的销售成绩与提成金额是否正确;

    b)最好能在调试模式下单步执行,观察输入不同的销售量之后程序进入各个分支语句的执行情况。

    展开全文
  • 分支语句和循环语句

    千次阅读 2021-11-19 12:40:04
    1、分支语句:if和switch 2、循环语句:while循环、for循环和do while循环 3、go to语句 1.什么是语句? C语句可分为以下几类; ①表达式语句 ②函数调用语句 ③控制语句 ④复合语句 ⑤空语句 1、对于①...
     
    
    生活中的任何一件事情无非是以下情景之一:
    生活中的事情无非要么是这三种的一种,要么是这三种中的几种的组合。
    • 1、分支语句:if和switch
    • 2、循环语句:while循环、for循环和do while循环
    • 3、go to语句

    1.什么是语句?

    C语句可分为以下几类;
    ①表达式语句
    ②函数调用语句
    ③控制语句
    ④复合语句
    ⑤空语句
    1、对于①表达式语句:如
    int a = 10;
    int b = 20;
    int c = 30;
    c = a + b;//是表达式语句,表达式构成的语句
    //注:语句里一定有分号,表示这个语句结束了

    2、对于②函数调用语句,如:

    如调用一个printf函数:
    printf("hehe\n");//函数调用语句
    3、对于 ④复合语句:
    把语句复合在一起写的语句。
    4、对于⑤空语句:
    空语句就是一个分号。如:
    int main()
    {
            ;//空语句
            return 0;
    }
    //空语句也是语句
    5、对于③控制语句:(今天学习)
    控制语句用于控制程序的执行流程,以实现程序的各种结构式方式,它们由特定的语句定义符组成,C语言中有9种控制语句。
    可以分成以下三类:
    ⑴条件判断语句:if语句、switch语句;
    ⑵循环执行语句:do while语句、while语句、for语句;
    ⑶转向语句:break语句、goto语句、continue语句、return语句。

    2.分支语句(选择语句)

    2.1  if语句

    if语句的语法结构:
    if(表达式)
             语句;
    如果表达式为真,就执行语句;如果表达式为假,就不执行语句。
    什么是真,什么是假?
    C语言中规定:0是假,非0就是真。(只有0是假)
    • 双分支
    if(表达式)
           语句1;
    else
           语句2;
    如果表达式成立,执行语句1,如果表达式不成立,执行语句2,非此即彼。
    • 多分支:
    if(表达式1)
           语句1;
    else if(表达式2)
           语句2;
    else
           语句3;
    如果表达式1成立,就执行语句1,表达式1不成立,看表达式2是否成立,若表达式2成立就执行语句2,若表达式2不成立就执行语句3。只是选择语句1到语句3中的一条语句执行,不可能同时执行2个或3个语句。
    演示代码:
    #include<stdio.h>
    int main()
    {
         int age = 0;
         scanf("%d", &age);
          if (age >= 18)
                 printf("成年\n");
          return 0;
    }//输入>=18,即得:成年;<18,即没有输出结果。

    //双分支:

    #include<stdio.h>
    int main()
    {
          int age = 0;
          //scanf("%d\n", &age);//错误
          //scanf("%d ", &age);//错误
          //scanf("%d", age);//错误
          scanf("%d", &age);
          if (age >= 18)
                 printf("成年\n");
          else
                 printf("未成年\n");
          return 0;
    }
    注:if语句中可以没有else,只写一个if也可以。
    多分支:
     
    #include<stdio.h>
    int main()
    {
          int age = 0;
          scanf("%d", &age);
          if (age < 18)
                 printf("少年\n");
          else if (age >= 18 && age < 40)
                 printf("青年\n");
          else if (age >= 40 && age < 60)
                 printf("壮年\n");
          else if (age >= 60 && age < 90)
                 printf("老年\n");
          else
                 printf("老寿星\n");
          return 0;
    }
    其他的写法:
    #include<stdio.h>
    int main()
    {
          int age = 0;
          scanf("%d", &age);
          if (age < 18)
                 printf("少年\n");
          else if (age < 40)
                 printf("青年\n");
          else if (age < 60)
                 printf("壮年\n");
          else if (age < 90)
                 printf("老年\n");
          else
                 printf("老寿星\n");
          return 0;
    }//这种写法可以,但可读性不高。
    注"if(18<=age<40)"的这种写法会产生bug,语法没问题(可以编译),但运行逻辑有问题
    if():if后面一定要有圆括号,圆括号里可以是表达式也可以是变量,若是变量:
    #include<stdio.h>
    int main()
    {
            int age = 0;
            scanf("%d", &age);
            if (age)//圆括号里是age,是变量,此时不判断大小,只关注age里是否为0,若是0,就进不去了,若非0,则进去了。
            //若是if(age>18),圆括号里是表达式,判断大小,也会产生真或假的结果。
            //若放的是1,if(1);因为1永远为真,所以能进去
            {
            }
            return 0;
    }
    如果条件成立,要执行多条语句,如何使用代码块?
    什么是代码块?——就是{}大括号。
    else不知和谁匹配了,因为if的后面跟了两个语句, 默认情况下,if语句后面只能跟一条语句,把if后面的第二个代码删掉整个代码是没有问题的 。 当if语句后面跟多条语句时,必须加大括号{},否则语法是有问题的。
    一对大括号{}就是一个代码块。

    2.2悬空else

    如代码:
     
    什么都没有输出,为什么不打印haha?
    此时是else匹配的问题。
    else总是与最近的if语句匹配,而不是和对齐的那个if语句。所以else与if(b==2)匹配,但是第一个if(a==1)如果不进去的话,后面的if和else整体都没有机会进去了。因为后面的if和else是第一个if里面的内容。所以此时什么都没有打印。
    即else是和离它最近的if匹配的。
    如果让代码更清晰,加大括号即可。
    即:
    #include<stdio.h>
    int main()
    {
            int a = 0;
            int b = 2;
            if (a == 1)
            {
                   if (b == 2)
                           printf("hehe\n");
                   else
                           printf("haha\n");
            }
            return 0
    }

    或:

    #include<stdio.h>
    int main()
    {
            int a = 0;
            int b = 2;
            if (a == 1)
            {
                   if (b == 2)
                   {
                           printf("hehe\n");
                   }
                   else
                   {
                           printf("haha\n");
                   }
            }
            return 0;
    }
    增加了可读性和逻辑性。
    如果按需要也可以一个if和else相匹配。

    2.3if语句书写形式的对比

    代码书写的风格形式不一,影响代码的可读性。
    如:
    if(condition){
                  return x;
    }
    return y;
    //是差的代码风格。条件成立返回x,条件不成立返回y

    更改:

    if (condition)
    {
            return x;
    }
    else
    {
            return y;
    }
    常犯代码错误:
    #include<stdio.h>
    int main()
    {
            int a = 10;
            if (a = 5)//错误
            {
                   printf("hehe\n");
            }
            return 0;
    }//5
    应该是a==5,a=5是把5赋值给a,而因为a为5,是真,所以也会打印。
    注意:
    a = 5和5 = a是有区别的。a=5是把5赋值给a,5=a是a等于5
    a==5和5==a是一样的,都是a=5。
    当比较一个常量和一个变量比较是否相等时,把常量放到等号左边写出的效果更好。
    #include<stdio.h>
    int main()
    {
            int a = 10;
            if (5 = a)//报错
            {
                   printf("hehe\n");
            }
            return 0;
    }
    #include<stdio.h>
    int main()
    {
            int a = 10;
            if (5 == a)//正确:运行后没有输出
            {
                   printf("hehe\n");
            }
            return 0;
    }
    1、判断一个数是否为奇数:用if语句
    #include<stdio.h>
    int main()
    {
            int a = 0;
            scanf("%d", &a);
            //if (a % 2 == 1)//更好
        //if(a/2 !=0)//错误
            if(a % 2 != 0)//√
            //if(1 == a%2)//运行也正常,结果也对。但这种写法没必要。
            //if(1 = a%2)//报错
            {
                   printf("奇数\n");
            }
            return 0;
    }
    注:若写成:1 == a%2可以没必要。因为a%2是表达式,本身是不能被赋值的。
    变量放在左边时可能会赋值,a%2这个表达式本身是不能赋值的,即使只写一个等号程序也会报错。
    2、输出1-100之间的奇数:
    #include<stdio.h>
    int main()
    {
            int a = 0;
            scanf("%d", &a);
            return 0;
    }
    方法:产生1-100之间的数字,然后挑出想要的奇数。
    用while循环:
    #include<stdio.h>
    int main()
    {
          int i = 1;
          while (i <= 100)
          {
                 printf("%d ", i);
                 i += 2;
          }
          return 0;
    //}这里循环了50次,打印了50次
    用if语句:
    #include<stdio.h>
    int main()
    {
            int i = 1;
            while (i <= 100)
            {
                   if (i % 2 == 1)
                           printf("%d ", i);
                   i++;//每次都+1
            }
            return 0;
    }//循环了100次,判断了100次

    2.4switch语句

    switch语句也是一种分支语句,常常用于多分支的情况。
    switch语句的语法形式:
    switch(整型表达式)
    {
          语句项;
    }
    其中语句项是一些case语句:
    case  整型常量表达式;
             语句;
    case是一种可能,案例。
    #include<stdio.h>
    int main()
    {
          int day = 0;
          scanf("%d", &day);
          if (1 == day)
                 printf("星期1\n");
          else if (2 == day)
                 printf("星期2\n");
          //……是多分支的情况
          return 0;
    }

    转化为switch语句:

    #include<stdio.h>
    int main()
    {
          int day = 0;
          scanf("%d", &day);
          switch (day)//day是变量,一会会输入变量值,输入几(scanf中取地址的对象)就会决定switch圆括号中是几
    //switch后面的圆括号是表达式,表达式值是几就会进入switch语句执行case几
         {
          case 1://有空格
                 printf("星期1\n");
          case 2:
                 printf("星期2\n");
          case 3:
                 printf("星期3\n");
          case 4:
                 printf("星期4\n");
          case 5:
                 printf("星期5\n");
          case 6:
                 printf("星期6\n");
          case 7:
                 printf("星期天\n");
    
          }
          return 0;
    }

    //根据day是几就从case几进去,但是还需要跳出来,用break终止

    #include<stdio.h>
    int main()
    {
            int day = 0;
            scanf("%d", &day);
            switch (day)
            {
            case 1:
                   printf("星期1\n");
                   break;
            case 2:
                   printf("星期2\n");
                   break;
            case 3:
                   printf("星期3\n");
                   break;
            case 4:
                   printf("星期4\n");
                   break;
            case 5:
                   printf("星期5\n");
                   break;
            case 6:
                   printf("星期6\n");
                   break;
            case 7:
                   printf("星期天\n");
                   break;
            }
            return 0;
    }

    //输入几就从case几进去,遇到break就跳出switch语句。

    注意:
    1、switch()中圆括号中的表达式一定是整型表达式或表达式结果一定是整型。
      2、每个cas选项后面一定是整型常量表达式,因为day是几就会从case几进去,day是整型,这儿必须也是整型。
     
    不能是小数。(浮点型)浮点型不能用switch语句。
     
    不能是变量。
    即case后main的语句必须是整型,还得必须是常量表达式。
    switch后面的day的用处:day是几就从case几进去,根据day的值进行选择。day可以是变量。day是放在switch后面的,switch后面要求必须是整型表达式,并没有说是常量表达式。
    switvh  (整型表达式)
    case   整型常量表达式
    3、switch是如何实现分支的?
    • ⑴实现分支的进口:switch后面的表达式是几就从case进去。
    • ⑵分支的出口:break,如果没有break就会继续向下执行,遇到break就跳出来了。
    若是:输入1-5,输出的是:“weekday”;
    输入6-7:输出的是:“weekend”;
    //#include<stdio.h>
    //int main()
    //{
    //      int day = 0;
    //      scanf("%d", &day);
    //      switch (day)
    //      {
    //      case 1:
    //             printf("weekday\n");
    //             break;
    //      case 2:
    //             printf("weekday\n");
    //             break;
    //      case 3:
    //             printf("weekday\n");
    //             break;
    //      case 4:
    //             printf("weekday\n");
    //             break;
    //      case 5:
    //             printf("weekday\n");
    //             break;
    //      case 6:
    //             printf("weekend\n");
    //             break;
    //      case 7:
    //             printf("weekend\n");
    //             break;
    //      }
    //      return 0;
    //}

    写法√,但啰嗦

    #include<stdio.h>
    int main()
    {
            int day = 0;
            scanf("%d", &day);
            switch (day)
            {
            case 1:
            case 2:
            case 3:
            case 4:
            case 5:
                   printf("weekday\n");
                   break;
    //不管case是1-5的几就输出weekday,不管从那个case进来都会往后走,没有遇到break就不会停下来。
            case 6:
            case 7:
                   printf("weekend\n");
                   break;
            }
            return 0;
    }

    只要case的后面不加break,可以有多个case选项执行同一行代吗。

    case的后面不一定必须加break,根据逻辑需要。

    2.5default字句

    若上述例子输入9就会没有什么输出,此时反馈一下会更好。如输入9反馈输入错误。
    加default;
    default的作用是默认,如果前面的case都不能匹配的话,那就走default,输入9的话,case1-case7都不能匹配,执行default。
     
    default用来处理默认选项的,若输错了什么都不想处理,则屏蔽掉即可。
     
    default可以放到前面,无所谓顺序。
     
    注意:
    case的后面先是空格,最后有冒号。
    编程的好习惯:在每个switch语句中都放一条default子句,甚至可以在后边再加一个break。
     
    从哪进去取决于switch后面表达式的值,什么时候跳出去取决于有没有遇到break,没有遇到break就一直顺序的往下执行。

    3.循环语句

    • while循环
    • for循环
    • do while循环

    3.1while循环

    if语句形式:
    if(条件)
       语句;
    while语法形式:
      while(表达式)
         循环语句;
    表达式成立,执行循环语句,循环语句执行完后,再上来判断表达式,如果表达式成立,会继续执行循环语句。
    while语句的执行流程:
     
     

    3.1.1while语句中的break和continue

    break在while循环中的作用:
    在循环中只要遇到break,就停止后期的所有循环,直接终止循环。
    所以:在while中的break是用于永久终止循环。
     
    continue在while中的作用:
    continue是用于终止本次循环的,也就是本次循环中continue后边的代码不会再执行,而是直接跳转到while语句的判断部分,进行下一次循环的入口判断。
    (continue继续,其作用是:跳过continue后面的代码直接去判断部分去看是否要继续循环。)
    再练习几个代码:
    #include<stdio.h>
    int main()
    {
            int ch = 0;
            while ((ch = getchar()) != EOF)
                   putchar(ch);
            return 0;
    }

    geychar: 

    //#include<stdio.h>
    //int main()
    //{
    //      int ch = 0;
    //      while ((ch = getchar()) != EOF)//获取字符,放到ch里去,再拿这个表达式的结果与EOF相比,
    即若获取的字符放到ch里不等于EOF就进入循环里
    //             putchar((ch));
    //      return 0;
    //}

    //getchar()函数的用法

    #include<stdio.h>
    //EOF
    int main()
    {
            int ch = getchar();//getchar获得的字符就会放到ch里去
            printf("%c\n", ch);//打印字符用%c,把ch打印在屏幕上
            return 0;
    }
    //getchar是获取字符,如'a'是一个字符,为什么要用ch来接收?
    //有2个原因:第一,getchar返回的是字符,字符本身的存储值是代表这个字符的ASCII值,
    //如代表'a'的ASCII值是97,97是一个整数,把它放到整型里不会出错。即写int ch(因为字符本身是由ASCII值表示它的)
    //第二:放int ch的原因:getchar读取失败的时候或者遇到文件结束标志或错误时,会返回EOF,而不放char ch,char是一个字符,只有8个比特,而#define EOF是-1,-1是一个整数,需要4个字节的空间才能存得下,(一个整型放一个char是不合适的)
    //所以把读取的字符放到ch里去。
    //运行结果:如输入a,按enter,则输出a(打印的即就是这个a)
    打印不仅仅可以用printf函数
    getchhar是从键盘上输入一个字符,
    putchar与getchar是一对函数。
    getchar—获取(输入)一个字符
    putchar—输出一个字符
     
    这几行代码可以用scanf和printf替代
    所以getchar和putchar是针对字符的输入和输出,可以完全用scanf和printf函数替代。
    scanf要比getchar功能全,printf要比putchar功能全。getchar和putchar一次只能操作一个字符,只是操作字符的,用于读字符和写字符。
    #include<stdio.h>
    int main()
    {
            int ch = 0;
            while ((ch = getchar()) != EOF)
    //getchar()读取一个字符,先放到ch里:是ch=getchar(),这个表达式:(ch=getchar())的结果就是ch的结果
    //如果这个表达式的结果不等于EOF,说明读取还没有结束,在正常读取,如读了一个字符a,不等于EOF它就入while,然后把这个字符打印出来
                   putchar(ch);
            return 0;
    }
    //运行时输入什么就会输出什么,没有结束进程,直到按Ctrl+z,因为ctrl+z可以让getchar读取结束,返回EOF。
    这样的代码有什么用呢?为什么会有这样的代码?
    这样结构的代码是有一定意义的。
    如一个场景:
     
    程序问题:还没有输入Y/N就弹出来下一步了。
     
    scanf是用来读取数据的,数据来源于我们键盘的输入
    但是scanf不是直接从键盘拿取数据的,中间有输入缓冲区,scanf的工作原理是:scanf先去看输入缓冲区是否有东西,如果有东西scanf就拿走了,如果看到输入缓冲区里什么东西都没有,那scanf就会等待,从键盘上敲出:abcdef,为了让scanf获取需要敲enter,相当于换行\n,即其实在键盘上敲出的是:abcdef\n,即相当于把“abcdef\n”放到输入缓冲区。此时scanf读到东西了,读到的是:abcdef,而\n是为了把这个信息放到input里敲的,所以scanf拿走了:abcdef,缓冲区里还有东西,printf函数打印“请确认密码(Y/N)”,接下来getchar工作,getchar获取信息也是通过输入缓冲区,它看缓冲区有没有东西可以用,如果有它就拿走了,如果没有它就等待从键盘上输入时获取,结果当getchar看输入缓冲区时,输入缓冲区中还有个“\n”,getchar就把"\n"拿走了,并把\n放到ch里去,ch不等于Y,则不走if走else,即打印出确认失败。
    所以getchar把\n拿走了,它有东西可拿,所以它没有等待就:没有输入Y或N就出来确认失败了。当输入缓冲区什么都没有,它才会等待,让键盘输入信息放到缓冲区里。
    要想达到想要效果,当getchar读取信息时,输入缓冲区什么都没有时,它才会等待我们输入Y/N,所以需要在getchar从输入缓冲区拿取数据时把输入缓冲区中的\n清理掉。
    处理:
     
    这样写还是有问题。
    输入abcdef+空格+hehe,输出的还是:请确认密码(Y/N):>确认失败。
     
    为了让“abcdef hehe”进入输入缓冲区,还按了回车(\n),
    scanf(“%s”,……)读取字符串的时候,遇到空格就结束了,后面的空格,hehe和\n都没读走,只读走了abcdef。
    第一个getchar可能拿走了一个空格,后面就还有hehe\n,所以第二个getchar看到输入缓冲区里有东西,所以没有等待就确认失败了。所以应该第一个getchar把\n之前的东西都拿走才行,所以上面的写法已经不够用了,需要换一种写法,用while循环。
     
    (如果读取的字符串有空格,可能用的是gets函数。)
    即: 
    看代码2:
    #include<stdio.h>
    int main()
    {
            int ch = 0;
            while ((ch = getchar()) != EOF)//getchar获取一个字符放到ch里去,不等于EOF说明读到了一个正常字符
            {
                   if (ch < '0' || ch > '9')//读到的这个字符如果小于或者大于字符9,那就不是数字字符了,就进入continue
                           continue;//continue后上去再进入while再读取一个字符,如果不在这个数字范围,就再上去读,直到读到的数字字符在这个范围(0-9)内,就putchar把它打印
                   putchar(ch);
            }
            return 0;
    }

    //ASCII表中字符0-9是连续的。数字范围(对应的ASCII值)是48-57。即当ASCII值小于48或大于57的为非数字字符。

    //运行时输入字符a,没有输出什么,输入数字字符0-9中的任何一个,都会输出对应的结果。
    //不想输出时,按ctrl+z就停止了。
    这里输入的4被理解为字符4,因为用getchar的方式获取的。所以这里4是字符,不是数字4。获取的字符4放到ch里是ASCII值52。
    注意:一定要带括号:
    ⑴while((ch=getchar())!= EOF)√
    ⑵while(ch=getchar()!= EOF
    ⑴意思是获取的字符放到ch里,拿ch=getchar()这个表达式结果与EOF相比看是否相等
    ⑵意思是getchar获取的字符若不等于EOF为假,所以getchar()!=EOF的结果为0,0赋给ch
    此处体现了操作符的优先级。

    3.2for循环

    for循环用到的最多。
    #include<stdio.h>
    int main()
    {
            int i = 1;//①循环变量的初始化
            
            while (i <= 10)//②循环的判断部分
            {
                   printf("%d ", i);
                   i++;//③调整部分
                           
            }
            return 0;
    }//1 2 3 4 5 6 7 8 9 10

    //以上是影响循环的三部分,也是主要修改和调整的对象

    //当循环复杂时,这三部分会越来越分离,会容易出错。代码增加了风险。
    //for循环完美解决了这种情况。
    for循环的语法形式:
    for(表达式1;表达式2;表达式3)
       循环语句;
    • 表达式1
    • 表达式1为初始化部分,用于初始化循环变量的。
    • 表达式2
    • 表达式2为条件判断部分,用于判断循环是否终止。
    • 表达式3
    • 表达式3位调整部分,用于循环条件的调整。
    在屏幕上打印1-10的数字,用for循环表达:
    #include<stdio.h>
    int main()
    {
            int i = 0;//创建循环变量,但此时的赋值没有意义,因为下面写for循环时,for后面的圆括号第一步写的就是初始化才决定i从几开始。
            for (i = 1; i <= 10; i++)
            {
                   printf("%d ",i);
            }
            return 0;
    }//1 2 3 4 5 6 7 8 9 10

    //for循环有变量,用循环变量值的变化来代表循环

    //i=1<=10,进来打印,然后i++,++调整完之后看是否<=10,如果是再打印,再++,以此类推。
    //注:循环体只有一条语句(printf)时,for循环时可以控制的,若循环体中有多条语句,一定要加大括号{}。
    for语句的执行流程:
    表达式1(初始化),进入表达式2,根据判断条件的真假看是否能进入表达式3,如果条件判断为真,执行循环体,进入表达式3(调整语句)。
    后来整个循环是:表达式2成立—执行循环体—进入表达式3—表达式2成立—执行循环体—进入表达式3—……表达式为假,循环停止。
    #include<stdio.h>
    int main()
    {
            int i = 0;
            for (i = 1; i <= 10; i++)
            {
                   if (5 == i)
                   {
                           break;
                   }
                   printf("%d ", i);
            }
            return 0;
    }//1 2 3 4

    for循环中的break作用—永久地终止循环

    for循环中的continue作用—跳过continue后面的代码
     
    #include<stdio.h>
    int main()
    {
            int i = 0;
            for (i = 1; i <= 10; i++)
            {
                   if (5 == i)
                   {
                           continue;
                   }
                   printf("%d ", i);
            }
            return 0;
    }//1 2 3 4 6 7 8 9 10

    3.2.1for语句中的循环控制变量:

    建议:
    1、不可在for循环体内修改循环变量,防止for循环失去控制
    #include<stdio.h>
    int main()
    {
    	int i = 0;//i是循环变量
    	for (i = 0; i < 10; i++)
    	{
    		printf("hehe\n");
    	}
    	return 0;
    }//10个hehe

    而:

    #include<stdio.h>
    int main()
    {
        int i = 0;
        for (i = 0; i < 10; i++)
        {
            i = 0;//不好的习惯
            printf("hehe\n");
        }
        return 0;
    }//陷入死循环,无数个hehe


    是因为在循环体中改变了循环变量。每次进入循环体都会把i变成0,总小于10,即循环控制受到了影响。所以:不要在循环体中对循环变量指手画脚。

    2、for语句的循环控制变量的取值采用“前闭后开区间”写法

    #include<stdio.h>
    int main()
    {
        int i = 0;//i是循环变量
        for (i = 0; i <= 9; i++)
        {
            printf("hehe\n");
        }
        return 0;
    }//10个hehe

    i<10和i<=9都是10个hehe

    int i=0;

    //前闭后开的写法

    for(i=0;i<10;i++)
    {}
    //两边都是闭区间
    for(i=0;i<=9;i++)
    {}
    因为i=0是闭区间开始的,i<=9也是闭区间, 建议写成i<10开区间,即写成前闭后开的形式。因为可以增加代码的可读性,容易理解。

    3.2.2一些for循环的变种

    #include<stdio.h>
    int main()
    {
    	for (;;)
    	{
    		printf("hehe\n");
    	}
    	return 0;
    }//陷入死循环

    所以:

    for循环的初始化,判断,调整三个部分都可以省略
    中间的判断部分如果省略,意味着判断恒为真,就构成了死循环。
    如果条件允许,不建议省略for循环的三个表达式,因为省略时会带来不可预测的问题。

    如:

    #include<stdio.h>
    int main()
    {
    	int i = 0;
    	int j = 0;
    	for (i = 0; i < 3; i++)
    	{
    		for (j = 0; j < 3; j++)
    		{
    			printf("hehe\n");
    		}
    	}
    	return 0;
    }//9个hehe

    工作原理:

    当前的这个代码for循环是嵌套的,把里面的for当成外面的for的循环体。

    i=0<3,进入第二个for循环,执行完再i++,然后i如果还是<3则进入第二个for循环,再i++……

    一共进行三次循环;而第二个for循环也是循环,i是0进入它的时候,它要彻底执行完,i是1时它又要彻底执行完,i是2的时候也要执行完,即每一次的外面的循环进入里层的循环要循环三次,所以3*3=9次。

    而:如果省略掉初始化部分:

    #include<stdio.h>
    int main()
    {
    	int i = 0;
    	int j = 0;
    	for (; i < 3; i++)
    	{
    		for (; j < 3; j++)
    		{
    			printf("hehe\n");
    		}
    	}
    	return 0;
    }//3个hehe

    i=0<3,进入第二个for循环,第二个循环要走:j=0<3,打印一次hehe,j上去++变成1,j=1<3,打印第二次hehe,j++后变成2,j=2<3打印第三次hehe,j++后变成3,j=3!<3,则跳出代码块,上去i++,(刚刚i是0)i++后变成1,i=1<3进入第二个for循环,因为初始化部分没有改j(是一个;分号)j刚刚是3,所以现在j=3!<3,所以直接就跳出代码块了,再上去进行i++,i=2<3,再进入第二个for循环,因为j还是3!<3,则又跳出代码块,再上去i++,i=3!<3就跳出大的代码块,循环终止。即整个过程中就打印了3次hehe。

    若使用多余一个变量控制循环:

    #include<stdio.h>
    int main()
    {
    	int x, y;
    	for (x = 0, y = 0; x < 2 && y < 5; x++, y++)
    	{
    		printf("hehe\n");
    	}
    	return 0;
    }

    for循环这里初始化部分写了2个表达式,整个循环可以用2个变量来控制。
    有两个条件来控制循环,根据需要是可以的。

    如代码题:问循环多少次?

    #include<stdio.h>
    int main()
    {
        int i = 0;
        int k = 0;
        for (i = 0, k = 0; k = 0; i++, k++)
            k++;
    }//运行成功没有输出

    0次

    注意:这里的for循环中的判断条件是:k=0;而一个等号是赋值,不是判断。k=0这个表达式的结果是0,0为假,则这个循环一次都不会进去。(表达式的结果是作为判断条件的,为假就不会进入循环。)

    3.3do…while()循环

    3.3.1do语句的语法:

    do
            循环语句;

    while(表达式);

    这里的do没有作任何的判断,直接干,执行循环语句,做完之后再判断(while中的表达式)

    使用do…whoile循环在屏幕上打印1—10:

    #include<stdio.h>
    int main()
    {
    	int i = 1;
    	do
    	{
    		printf("%d ", i);
    		i++;
    	} while (i<=10);
    	return 0;
    }//1 2 3 4 5 6 7 8 9 10

    3.3.2执行流程

     do while语句的循环体至少执行一次。

    #include<stdio.h>
    int main()
    {
    	int i = 1;
    	do
    	{
    		if (5 == i)
    			break;
    		printf("%d ", i);
    		i++;
    	} while (i<=10);
    	return 0;
    }//1 2 3 4 

    break只能跳出一层循环,只能跳出自己的循环。

    #include<stdio.h>
    int main()
    {
    	int i = 1;
    	do
    	{
    		if (5 == i)
    			continue;
    		printf("%d ", i);
    		i++;
    	} while (i<=10);
    	return 0;
    }//1 2 3 4

    此时4后面一直闪,说明程序并没有结束,它一直在等待,等待的原因是死循环,其实这时程序很忙,它一直在执行,只不过它陷入死循环了。

    continue为什么会造成本次的死循环?因为continue会跳过本次循环后面的代码,当i为5时,continue跳过了printf和i++,然后到判断:5符合<=10,再上去,进入循环,i还是等于5,这个过程中i没有机会变成6,7,8,9,10这样的数字,所以导致代码进入死循环了。

    3.3.3 do语句的特点

    循环至少执行一次,使用的场景有限,所以不经常使用。

    (循环至少一次的时候才使用)

    3.4练习

    1、计算n的阶乘:

    思路:

    假设n是5,计算5的阶乘,那么要产生1,2,3,4,5这些数字,然后乘在一起即可。

    则若计算n的阶乘:要产生1,2,3,4……n这些数字,然后相乘即可。

    第一步:输入n

    第二步:产生1—n的数字,累计乘在一起。

    第三步:打印

    #include<stdio.h>
    int main()
    {
    	int n = 0;
    	scanf("%d", &n);//输入n,假设n为5
    	//产生1-n(1-5)的数字,用循环
    	int i = 0;
    	int ret = 1;
    	for (i = 1; i <= n; i++)
    	{
    		ret = ret * i;//ret产生累计乘的效果
    	}
    	printf("%d\n", ret);
    	return 0;
    }//输入5,输出120

    写代码时把n=5带入好梳理思路。

    注意:输入的数字不能太大,比如100,这样输出会出错。100的就阶乘太大了。

    long类型甚至long long类型也不行,存不下。

    2、计算1!+2!+3!+……+10!

    用上一题中的把n想象成2算出一个ret,把n想象成n成3算成一个ret,把每次算出的ret在累积加在一起就可以求出1的阶乘加2的阶乘加3的阶乘加……的和,即在刚刚的代码上再套上一种循环即可。

    #include<stdio.h>
    int main()
    {
    	int n = 0;
    	int i = 0;
    	int ret = 1;
    	int sum = 0;
    	for (n = 1; n <= 3; n++)
    	{
    		for (i = 1; i <= n; i++)
    		{
    			ret = ret * i;
    		}
    		sum += ret;
    	}
    	printf("%d\n", sum);
    	return 0;
    }//15,正确答案是9

    代码出问题了,调试。

    注意:每次进入第二个for循环 i 都是初始值为1,不是延续之前的。

    调试时前面都正确,问题出现在当计算 n=3的阶乘,应该是ret = 1*1*2*3 , 而不是ret = 2*1*2*3 , 即ret有初始值,不像第二个for循环中的 i 那样。所以调整代码为:

    #include<stdio.h>
    int main()
    {
    	int n = 0;
    	int i = 0;
    	int ret = 1;
    	int sum = 0;
    	for (n = 1; n <= 3; n++)
    	{
    		ret = 1;
    		for (i = 1; i <= n; i++)
    		{
    			ret = ret * i;
    		}
    		sum += ret;
    	}
    	printf("%d\n", sum);
    	return 0;
    }//9

     因为每一次算阶乘的时候都是从1开始向上乘的:

    ret*1
    ret*1*2
    ret*1*2*3
    ret*1*2*3*4

    同时也发现这个代码是可以优化的:前面相同的就可以不用再相乘了。

    #include<stdio.h>
    int main()
    {
    	int n = 0;
    	int i = 0;
    	int sum = 0;
    	int ret = 1;
    	for (n = 1; n <= 3; n++)
    	{
    		ret = ret * n;
    		sum += ret;
    	}
    	printf("%d\n", sum);
    	return 0;
    }//9

    3、在一个有序数组中查找具体的某个数字n。(讲解二分查找)

    看出关键词:有序数组   查找

    思路:

    第一步:定义一个有序数组

    第二步:查找其中某一个字符

    (怎么查找呢?—在数组中,且是有序数组中—用数组的下标,0-9是这10个元素的下标,只要把这10个元素的下标和7比一下就可以了)

    #include<stdio.h>
    int main()
    {
    	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
    	//这个数组是有序的,是递增的。
    	int k = 7;
    	int i = 0;
    	for (i = 0; i < 10; i++)
    	{
    		if (arr[i] == k)
    		{
    			printf("找到了,下标是%d\n", i);
    			break;
    		}
    	}
    	if (i == 10)
    	{
    		printf("找不到\n");
    	}
    	return 0;
    }//找到了,下标是6

    这个算法可以优化:因为这个数组最坏情况下需要循环10次,即若数组有n个元素,则最坏情况下要循环n次,增加了算法的时间复杂度。

    查找过程:

    猜中间,再判断——成半的缩小查找范围。

    1的下标是0,10的下标是9,0和9的平均值:(0+9)/2=4,以4为下标找到元素5,5是找到的中间元素,5比要找的中间元素小,所以被查找范围变成6-10,6的下标是5,10的下标是9,(5+9)/2=7,以7为下标的元素是8,找到的元素是8,8比要找的元素7大,说明要找的元素在8的左边,所以被查找范围变成6-7,(5+6)/2=5,以5为下标锁定的元素是6,找到的元素6比要找的元素7小,说明要找的元素在6的右边,所以被查找范围是7,7的左下标和右下标都是6,(6+6)/2=6,以6为下标锁定的元素是7,7和要找的元素7相比相等,说明已经找到,如果7都不是要找的元素说明就找不到了。

     即:每次都找一个范围的中间元素,若中间元素比要找的元素小,说明要找的元素在中间元素的左边,范围缩小到左边的范围(即查一次范围缩小一半)——折半查找算法或者说是二分查找算法。

    二分查找算法的思路:

    当前有一组有序数字1 2 3 4 5 6 7 8 9 10,在这组数字中找7,k=7,怎么找?

    这组数字的最左边left下标是0,最右边right下标是9,(0+9)/2=4,确定中间元素mid的下标是:4,即以4为下标锁定的元素是5,5是中间元素,5比要找的元素k小,5就不要找了,它已经比k小了,5左边包括5都不要找了,所以从5的右边开始找,所以范围变成了6-10,(第一次查找的范围是1-10,;第二次查找的范围是6-10)。新的左下标left是5,(5+9)/2=7,7作为下标锁定的元素是8,8是新的中间元素,要找的k比8小,所以在8的左边,所以范围是6-7(即第三次查找的范围是6-7),这次左下标不变,新的右下标right是7(元素8)(5+6)/2=5,以5为下标锁定的元素是6,6比要找的7(k)小,所以要找的元素在6的右边,本来找的范围是6-7,所以现在的范围只剩一个7了,(即第四次查找的范围是7),7的左右下标再算一次,7的左下标left是6,7的右下标right也是6,(6+6)/2=6,以6为下标锁定的元素是7,7恰好等于要找的7,如果7都找不到了就真的找不到了。

    这个过程中左下标一直在向右走,右下标在向左走,范围一直在缩小,如果左下标还小于右下标,说明中间还有元素可以查找,如果左下标等于右下标,说明中间只剩一个元素可以查找了,如果左下标大于右下标,说明交错了没有元素可以查找了,即查找停下来的时期判断。

    代码:

    int sz = sizeof (arr) / sizeof (arr [0] );

    是用来计算数组元素的方法,sizeof(arr)——数组名放到sizeof内部,算的是数组的总大小,单位是字节。(这个数组是:int arr[] = { 1,2,3,4,5,6,7,8,9,10 };数组中有10个元素,每个元素的类型是整型)所以sizeof(arr)算的是40。arr[0]指的是数组里的第一个元素,所以sizeof(arr[0])计算的是第一个元素的大小,是一个Int,是4个字节。所以40/4=10,sz=10,表示的是10个元素(注意这是可以通过计算得到的)

    元素个数sz-1=右下标right。

    上面阴影部分是一次二分查找。

    查找过程是:找到中间元素,中间元素与k比,找到新的范围
    查找结果是调整产生了新的下标,得到了新的范围(然后接下来是又要拿新的左右下标求中间元素的下标,以此类推)

    所以处理:循环
    循环条件:left只要还小于right说明中间还有元素可以被查找,left=right说明还有一个元素可以被查找,所以条件设为left<=right,这说明的是left和right中间还有元素可以被查找的,此时就进入循环进行二分查找。如果left大于right说明就找完了,就不可能找到了。

    因为只有一个条件,所以选择了while循环。

    #include<stdio.h>
    int main()
    {
    	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
    	int sz = sizeof(arr) / sizeof(arr[0]);
    	int k = 7;
    	int left = 0;
    	int right = sz - 1;
    
    	while (left <= right)
    	{
    		int mid = (left + right) / 2;
    		if (arr[mid] < k)
    		{
    			left = mid + 1;
    		}
    		else if (arr[mid] > k)
    		{
    			right = mid - 1;
    		}
    		else
    		{
    			printf("找到了,下标是:%d\n", mid);
    			break;//不想找了就跳出去
    		}
    	}
        //循环跳出来有两种情况:一种是找到了break跳出来,另一种是一直没有找到,但是不满足条件left<=right了,那就是找不到了。
    	if (left > right)
    	{
    		printf("找不到\n");
    	}
    	return 0;
    }//找到了,下标是:6

    注:一定会发生left>right这种情况的,否则这个循环跳不出去。

    折半查找/二分查找算法即是每查找一次,范围缩小一半。

    效率非常高,但条件苛刻:必须是有序的。

    4、编写代码,演示多个字符从两端移动,向中间汇聚。

    意思是:如果打印hello bit!!!!!!!,打印效果为:
    ################
    h##############!
    he############!!
    hel##########!!!
    hell########!!!!
    hello######!!!!!
    hello ####!!!!!!
    hello b##!!!!!!!
    hello bi#!!!!!!!
    hello bit!!!!!!!

    做法是?

    需要要打印的内容hello bit!!!!!!!和最开始的################。因为当要打印h##############!
    时,可以把第一个h拿下来放到第一#处,把最后一个!拿下来放到最后的#处,即内容变成h##############!了,再打印即可。当要打印he############!!时,把hello bit!!!!!!!中的e放到h##############!第二个#处,把hello bit!!!!!!!中的倒数第二个!放到h##############!中的倒数第二个人#处,即内容变成了he############!!再打印即可,所以准备hello bit!!!!!!!和################这两组数据,把hello bit!!!!!!!中的内容两端一对一对拿下来打印,直到它所有元素都拿下来即可。

    若一个数组为:char arr[ ] = "abc" ;

    则这个数组的内容是:a b c 和隐藏的\0这四个字符。这个字符串的长度是3。

                         a  b  c  \0

    对应的下标:0  1  2  (这个下标2的来源可以是字符串长度-1)

    求字符串长度用strlen函数。

     注:以上是一次打印。

    所以应该写成一个while循环:那while()圆括号中循环的条件是什么?

    当left<right时,说明还有中间元素没有拿下来。当left=right时最后一个元素拿下来,再让left++,right--,就交错了,一旦交错说明所有元素都被拿下来被打印了。所以这个条件一定是left<=right。

    注意:char arr1[] = "hello bit!!!!!!!";中"hello bit!!!!!!!"是一个字符串,拿这个字符串的内容用来初始化arr1数组的。这是一串数组。字符串是可以用来初始化数组的。

    #include<string.h>
    #include<stdio.h>
    int main()
    {
    	char arr1[] = "hello bit!!!!!!!";
    	char arr2[] = "################";
    	int left = 0;
    	int right = strlen(arr1) - 1;
    	while (left<=right)
    	{
    		arr2[left] = arr1[left];
    		arr2[right] = arr1[right];
    		printf("%s\n", arr2);
    		left++;
    		right--;
    	}
    	return 0;
    }//strlen是库函数,需要引头文件,是<string.h>

    一瞬间打印出来了,以至于看不到打印的过程,需要打印慢一些,所以用Sleep函数,打印一下Sleep一下。
    Sleep()是睡眠函数,是VS自动提供的函数,单位是毫秒。Sleep的使用需要有头文件,是<windows.h>,若写1000毫秒即1秒,其效果是:打印一下睡眠一秒,目的是可以看到打印的这个现象,变化的过程。

    注意:Sleep中S要大写。

    #include<string.h>
    #include<stdio.h>
    #include<windows.h>
    int main()
    {
    	char arr1[] = "hello bit!!!!!!!";
    	char arr2[] = "################";
    	int left = 0;
    	int right = strlen(arr1) - 1;
    	while (left<=right)
    	{
    		arr2[left] = arr1[left];
    		arr2[right] = arr1[right];
    		printf("%s\n", arr2);
    		Sleep(1000);
    		left++;
    		right--;
    	}
    	return 0;
    }

    注意:strlen是用来求字符串长度的,用sizeof求数组的大小时,求char arr[ ] = "abc"它的大小是4个字节而不是3,它包含\0字符。sizeof只关注大小,不会关注有没有\0的问题。所以在上例中如果用sizeof求字符串长度应该在int right = sizeof(arr[1])-2是减2的。

    所以在求字符串长度时:

    strlen不算\0这个字符的,而sizeof算。

    若在一行上两端移动向中间汇聚的效果更好:

    在Sleep(1000);休息1秒看见一下就清理掉,再打印,这用到一个函数system(),system()函数是用来系统命令的,在window系统中cls是清理屏幕的命令,C语言是如何执行这样的命令的呢?用system()函数,只要把这个cls命令放在圆括号中用双引号引起来传给system()函数它就可以直接执行这个系统命令,即这个cls就可以清理掉屏幕上的信息,达到清空屏幕的效果。

    所以打印一下,先休息一秒看见一下,再清理掉,清理后又立马打印,以此类推。这时给人的感觉就是一行上代码不断在缩进缩进。

    #include<string.h>
    #include<stdio.h>
    #include<windows.h>
    int main()
    {
    	char arr1[] = "hello bit!!!!!!!";
    	char arr2[] = "################";
    	int left = 0;
    	int right = strlen(arr1) - 1;
    	while (left<=right)
    	{
    		arr2[left] = arr1[left];
    		arr2[right] = arr1[right];
    		printf("%s\n", arr2);
    		Sleep(1000);
    		system("cls");
    		left++;
    		right--;
    	}
    	return 0;
    }

    打印后最后一次没了(屏幕上没有任何显示)因为最后一次打印完也停下来了,清理掉之后也没有

    再打印了。

    若想看到这个信息,可以最后再打印一下:

    #include<string.h>
    #include<stdio.h>
    #include<windows.h>
    int main()
    {
    	char arr1[] = "hello bit!!!!!!!";
    	char arr2[] = "################";
    	int left = 0;
    	int right = strlen(arr1) - 1;
    	while (left<=right)
    	{
    		arr2[left] = arr1[left];
    		arr2[right] = arr1[right];
    		printf("%s\n", arr2);
    		Sleep(1000);
    		system("cls");
    		left++;
    		right--;
    	}
    	printf("%s\n", arr2);
    	return 0;
    }

    即最终会看到:hello bit!!!!!!!

    5、编写代码实现,模拟用户登录情景,并且只能登录三次。(只允许输入三次密码,如果密码正确则提示登录成功,如果三次均输入错误,则退出程序。)

    代码演示:

    #include<stdio.h>
    #include<string.h>
    int main()
    {
    	int i = 0;
    	char password[20] = "";
    	for (i = 0; i < 3; i++)
    	{
    		printf("请输入密码:>");
    		scanf("%s", password);
    		if (strcmp(password, "123456") == 0)
    		{
    			printf("登录成功\n");
    			break;
    		}
    		else
    		{
    			printf("密码错误\n");
    		}
    	}
    	if (i == 3)
    	{
    		printf("三次密码均错误,退出程序\n");
    	}
    	return 0;
    }

    注意:

    char password [ ] = "" ; // 这样写代码是错误的。

    这样写代码带来的后果:因为数组的创建没有指定大小,则是根据后面的内容来创建的。而后面的内容是空字符串,里面只有:\0,即password这个字符串数组里面只放了一个元素就是\0,后面往这个数组里放密码会放不下会造成越界访问的情况。所以明确需要多大空间,给的初始化空间长度要符合使用的空间大小,要足够使用。如果需要20个空间,则:char password[20] = "";这样就开辟了20个字符的空间,即使后面是空字符串它也是20个字符的空间。

    包括整型数组也是这样:

    int arr [ ] = {0} ;只初始化一个元素0,那么它只有一个整型的空间。

    strmp->string compare字符串比较,专门用来比较字符串的。
    strcmp(字符串a,字符串b)
    strcmp比较返回的是0,说明两个字符串相等;
    返回大于0的数字,表示

    string1 greater than string2

    返回小于0的数字,表示

    string1 less than string2

    strcmp是字符串函数,是库函数,需要引头文件:<string.h>

    代码讲解:

    //最多输入三次,就最多循环三次密码,如果能提前结束就break跳出去。
    #include<stdio.h>
    #include<string.h>
    int main()
    {
    	int i = 0;
    	char password[20] = "";
    	//假设密码是字符串:"123456"
    	for (i = 0; i < 3; i++)
    	{
    		printf("请输入密码:>");
    		scanf("%s", password);//输入的密码放到哪呢?所以在前面定义数组。
    		//为什么这里的password不取地址呢?原因是password是数组名,数组名本来就是地址。
    		//密码输入进来后,假设正确的密码是字符串123456,那这时需要判断一下,看password里放的是不是123456
    		//判断:
    		//if (password == "123456")//比较判断password和123456是否相等,但这样判断错误。比较两个字符串是否相等,不能使用等号,而应该使用strcmp()这个函数,注这里字符串123456需要用双引号引起来。
    		if(strcmp(password,"123456")==0)//比较password和123456则把这两个字符串传进去就好了,中间用逗号隔开
    		{
    			//相等意味着密码输入正确就进来
    			printf("登录成功\n");
    			//登录成功就没有必要再登录再输入密码了,所以break跳出去。
    			break;
    		}
    		//如果密码输入错误,没有进入if就进入了else
    		else
    		{
    			printf("密码错误\n");//密码错误就上去再重新输入密码。输入次数在3次以内。
    		}
    		//而3次密码输入错误就要退出程序了。
    
    	}//break跳到这,不要输入密码了。
    	//密码三次都输入错误走到这。这时i=3。
    	if (i == 3)
    	{
    		printf("三次密码均错误,退出程序\n");
    	}
    	return 0;
    }

    结果演示:

     3.5猜数字游戏

    3.5.1最终代码展示

    #include<stdio.h>
    #include<stdlib.h>
    #include<time.h>
    void menu()
    {
    	printf("****************************\n");
    	printf("*******    1.play    *******\n");
    	printf("*******    0.exit    *******\n");
    	printf("****************************\n");
    }
    void game()
    {
    	int r = rand()%100+1;
    	int guess = 0;
    	while (1)
    	{
    		printf("猜数字:>");
    		scanf("%d", &guess);
    		if (guess < r)
    		{
    			printf("猜小了\n");
    		}
    		else if (guess > r)
    		{
    			printf("猜大了\n");
    		}
    		else
    		{
    			printf("恭喜你,猜对了\n");
    			break;
    		}
    	}
    }
    int main()
    {
    	int input = 0;
    	srand((unsigned int)time(NULL));
    	do
    	{
    		menu();
    		printf("请选择\n");
    		scanf("%d", &input);
    		switch (input)
    		{
    		case 1:
    			game();
    			break;
    		case 0:
    			printf("退出游戏\n");
    			break;
    		default:
    			printf("选择错误\n");
    			break;
    		}
    	} while (input);
    	return 0;
    }

    3.5.2代码逐步讲解:

    电脑随机生成一个数字,限定范围是1-100,

    猜数字,

    玩家猜大了,电脑会告诉:猜小了,

    玩家猜大了,电脑会告诉:猜大了,

    玩家猜对了,电脑会告诉:恭喜你,猜对了。

    若玩一把不过瘾则这个游戏不要退出,再玩一把,再玩一把,循环玩。

    所以选择用do while结构,因为游戏一运行起来就要看到菜单,即什么都不判断时就要先看到菜单。所以do while一上来(进入)就可以首先打印菜单,如果是while或for循环一上来就是判断才能进入。

    这样的思路代码演示:

    #include<stdio.h>
    void menu()
    {
    	printf("****************************\n");
    	printf("*******    1.play    *******\n");
    	printf("*******    0.exit    *******\n");
    	printf("****************************\n");
    }
    int main()
    {
    	int input = 0;
    	do
    	{
    		menu();
    		printf("请选择\n");
    		scanf("%d", &input);
    		switch (input)
    		{
    		case 1:
    			printf("猜数字\n");
    			break;
    		case 0:
    			printf("退出游戏\n");
    			break;
    		default:
    			printf("选择错误\n");
    			break;
    		}
    	} while (input);
    	return 0;
    }

    结果演示:

    代码讲解:

    #include<stdio.h>
    //写菜单:
    void menu()//menu返回类型是void,因为不需要返回
    {
    	printf("****************************\n");
    	printf("*******    1.play    *******\n");//功能玩游戏
    	printf("*******    0.exit    *******\n");//功能exit
    	printf("****************************\n");
    }//即一个菜单
    int main()
    {
    	int input = 0;
    	do
    	{
    		//打印菜单
    		menu();//简易的一个函数,在上面去写具体的菜单。写好菜单后只要走到这,它就会调用menu(),就会打印这个菜单
    		//接下来是选择,提示用户
    		printf("请选择\n");
    		//选择则给scanf输入,选择的数字需要存起来(scanf中取地址中的地址),则在上面创建变量input。(输入给个input)
    		scanf("%d", &input);
    		//玩家输入的是1呢还是0呢,还是其他,需要根据输入情况判断
    		switch (input)//判断的是input值
    		{
    		case 1://如果输入的是1,那就走case1
    			printf("猜数字\n");
    			break;
    		case 0://如果输入的是0,那就走case0
    			printf("退出游戏\n");
    			break;
    		default://如果输入的既不是1也不是0则走default
    			printf("选择错误\n");
    			break;
    		}
    		//break从这跳出来。此时do做完了,来到了while。
    	} while (input);//圆括号里是判断条件。
    //如果选择0,即input里放的是0,那就退出游戏,while中判断是0,0为假就停下来了。如果选择1,input里放的是1,while中判断是1即再上去玩,又有一次选择的机会。如果选错了也会上去,即选择的是其他非0的数字。
    //这里有分号,在while()圆括号后面有分号。
    	return 0;
    }
    

    注意:

    int input = 0;在do之前创建,不能在do之后创建。注意定义标识符的顺序。

    上面整个逻辑代码是对的,但唯一不好的是:“猜数字”不可能仅仅只是一句简单的话。

    game()函数是一个简易的函数,这个函数里面是玩游戏的整个逻辑。

    所以再写一个game()函数的整体代码演示为:

    #include<stdio.h>
    #include<stdlib.h>
    void menu()
    {
    	printf("****************************\n");
    	printf("*******    1.play    *******\n");
    	printf("*******    0.exit    *******\n");
    	printf("****************************\n");
    }//这一段代码打了一个包叫menu
    void game()//圆括号里面没有参数,返回类型是void,因为不需要返回。
    {
    	//game里边放的是猜数字游戏的代码:
    	//思路是:1、生成随机数
    	//        2、猜数字
    	//C语言中生成随机数的方法是:——rand()函数,生成随机数的范围是:0-RAND_MAX,RAND_MAX是多大呢?RAND_MAX选中,转到定义,得到:0x7fff是十六进制(32767是它的十进制),所以它的范围是0-32767
    //rand是库函数,需要引头文件<stdlib.h>
        int r = rand();
    	printf("%d\n", r);
    }//这一段代码打了一个包,叫game,这个包完成的任务是猜数字的过程
    int main()
    {
    	int input = 0;
    	do
    	{
    		menu();
    		printf("请选择\n");
    		scanf("%d", &input);
    		switch (input)
    		{
    		case 1:
    			game();
    			break;
    		case 0:
    			printf("退出游戏\n");
    			break;
    		default:
    			printf("选择错误\n");
    			break;
    		}
    	} while (input);
    	return 0;
    }

    这样写是有问题的

    运行结果每次都会产生相同的随机数。第一次运行是:第二次运行也是……以下:

    rand确实可以生成随机数,但只用rand会使游戏产生bug:几次生成的随机数是一样的。

    所以在调用rand函数之前要用srand去设置随机数的生成器。

    void srand( unsigned int seed );

    意思是:srand(接收的是整数),返回的是void。

    若是这样用:(错误)

    srand(1);
    int r = rand();
    printf("%d\n", r);

    srand圆括号里的值发生变化,rand生成的随机数就在发生变化。即为了生成一个随机数又需要输入一个随机数。

    所以只要给srand传一个经常发生变化的值就可以了。有些值是经常发生变化的,比如电脑上的时间。所以就可以把时间传给它,每一秒的时间都会产生一个数字。

    时间戳——任意一个时间都可以转换成一个秒数,这个秒数就称为时间戳,这样一个时间戳就可以转换成一个时间,所以时间在不断发生变化时,时间戳也在不断发生变化。任何一个时间都可以转换成一个时间戳。

    时间戳是怎么获取的呢?——是当前时间和计算机起始时间的差值转化成秒的这样一个数字。

    在C语言中获取时间戳要用到time()函数,time()函数是C语言的库函数,它能获取时间戳。

    time_t time( time_t *timer );

    time()函数的参数: time_t *timer      

    time_t *是一种指针,如果不想用这个参数,就传一个空指针:NULL

    time()函数返回的值是:time_t

    srand()函数void srand( unsigned int seed );需要的是unsigned int,这能匹配吗?

    ——可以。(time_t选中,转到定义,转到定义,发现:time_ttypedef __int64,time_t也是一种整型,是typedef来定义的一种整型值,即time_t本质上是64位的整型。所以就把time()函数的返回值作为srand的参数,只不过是需要强制类型转换一下强制转化为unsiged int 类型(因为srand函数需要的是unsiged int 类型的参数

    由:srand(time(NULL));——>强制类型转换后:srand((unsigned int)time(NULL));

    time()是库函数,需要引头文件:<time.h>

    #include<stdio.h>
    #include<stdlib.h>
    #include<time.h>
    
    void menu()
    {
    	printf("****************************\n");
    	printf("*******    1.play    *******\n");
    	printf("*******    0.exit    *******\n");
    	printf("****************************\n");
    }
    void game()
    {
    	//srand(23);错误,在rand函数之前调用srand,圆括号里传的参数随便给一个整数
    	srand((unsigned int)time(NULL));//time()函数调用时需要传一个空值NULL,此时time()函数就返回一个时间戳
    	//这句话是在设置随机数的生成器
    	int r = rand();
    	printf("%d\n", r);
    }
    int main()
    {
    	int input = 0;
    	do
    	{
    		menu();
    		printf("请选择\n");
    		scanf("%d", &input);
    		switch (input)
    		{
    		case 1:
    			game();
    			break;
    		case 0:
    			printf("退出游戏\n");
    			break;
    		default:
    			printf("选择错误\n");
    			break;
    		}
    	} while (input);
    	return 0;
    }

    结果:

     产生问题:当按的太快时,两次的随机值生成的一样——生成的不够随机

    srand((unsigned int)time(NULL));//这句话是在设置随机数的生成器,但是在整个程序中只要设置一次就可以了。

    若设置在:

    void game()
    {
        srand((unsigned int)time(NULL));
        int r = rand();
        printf("%d\n", r);
    }

    设置在这里(game玩游戏的过程中),就会玩一次游戏就设置一次,没有必要频繁设置。

    因为主函数只用调用一次,do while中是玩游戏,所以把“srand((unsigned int)time(NULL));”放到主函数中。这时无论多快生成的数字都是随机的——这才是rand,srand函数的正确打开方式。

    正确代码演示:

    #include<stdio.h>
    #include<stdlib.h>
    #include<time.h>
    
    void menu()
    {
    	printf("****************************\n");
    	printf("*******    1.play    *******\n");
    	printf("*******    0.exit    *******\n");
    	printf("****************************\n");
    }
    void game()
    {
    	int r = rand();
    	printf("%d\n", r);
    }
    int main()
    {
    	int input = 0;
    	srand((unsigned int)time(NULL));
    	do
    	{
    		menu();
    		printf("请选择\n");
    		scanf("%d", &input);
    		switch (input)
    		{
    		case 1:
    			game();
    			break;
    		case 0:
    			printf("退出游戏\n");
    			break;
    		default:
    			printf("选择错误\n");
    			break;
    		}
    	} while (input);
    	return 0;
    }

    结果演示:

     现在生成的数字是0—32767,若想生成0—100的数字则:

    把int r = rand();——>变成:int r = rand()%100;

    把生成的数字模上100,(一个大于100的数字%100,它的余数范围是0-99)即生成的数字是0-99,再加1,int r = rand()+1;即范围变成了1-100。这时就绝对不可能随机出现大于100的数字了,因为已经设置好算法了。

    #include<stdio.h>
    #include<stdlib.h>
    #include<time.h>
    
    void menu()
    {
    	printf("****************************\n");
    	printf("*******    1.play    *******\n");
    	printf("*******    0.exit    *******\n");
    	printf("****************************\n");
    }
    void game()
    {
    	int r = rand()%100+1;
    	printf("%d\n", r);
    }
    int main()
    {
    	int input = 0;
    	srand((unsigned int)time(NULL));
    	do
    	{
    		menu();
    		printf("请选择\n");
    		scanf("%d", &input);
    		switch (input)
    		{
    		case 1:
    			game();
    			break;
    		case 0:
    			printf("退出游戏\n");
    			break;
    		default:
    			printf("选择错误\n");
    			break;
    		}
    	} while (input);
    	return 0;
    }

    结果演示:

     接下来就不打印数字,而是猜数字了:

    提示猜数字——输入数字(这时就需要把输入的这个数字存起来,所以在上面创建变量guess,即把输入的这个数字放到guess里了)——判断,如果(猜的数字)输入的值<刚刚的r,说明猜小了,则提示猜小了;如果guess>r,则提示猜大了;如果刚好等于,则提示:恭喜你,猜对了。——用的是If语句,需要的是反复猜,则猜数字的这个过程需要写个循环体,就写while(1),不断的猜。猜对了就从break跳出去。——这是完整的实现逻辑。

     所以代码演示为:

    #include<stdio.h>
    #include<stdlib.h>
    #include<time.h>
    
    void menu()
    {
    	printf("****************************\n");
    	printf("*******    1.play    *******\n");
    	printf("*******    0.exit    *******\n");
    	printf("****************************\n");
    }
    void game()
    {
    	int r = rand()%100+1;
    	int guess = 0;
    	while (1)
    	{
    		printf("猜数字:>");//提示玩家猜数字,让玩家输入数字
    		scanf("%d", &guess);//把玩家输入的数字存起来,存到guess中。
    		if (guess < r)//判断,r是上面生成的随机数
    		{
    			printf("猜小了\n");
    		}
    		else if (guess > r)
    		{
    			printf("猜大了\n");
    		}
    		else
    		{
    			printf("恭喜你,猜对了\n");
    			break;//停下来的条件就是break
    		}
    	}
    }
    int main()
    {
    	int input = 0;
    	srand((unsigned int)time(NULL));
    	do
    	{
    		menu();
    		printf("请选择\n");
    		scanf("%d", &input);
    		switch (input)
    		{
    		case 1:
    			game();
    			break;
    		case 0:
    			printf("退出游戏\n");
    			break;
    		default:
    			printf("选择错误\n");
    			break;
    		}
    	} while (input);
    	return 0;
    }

    结果演示:

     总结:(梳理整个逻辑)

    菜单打印包含游戏的主逻辑(选择1就玩游戏,选择0就退出游戏,选择其他就是选择错误)——do while结构,就开始玩游戏——写game()函数,game()函数上去之后就玩游戏

    ——玩游戏首先生成随机数(怎么生成呢?用rand,rand在使用之前必须用srand设置随机数的生成器,生成器设置好后,rand才会安安稳稳地生成随机数,而它生成随机数的范围是0-32767,而想要的数字是1-100,所以%100+1得到想要的数字)——然后就是猜。

    rand()函数生成随机数,然后进入while循环,然后不断地猜数字。所以一定是生成随机数之后,再在下面反复地猜。一定不要把随机数的生成这个代码放到while循环中,如果这样,就会形成一个现象:每一把猜的数字都是随机的,猜一把下一次的随机数就又变了(一把指的是一轮游戏,一轮游戏中猜的最终答案总在变化——猜一次变化一次,这样是错误的)。

    注意:

    不是真正的随机,是通过算法实现出来的随机数。真正的随机数是无规律的,而写代码是有规律的。

    4.goto 语句

    go to是跳到哪里去。

    语法形式:

    #include<stdio.h>
    int main()
    {
    again :
    	printf("hehe\n");
    	printf("haha\n");
    	goto again;//跳到again那个地方(again是任意一个变量)
    	return 0;
    }//死循环的打印hehe、haha
    //调试发现执行goto again后跳转到again下面的一行。

    只要跳转的标签和写好的标签是一样的,就会进行跳转。

    约束条件是:goto语句和跳转标签必须在同一个函数内,不能跨函数跳转

    goto语句存在时会打乱代码的执行流程,降低代码的可控性,增加代码的风险——谨慎慎重使用goto语句。

    理论上goto语句是不存在的。

    C语言中的goto语句在某些场景下是有很用的。比如最常见的用法就是终止程序在某些深度嵌套的结构的处理过程。例如:一次跳出两层或多层循环。多层循环这种情况下使用break是达不到目的的,它只能从最内层循环退出到上一层的循环。

    goto语句真正适合的场景如下:

    for (...)
    	{
    		for (...)
    		{
    			for (...)
    			{
    				if (disaster)//如果灾难为真,则发生灾难
    					goto error;//跳转到error处
    			}//循环嵌套了三层
    		}
    	}
    	...
    error:
    	if(disaster)//如果disaster发生的时候
    		//处理错误情况

    goto语句可以被替换掉。(如使用循环的实现方式替换goto语句)

    写一个关机程序:

    只要程序启动,就倒计时60秒关机,如果倒计时60秒内,你输入:我是猪,就取消关机;如果不输入,时间到就关机。

    windows系统中提供的一种关机命令:shutdown

    用这个命令(60秒内关机的命令)的方法:shutdown -s -t 60

    -s是设置关机,-t是设置时间关机,60是设置60秒内关机。

    电脑是怎么执行这个命令呢?

    打开电脑的cmd输入shutdown -s -t 60即可关机,注销登录。

    shutdown -a是取消关机,注销取消

     在C语言中执行这种命令:

    system()是库函数,——专门用来执行系统命令。需要引头文件:<stdlib.h>(这个常见)

    代码演示:

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    int main()
    {
    	char input[20] = { 0 };
    	system("shutdown -s -t 60");
    again:
    	printf("请注意,你的电脑在1分钟内关机,如果输入:我是猪,就取消关机\n");
        sacanf("%s",input);
    	if (strcmp(input, "我是猪") == 0)
    	{
    		system("shutdown -a");
    	}
    	else
    	{
    		goto again;
    	}
    	return 0;
    }

    代码讲解:

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    int main()
    {
    	char input[20] = { 0 };
    	system("shutdown -s -t 60");//这个命令一旦被system执行,电脑就已经开始倒计时关机了。
    again:
    	printf("请注意,你的电脑在1分钟内关机,如果输入:我是猪,就取消关机\n");
    	scanf("%s",input);//“我是猪”是字符串,用%s,存起来则在上面创建字符数组。
    	//注:input本来就是数组名,数组名就是地址,所以不用取地址。
    	//若用户输入的是其他的,如:“你是猪,你才是猪”呢?
    	//所以需要判断一下:
    	if (strcmp(input, "我是猪") == 0)//两个字符串比较用strcmp,引头文件<string.h>
    	{//发现input里面的内容和“我是猪”一样的话就进来
    		//则取消关机
    		system("shutdown -a");
    	}
    	else//如果输错了,
    	{//再提醒一次,一分钟中还有时间剩余
    		goto again;
    	}
    	return 0;
    }

    结果演示:

     不用goto语句换一种写法则是:

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    int main()
    {
    	char input[20] = { 0 };
    	system("shutdown -s -t 60");
    	while (1)
    	{
    		printf("请注意,你的电脑在1分钟内关机,如果输入:我是猪,就取消关机\n");
    		scanf("%s", input);
    		//判断
    		if (strcmp(input, "我是猪") == 0)
    		{
    			//取消关机
    			system("shutdown -a");
    			break;
    		}
    	}
    	return 0;
    }

    结果演示:

     即goto语句是可以被替代的,可以尽量不使用goto语句的。

    展开全文
  • C语言之分支语句

    2021-11-03 00:00:58
    4. 复合语句 5. 空语句 其中控制语句用于控制程序的执行流程,以实现程序的各种结构方式,它们由特定的语句定义符组成,C语 言九种控制语句。 分为三类: 1. 条件判断语句也叫分支语句:if语句、switch语句; ...
  • python几种类型的复合语句:if、for、while、def、class、try/except、with/as等。这些复合类型的语句在编写时,要遵循python的语法风格:1.冒号结尾复合语句的声明,如if expr:、def f():2.通过缩进数量决定代码...
  • 在进行软件逆向工程的过程,对C反编译后的逻辑分支语句结构进行了形式化的描述,将图论领域的与或图概念应用到逻辑分支语句的识别上来,克服了相关识别算法的局限性。求解与或图的过程,提出了逻辑关联矩阵的...
  • C++分支语句

    2020-09-10 16:57:30
    复合语句:用一对花括号{}括起来 的语句块,在语法上等效于一个单一语句。 if语句: if语句是最常用的一种分支语句,也称为条件语句。 if(p!=NULL){ cout << *p <<endl; }else{ ; } 注意:比较好的...
  • 按照语句的组成部分,可以将顺序结构的语句分为表达式语句、空语句和复合语句 3 大类。 语句编写方式 在 Java ,语句是最小的组成单位,每个语句必须使用分号作为结束符。除此之外,Java 对语句无任何其他限制,...
  • 2 单分支if语句

    千次阅读 2021-05-24 01:56:39
    分支if语句1. 一般形式单分支if语句是最简单的条件判断语句,其一般形式为:if(表达式) 语句;或者if(表达式)语句;2.执行流程图单分支if语句的执行流程图如下:先判断“表达式”的值,如果值为真(非零),则执行...
  • 复合语句:public class COM{ public static void main(String args[]) { int a = 1; int b= 2; byte a = 'a'; byte b = 'b'; boolean b; { System
  • 如果正确,执行else的复合语句,然后结束当前语句执行。 3、if-else if-else语句 if-else if-else语句为多条件分支语句,即根据多个条件来控制程序的执行。 格式: if(表达式){ …语句 } else if(表达式){ …...
  • 在编程一个常见的问题就是检测一个变量是否符合某个条件,如果匹配,再用另一个值来检测它,依此类推。当然,这种问题使用if条件语句可以完成。例使用if语句检测变量是否复合某个条件,关键代码如下:String ...
  • GNU复合语句

    2016-09-17 14:19:33
    在写Objective-C代码时,使用复合语句能让我们的代码变得更优雅,特别是创建并添加一堆子view时,让我们的代码看上去更整洁。建议经常使用。
  • 在讲解分支语句前,我们先来了解一个概念——块(block),块(复合语句)指的是由一对大括号{}括起来的若干条简单的java语句。例如,public class Tset5{...}大括号里面包含的就是块了,块可以嵌套,例如public ...
  • Java语言基础(四)-复合语句

    千次阅读 2017-03-09 23:43:44
    复合语句、条件语句、循环语句、循环控制
  • java复合语句与条件语句

    千次阅读 2016-05-13 11:40:01
    典型例子,复合语句以整个块为单位,可以用在任何一个单独语句可以用到的地方,并且在复合语句中还可以嵌套复合语句. if(布尔表达式) { 语句 } else { 语句 } 条件语句: 条件语句包括if条件语句和...
  • VB 等一些语言中同一个()号会有不一样的 作用,它用于组合若干条语句形成功能块,用做数组的下标等,而在 C 括号的分 工较为明显,{}号是用于将若干条语句组合在一起形成一种功能块,这种由若干条语句组合 而...
  • java控制语句的概念

    2021-03-05 21:00:14
    Java中的控制语句Java的控制语句的分类Java中有如下几种控制语句(1)分支语句A. if –else (条件语句)B. switch (多分支选择语句)(2)循环语句A. while循环 B. do– while循环 C. for 循环(3)与程序有关的其他语句A. ...
  • case 分支语句的使用

    2020-05-26 15:43:12
    这种情况和多分支if语句非常相似。只不过if要判断多个不同的条件而case语句只判断一个变量的不同取值。 Case语句的结构 case 变量值 in 模式1) 命令序列1 ;; 模式2) 命令序列2 ;; 。。。。。。。...
  • VB 等一些语言中同一个()号会有不一样的 作用,它用于组合若干条语句形成功能块,用做数组的下标等,而在 C 括号的分 工较为明显,{}号是用于将若干条语句组合在一起形成一种功能块,这种由若干条语句组合 而...
  • 分支与循环语句(详讲)

    多人点赞 2021-10-29 11:04:42
    2. 分支语句(选择结构) 2.1 if语句 2.2 switch语句 2.2.1 break的引入 2.2.2 default的引入 3. 循环语句 3.1 while语句 3.1.1 while循环的break和continue 3.2 for循环 3.2.1 语法 3.2.2 break和...
  • 在C语言0代表false,非0代表真 注意: (1)前4种关系运算符的优先级别相同,后两种也相同。前四种高于后两种。 (2)关系运算符的优先级低于算术运算符。 (3)关系运算符的优先级高于赋值运算符。 5.2 关系...
  • switch分支语句 switch分支语句主要用于多分支条件选择程序,其功能非常类似于else if的多分支条件语句。switch语句涉及到的关键字包括:switch、case、break和default,因此其语法规则比if语句稍微复杂一些。 ...
  • VB 等一些语言中同一个()号会有不一样的 作用,它用于组合若干条语句形成功能块,用做数组的下标等,而在 C 括号的分 工较为明显,{}号是用于将若干条语句组合在一起形成一种功能块,这种由若干条语句组合 而...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 17,154
精华内容 6,861
关键字:

复合语句中不能有分支语句

友情链接: CPPstatuslogdemo.rar