分支和循环语句

目录

1.&&的注意事项

2.悬空else

3.switch语句

4.循环语句

break:

Continue:

5.(小插曲)getchar和putchar和标准输入缓冲区

6.for循环

for语句的循环控制变量

7.do...while()循环

8.例题

1.计算n的阶乘:

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

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

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

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

9.猜数字游戏实现

9.1插曲:随机数的生成

10.goto语句

小游戏:


1.&&的注意事项

int main()
{
    int age=0;
    scanf("%d",&age);
    if(age<18)
        {
        printf("未成年\n");
        }
     else if(18<=age<30)
        {
            printf("青年\n");
        }
    return 0;
}

这样无论怎么输入都会打印青年

因为(18<=age<30)是先判断前面,18<=50为真1,再1<=30也为真。需要改为(18<=age && age<30)。

2.悬空else

这段代码的执行结果什么都不会输出。

else和离得近的语句进行匹配

改进:

int main()
{
    int a = 0;
    int b = 2;
    if( a == 1 )
    {
       if(b == 2)

        {

            printf("hehe\n");
        
        }
    }
     else {
           printf("haha\n");
            } 
return 0;
    
}     

3.switch语句

case决定入口

break决定出口


​​​​​​​

switch(整型表达式)

{

        语句项;         

}

而语句项是什么呢?

//是一些case语句: 
//如下: 
case 整形常量表达式:

语句;

如果像下面这样写的话输入5就会把后面的打印出来,执行流程是这样的:

改进:

int main() 
{
int day = 0; 
switch(day) 
 { 
    case 1: 
        printf("星期一\n");
        break; 
    case 2:
        printf("星期二\n");
        break;
     case 3:
        printf("星期三\n");
        break;
     case 4:
        printf("星期四\n");
        break;
     case 5:
        printf("星期五\n"); 
        break; 
     case 6:
        printf("星期六\n"); 
        break; 
     case 7:
        printf("星期天\n");
        break;
     default:
        printf("输入错误\n");
        break;
  } 
return 0;

}

有时候我们的需求变了:

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

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

//switch代码演示 
int main() 
{
    int day = 0;
    switch(day) 
    { 
        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");
    }
     return 0;

}

打印的结果为m=5,n=3 。自己的break只能跳出自己的语句

4.循环语句

break:

其实在循环中只要遇到break,就停止后期的所有的循环,直接终止循环。 所以:while中的break是用于永久终止循环的。

打印的结果是1 2 3 4

Continue:

continue是用于终止本次循环的,也就是本次循环中continue后边的代码不会再执行, 而是直接跳转到while语句的判断部分。进行下一次循环的入口判断。

这段代码的结果是1 2 3 4 死循环

因为i == 5的时候continue会跳过下面的代码,然后i还是5

5.(小插曲)getchar和putchar和标准输入缓冲区

getchar - 读取一个字符

putchar - 输出/打印一个字符

getchar 读取到一个字符的时候返回的是一个字符的ASII码值

如果读取失败,返回的是EOF,而EOF是一个整型的-1。所以是int ch = getchar()

清空标准输入缓冲区的重要性

但是这样又会出错

getchar只会处理\n

改进

如果scanf要读取123 abc的话可以这样写(意义不大)

意思为一直向后读,直到遇到\n

6.for循环

语法:

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

        循环语句;

表达式1

表达式1为初始化部分,用于初始化循环变量的。(只会执行一次)

表达式2

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

表达式3

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

for语句的循环控制变量

建议:

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

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

如这样就是错的:

前闭后开

for循环的初始化、判断、调整三个部分均可以省略

如果把判断部分省略了,就意味着判断恒为真

例题:

条件判断中是赋值,0为假所以不会进去。

7.do...while()循环

do语句的语法:

break在其中的结果:

continue在其中的结果:

结果为死循环

总结:

8.例题

1.计算n的阶乘:

#include <stdio.h>


int main()
{
    int total,n;
    scanf("%d",&n);
    for (total=1;n>0;n--)
    {
        total*=n;
    }
    printf("%d",total);
}

有这样一个宏定义:

所以不能计算100的阶乘,会溢出。

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

int main()
{
    int total=1,i,sum=0,n;
    for (n=1;n<=10;n++)
    {
        for (i = 1,total=1; i <= n; i++)
        {
            total *= i;
        }
        sum += total;
    }
    printf("%d\n",total);
    printf("%d\n",sum);
}

代码优化:

思路算1的时候是1*1

算2的时候是       1*2

算3的时候是       1*2*3

算4的时候是       1*2*3*4

所以每次在算的时候就上一个阶乘乘以自身就可以了

#include <stdio.h>

int main()
{
    int total=1,sum=0,n;
    for (n=1;n<=10;n++)
    {
        total *= n;
        sum += total;
    }
    printf("%d\n",total);
    printf("%d\n",sum);
}

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

⚠️注意二分查找的前提是有序的

这里首先看找一个数,普通的方式就是遍历进行查找

#include <stdio.h>


int main()
{
    int arr[]={1,2,3,4,5,6,7,8,9,10};
    //         0 1 2 3 4 5 6 7 8 9
    int k = 7,i=0;
    int sz=sizeof (arr)/ sizeof(arr[0]);
    int flag;
    for (i=0;i<sz;i++)
    {
        if(k==arr[i])
        {
            flag =1;
            printf("find element,arr:%d\n",i);
            break;
        }
    }
    if(flag == 0)
    {
        printf("not find\n");
        return 0;
    }
}

但是这样进行查找的话,就算一个无序的数组这样查找的话也可以。而现在是有序的这样反而显得效率并不高。

参考旧金山大学的动画演示

Binary and Linear Search Visualizationicon-default.png?t=N7T8https://www.cs.usfca.edu/~galles/visualization/Search.html

#include <stdio.h>


int main()
{
    int arr[]={1,2,3,4,5,6,7,8,9,10};
    //         0 1 2 3 4 5 6 7 8 9
    int k = 7;
    int sz=sizeof (arr)/ sizeof(arr[0]);
    int flag=0;
    int mid,left,right;
    left=0;
    right=sz-1;
    while (left<=right)
    {
        mid=(left+right)/2;//mid只能放在循环里面每次需要重新定位mid
        //但是这样如果数特别大很容易溢出,所以可以改进为
        //mid=left +(right-left)/2
        if (arr[mid] < k)
        {
            left = mid + 1;
        }
        else if (arr[mid] > k)
        {
            right = mid - 1;
        }
        else
        {
            printf("find element arr%d", mid);
            flag = 1;
            break;
        }
    }
    if (0==flag)
    {
        printf("not find\n");
    }
    return 0;

}

溢出改进的图示:

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

#include <stdio.h>
#include <string>
#include <unistd.h>
#include <stdlib.h>

int main()
{
   char arr1[]="hello world";
   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);
        usleep(1000000);
        system("clear");
        left++;
        right--;
    }
    printf("%s\n",arr2);
   return 0;
}

这是在Mac的Clion中所使用的。usleep意思是延迟输出,system意思为清空输出框的显示

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

假设密码为123456

        strcmp函数的基本形式为strcmp(str1,str2),若str1=str2,则返回零;若str1<str2,则返回负数;若str1>str2,则返回正数12。

注意这里不能写成if("123456"==password),字符无法这样比较。

#include <stdio.h>
#include <string>

int main()
{
    int i;
    char password[20]={0};
    int flag=0;
    for (i=0;i<3;i++)
    {
        printf("请输入密码\n");
        scanf("%s",password);
        if(strcmp("123456",password)==0)
        {
            flag=1;
            printf("密码正确\n");
            break;
        }
        else
        {
            printf("密码错误\n");
        }
    }
    if(flag==0)
    {
        printf("输入三次错误,密码退出");
    }
    return 0;
}

        在这篇代码中如果 char password[20]={0};写成了 char password[]={0};那么表示这个数组只有一个字符的空间,然后试图在这个数组中存储长度为6的字符串"123456"。这会导致越界,因为这个数组只能存储一个字符。

        正确的做法应该是使用一个足够大的字符数组来存储密码。如:

char password[]={1,2,3,4,5,6};或char password[20]={0};

⚠️strlen只针对字符串,只能计算字符串长度。sizeof计算变量,空间,数组所占空间大小的,不关心内容。strlen是库函数,sizeof是操作符。

9.猜数字游戏实现

9.1插曲:随机数的生成

有一个库函数rand()

Time函数会返回一个指针,不需要所以写成 time(NULL)

#include <stdio.h>
#include <time.h>
#include <stdlib.h>

void menu()
{
    printf("**************************\n");
    printf("********* 1. play  *******\n");
    printf("********* 0. exit  *******\n");
    printf("**************************\n");
};
void game()
{
    int ret;

    //1.生成随机数
    ret =rand()%100+1;//范围是1-100
    //2.猜数字
    int guess = 0;
    while (1)
    {   printf("请猜数字:>");
        scanf("%d",&guess);
        if (guess < ret) {
            printf("猜小了\n");
        } else if (guess > ret) {
            printf("猜大了\n");
        }else{
            printf("恭喜你,猜对了\n");
            break;
        }
    }
}

int main()
{
    int input=0;
    //通过时间戳,设置随机数的生成器
    srand((unsigned int )time(NULL));
    do
    {
        menu();
        printf("请选择:>");
        scanf("%d", &input);
        switch (input) {
            case 1:
                game();
                break;
            case 0:
                printf("退出游戏\n");
                break;
            default:
                printf("选择错误\n");
                break;
        }
    }while (input);
    return 0;
}

10.goto语句

#include <stdio.h>

int main()
{
begain:
    printf("hehe\n");
    goto begain;
    return 0;
}

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

从理论上 goto语句是没有必要的,实践中没有goto语句也可以很容易的写出代码。 但是某些场合下goto语句还是用得着的,最常见的用法就是终止程序在某些深度嵌套的结构的处理过 程。 例如:一次跳出两层或多层循环。 多层循环这种情况使用break是达不到目的的。它只能从最内层循环退出到上一层的循环。

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

for(...)

for(...)

{ for(...)

{ if(disaster) goto error; }

} …

error:

if(disaster) // 处理错误情况

如果想从三个for循环里出来就要三个break,而go to就很方便了。

小游戏:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main()
{
//使用命令行关机
//shutdown
//-s设置关机 -t设置时间关机
//shutdown -s -t 60设置60s后关机
//shutdown -a 取消关机
    char arr[20]={0};
    system("shutdown -s -t 60");
agagin:
    printf("请注意,你的电脑在1分钟之内关机,如果输入:我是猪,就取消关机\n");
    scanf("%s",arr);
    if(strcmp(arr,"我是猪")==0)
    {
        system("shutdown -a");
    } else{
        goto agagin;
    }
    return 0;
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

KrisZhang10

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值