分支循环语句(1)

1.什么是语句?

  • 表达式语句
  • 函数调用语句
  • 控制语句
  • 复合语句
  • 空语句

本篇主要介绍控制语句

控制语句用于控制的执行流程,以实现程序的各种结构方式,它们由特定的语句定义符组成,C语言有九种控制语句

可以分成以下三类:

  1. 条件判断语句也叫分支语句:if 语句、switch 语句:
  2. 循环执行语句:do while语句、while语句、for 语句;
  3. 转向语句:break 语句、goto 语句、continue 语句、return语句

本编介绍的分支循环语句都属于控制语句

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

C语言是结构化的程序设计语言(顺序结构、选择结构、循环结构)

2.1 if语句

语法结构:

//形式1

if(表达式)

        语句;

//形式2

if(表达式)

        语句1;

else

        语句2;

//多分支

if(表达式1)

        语句1;

else if(表达式2)

        语句2;

else

        语句3;

表达式结果为真,执行语句,表达式结果为假,不执行语句

在C语言中,非零表示真,0表示为假

if 和else默认只能控制一条语句,如果想要控制多条语句必须加 {  } 

#include<stdio.h>
int main()
{

    if(表达式)
    {
        语句列表1;
    }
    else
    {
        语句列表2;
    }
    return 0;
}

 注意:在C语言中。有两个范围的变量不能像数学中那么写

用&&(两边同时为真,才能执行语句)和  | | (两边只要有一个为真,就可以执行语句)连接

2.1.2 if书写形式对比

悬空else

这里有一个小小的陷阱

 注意:else与最近的if语句搭配,不是看和谁对齐

不规范的写代码,不便于阅读和理解,所以必须规范书写习惯,养成好的代码风格

1.变量的命名(有意义,规范)

#include<stdio.h>
int main()
{
    char firstname[20]={0};//不便于读取,像下面这样的形式就比较容易读取
    char FirstName[20]={0};
    char First_name[20]={0};
}

2.空格,空行,换行

int a=10;
int a = 10;

第二行代码就比第一行代码看起来更舒服一些

养成好的代码风格, 推荐看《高质量的c-c++编程》

2.2.1 if书写形式的对比

//代码1
if(condition){
    return x;
}
return y;

//代码2
if(condition)
{
    return x;
}
else
{
    return y;
}

上面的这两种书写形式不同,但是它们意思都是相同的,return返回值

但是代码1这种形式不便于理解,会让人误以为返回两个值,所以养成好的代码风格非常重要

//代码3
int num=1;
if(num==5)//这里有时候会误写成num=5没有语法错误,这时这条语句恒为真,编译器不会报错
{
    printf("hehe\n");
}

//代码2
int num=1;
if(5==num)//如果这里不小心写成5=num,编译器会报错,因为变量是不能赋值给常量的
{
    printf("hehe\n");
}

2.1.3 练习

#include<stdio.h>
int main()
{
    int i = 0;
    scanf("%d",&i);
    if( i %2 ==1)
        printf("奇数");
    else
        printf("不是奇数");
    return 0;

}

1.判断一个数是否为奇数2.输出1-100之间的奇数

#include<stdio.h>
int main()
{
    int i=0;
    for(i=0;i<=100;i++)
    {
        if(i%2==1)
            printf("%d ",i);
    }
    return 0;

}

 2.2 switch 语句

switch语句也是一种分支语句,常常用于对分支的情况

输入1,输出星期一

输入2,输出星期二

输入3,输出星期三

输入4,输出星期四

输入5,输出星期五

输入6,输出星期六

输入7,输出星期日

写成if...else...过于复杂,用switch语句会比较简单一些

switch语句的语法结构

switch(整形表达式)//必须是整型

{

        语句项;

}

语句项的形式

case  整型常量表达式;

        语句;

#include<stdio.h>
int main()
{
    int day=0;
    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;

    }

}

多个case支配同一个语句

1.输入1-5,输出的是"weekday";

2.输入6-7,输出的是“weekend ”

#include<stdio.h>
int main()
{
    int n=0;
    scanf("%d",&n)
    switch(n)
    {
        case 1:
        case 2:
        case 3:
        case 4:
        case 5:
            printf("weekday\n");
            break;
        case 6:
        case 7:
            printf("weekend\n");
            break;
        default:
        printf("选择错误\n");
        break;
    }
    return 0;

}

每个switch语句中只能出现一条default子句

switch允许嵌套使用

编程好习惯

在每个switch语句总都放一条default子句是个好习惯,甚至可以在后面再加一个break

3.循环语句

  • while
  • for
  • do while

while的语法形式

while(表达式)

        循环语句;//表达式为真,执行语句

3.3.1while循环中的break和continue的作用

打印1-10数字

#include<stdio.h>
int main()
{
    int i=1;
    while(i<=10)
    {
        printf("%d ",i);
        i++;
    }
    return 0;
}
//switch语句中break的作用:终止循环
#include<stdio.h>
int main()
{
    int i=1;
    while(i<=10)
    {
        if(5==i)
            break;
        printf("%d ",i);//1 2 3 4 
        i++;
    }
    return 0;
}

//switch语句中continue的作用:跳过本次循环(也就是说后面的代码不再执行),直接到判断部分,进行下一次循环

#include<stdio.h>
int main()
{
    int i=1;
    while(i<=10)
    {
        if(5==i)
            continue;
        printf("%d ",i);//1 2 3 4死循环
        i++;
    }
    return 0;
}
#include<stdio.h>
int main()
{
    int i=1;
    while(i<=10)
    {
        i++;
        if(5==i)
            continue;
        printf("%d ",i);//2 3 4 6 7 8 9 10 11
//打印结果没有5
    }
    return 0;
}

 while循环中的

break是用于永久的终止循环

continue跳过本次循环后面的代码,直接去判断部分,进行下一次循环的判断

再看几个代码:

//代码什么意思

//代码1

#include<stdio.h>
int main()
{
    int ch=0;
    while((ch=getchar()!=EOF)
        putchar(ch);
    return 0;
}

这里的代码设当的修改是可以用来清理缓冲区的

//代码2

getchar的返回类型就是整型,返回读到的字符,当读取错误或者是遇到文件结束,会返回EOF,EOF的值是-1

#include<stdio.h>
int main()
{
    char ch='\0';
    while((ch=getchar())!=EOF)
    {
    
    }

}

再vs2019中ctrl+z三次能终止getchar读取字符,不过这个是vs2019的问题,在别的编译器中,一次ctrl+z就能终止个体getchar读取字符

等你输入密码时,回车一按,没有确认就直接打印出No

这是为什么呢? 

scanf、getchar在读取字符时不是直接在键盘上读取字符,scanf、getchar是在输入缓冲区读取字符

 第一次读取a,第二次再读取\n

所以当输入密码时,他不会拿走\n,它将你输入的123456拿走放到password,留下的\n放到了ret中,所以还没确认就直接输出No啦,但是我们不希望getchar把\n拿走,我们该怎么办呢?

这时就可以清除\n,但是这种写法是临时的,只是对当前输入的123456\n有用,假设输入

123456 abcdef,这时它也是直接没等确认就直接输出No,scanf这里空格它是不会读取,只读取123456,到getchar时只读取空格,下面ret中getchar读取abcdef,不等确认就直接输出No

 

 此时\n之前的,包括\n都可以被清理掉了,就可以很好的解决问题啦

//代码

这个代码的作用时:只打印数字字符,跳过其他字符

#include<stdio.h>
int main()
{
    char ch='\0';
    while((ch=getchar())!=EOF)
    {
        if(ch<'0'||ch>'9')
            continue;
            putchar(ch);
    }
    return 0;
}

题外:练习

sizeof(arr)-计算的时数组的总大小,单位是字节

sizeof(arr[ 0 ])-计算的数组元素的大小

strlen计算的时字符数组的大小,并且后面有\0,才能计算大小

double和float的保存精度不同 

浮点型数据

在给一个float型数据初始化时要写成0.0f

3.2 for循环

3.2.1 语法

for(表达式1;表达式2;表达式3)

        循环语句;

表达式1

表达式1为初始化部分,用于初始化循环变量的

表达式2

表达式2为条件判断部分,用于判断循环时终止

表达式3

表达式3为调整部分,用于循环条件的调整

3.2.2 break和continue在for循环中的作用

 for循环中的break用于终止循环,break只能结束它所在的循环,多层嵌套终止循环的需要多个break

 continue在for循环中的作用,跳过本次循环到调整部分

3.2.3 for语句的循环控制变量

建议:

1.不可以在for循环体内修改循环变量,防止for循环失去控制

 

这样只进行一次循环 ,只打印出1

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

int i=0;

//前闭后开的写法

for(i=0;i<10;i++)

{ }

//两边都是闭区间

for(i=0;i<=9;i++)

{}

3.2.4 一些for循环的变种

 此时若省略for循环中的初始化部分只能打印10个hehe,因为当i=2是j的值还是上次剩下的值j=10,所以这里只能打印10个hehe与上面的结果有所不同

 

 C99 语法才支持了这种写法

C++支持这种写法

3.2.5 一道笔试题

 注意:

这道题有陷阱

判断部分k=0,表达式结果为0,0为假,这个循环不循环

3.3 do...while()循环

3.3.1 do语句的语法

do

        循环语句;

while(表达式);

//这个循环至少循环一次

 3.3.2 break和continue在do...while循环中的作用

3.

 在do...while循环中,break也是用于终止循环

 在do...while中continue跳过本次循环(continue后面的代码)到判断部分

3.3.3 do...while语句的特点

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

三种循环中最常使用的是for,然后是while,最后是do...while

3.4练习

1.计算n的阶乘

2.

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

注意二分查找必须是有序的

特点:每次查找都将数据范围减小一半

注意事项:

  • 这里的 int mid=(left+right)/2;必须放到循环中,因为每次查找的时候,left和right的二者之一都在改变,所以必须放到while循环中
  • break不要忘记加,因为这是在循环中,如果不用break终止循环,这个程序将死循环

 那么我们应该怎么写?

 把right高于left的部分/2,再加到left上,left和right一样高

 这样就不会出现栈溢出的现象

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

 这里是直接出来的,没有那种动态的效果

所以可以每次让它停几秒在打印下一个,这是我们引入Sleep()函数单位是ms,当然使用这个函数需要引头文件#include<windows.h>

 这样会有一个动态的效果

这时我们想要在一行就能展示出这种动态的效果,所以每次打印清理掉屏幕,使用库函数system("cls");,使用它也需要引头文件#include<stdlib.h>这个可以清空屏幕,他会将最终的想要展示welcome to bit!!!!也会被清理掉,最后打印一遍welcome to bit!!!!即可

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

 

 注意两个字符串比较不能用==来比较,使用库函数strcmp来进行比较,使用库函数需要引头文件#include<string.h>

3.4.1猜数字游戏实现

猜数字游戏的逻辑:

  • 电脑生成随机数
  • 我们输入数字,看猜大了还是猜小了

每次都需要打印菜单,看是否要玩,所以这个选择玩游戏至少要进行一次,用do...while循环

 这里的打印猜数字游戏先暂时代替我们要写的猜数字逻辑,我们每写完一部分程序时都要运行一下,看我们的代码是否有问题,写一部分,测一部分,问题就不会积累在后面

 现在我们来实现猜数字游戏的逻辑

1.电脑生成随机数

使用rand函数,生成随机数

 生成随机数的范围0~RAND_MAX,转到定义可以看到RAND_MAX的值

 但是有没有发现每次想玩的时候,每一把生成的随机数都是一样的

注意仔细看rand函数的使用方法,

 使用rand函数之前,用调用srand函数设计随机数的生成器

srand(),()括号内的数字变化时,才生成随机数

是不是懵了!!!

想要生成随机数,必须调用一个随机数才能生成随机数

因为时间时一直变化的,这里我们引入时间戳的概念,时间可以转换为对应的时间戳

C语言中的time函数就能返回一个时间戳,这里time函数的参数是指针类型,我们可以不用,传一个空指针(NULL)即可,但是它返回的是time_t的类型

 但是srand函数的返回类型是unsigned int的类型,所以需要强制类型转换

 这儿确实生成了随机数,但是有没有发现当你按得太快,它会生成一样的数字

 rand函数使用之前确实需要调用srand函数,但不是每次生成随机数时都需要设置一个新的起点,所以我们在整个工程只设置一次即可

有没有发现每次生成随机数得数值都太大了,这样不便于我们猜数字,那咱们让电脑生成1-100的随机数

 2.猜数字

整体的一个实现

4.goto语句

C语言中提供了可以随意滥用的goto语句和标记跳转的标号。

从理论上goto语句是没有必要的,实践中没有goto语句也可以很容易的写出代码,但是某些场合下goto语句还是用得着的,最常见的用法就是终止程序在某些深度嵌套的结构的处理过程

例如:一次跳出两层或多层循环

多层循环这种情况使用break是达不到目的的。他只能从最内层循环退出到上一层的循环

 这里一直不停的打印hehe和haha

goto语句会打乱原本的程序的执行流程,跳来跳去的,可能会让程序出现问题

所以尽可能少使用goto语句,goto函数不能跳函数,只能在一个函数内部跳转

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

for(...)
    for(...)
        {
            for(...)
                {
                    if(disaster)
                        goto error;
                }
        }
        ...
error:
    if(disaster)
        //处理错误情况    

下面是使用goto语句的一个例子,然后使用循环的实现方式替换goto语句

一个关机程序

shutdown -s 设置关机

-t 设计倒计时关机时间

shutdown -a 停止关机

int 、struct、continue都是关键字,但是像#define 、#include等不是关键字,而是预处理指令,基本上以#开头的都是预处理指令

在switch语句中continue不死switch的关键字,continue是用于循环中,switch不是循环语句

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值