分支和循环(二)

分支和循环(二)

do while循环

格式: do{

​ 循环语句;}

​ while(表达式);

特点:循环至少循环一次

例如,我们使用do while循环打印1-10

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

注意:while()后记得打分号

与while循环相同,do while循环加continue之后也有可能出现死循环,原因是continue会跳过循环的调整部分

一些实例

求n的阶乘

#include<stdio.h>
int main(){
    int factorial=1;           //定义一个表示乘积的变量
    int n=0;
    scanf("%d",&n);
    for(i=1;i<=n;i++){
        factorial=factorial*i;
    }
    printf("%d",factorial);
    return 0;
}

求1!+2!+3!

思路:刚刚我们求解了任何一个数n的阶乘,现在我们只需再嵌套一个循环,让n从1变到10,再求和即可

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

结果如下:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mOktRalA-1662121712424)(C:\Users\kevin\AppData\Roaming\Typora\typora-user-images\image-20220830195455181.png)]

然而实际答案却是:1+2+6=9,为什么错误了呢。原因是我们每次循环使用的factorial没有重置导致下一次使用时factorial用的是上次计算保留的值,而每次计算时我们应该将factorial重置为1,改进为:

#include<stdio.h>
int main(){
    int i=0;
    int factorial=1;
    int sum=0;
    for(int n=1;n<=3;n++){
        factorial=1;                  //这里使每次重新计算一个数的阶乘时,factorial从1开始
        for(i=1;i<=n;i++)
        {
        factorial=factorial*i;
        }
    sum=sum+factorial;
    }
    
    printf("%d",sum);
    return 0;
}

结果如下:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v0v1jG1w-1662121712425)(C:\Users\kevin\AppData\Roaming\Typora\typora-user-images\image-20220830200336304.png)]

到这里,我发现这样算会嵌套两个循环,极大的增加了程序的时间复杂度,因此我们不妨想想求阶乘的另一种思路:递归的思想,因为n!=(n-1)!*n,我们求出了上一个数的阶乘,就只需在此基础上乘一个数即可,如下:

#include<stdio.h>
int main(){
    int factorial=1;
    int sum=0;
    for(int n=1;n<=3;n++){
    factorial=factorial*n;            //一层for循环提高了程序的效率
    sum=sum+factorial;
    }
    
    printf("%d",sum);
    return 0;
}

在一个有序的数组中查找某个数字n

在数字中:1 2 3 4 5 6 7 8 9 10中找到7

思路一:存放于数组中遍历 缺点:没有用上有序的条件,这样做对于无序数组同样可以

思路二二分查找/折半查找

​ 左右元素下标------>中间元素下标(若遇到偶数个元素,取整即可)

#include<stdio.h>
int main(){
    int arr[]={1,2,3,4,5,6,7,8,9,10};
    int left=0;
    int sz=sizeof(arr)/sizeof(arr[0]);    //求数组的元素个数
    int right=sz-1;                       //left,right代表的是数组元素的下标
    int key=7;
    
    while (left<=right)                   //注意循环条件
 	{  
    int mid=(left+right)/2;               //mid要放在循环体内部,时刻随着left和right的改变值
    if(arr[mid]>key){
        right=mid-1;
    }
    else if(arr[mid]<key){
        left=mid+1;
    }
    else{
        printf("找到了,下标是:%d\n",mid);
        break;
    }
 }
    if(left>right){
        printf("not found\n");
    }
   
    return 0;
}

演示多个字符从两端移动,向中间汇聚

例如:welcome !!!

​ ###########

​ w#########!

​ we#######!!

​ …

​ welcome !!!

思路:welcome !!! 左右分别保存下标,将#(arr2)与字符(arr1)逐一替换

​ ###########

​ | |

​ left right

#include<stdio.h>
#include<string.h>          
#include<windows.h>                  //Sleep函数头文件
int main(){ 
    char arr1[]={"welcome!!!"};
    char arr2[]={"##########"};

    int left=0;
    int right=strlen(arr2)-1;        //最后一个元素下标是strlen长度-1

    while (left<=right)
    {
        arr2[left]=arr1[left];
        arr2[right]=arr1[right];
        printf("%s\n",arr2);         
        Sleep(100);                  //Sleep睡眠函数(单位是ms),每步停100ms,方便看出打印过程
        left++;
        right--;
    }
    return 0;
}

输出结果如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Vn80JgYE-1662121712426)(C:\Users\kevin\AppData\Roaming\Typora\typora-user-images\image-20220830213827033.png)]

模拟用户登录,并且最多登录三次

难点:判断密码正确性 两个字符串比较,不能用==来比较,应该使用函数**strcmp()**来比较两字符串是否相同

比较两个字符串,不是比较字符串的长度,而是比较对应位置的ASCII码值

//假设正确密码是:mwztwrx
#include<stdio.h>
#include<string.h>                          //使用strcmp函数头文件
int main(){
    int i=0;
    char password[20]={0};                  //用数组保存密码

    for(i=0;i<3;i++)
    {
        printf("请输入密码:\n");
        scanf("%s",password);
        
        if (strcmp(password,"mwztwrx")==0)    //判断密码正误(判断字符串是否相等)
        {
            printf("登录成功");
            break//当登录成功时跳出循环,用再次叫用户输入密码了
        }
        else 
        {
            printf("密码错误,请重新输入");
        }
    }
    if(i==3){
        printf("三次密码错误,即将退出程序");
    }
    return 0;
}

注意:strcmp()函数返回值有三种:

字符串1>字符串2 返回值大于0

字符串1<字符串2 返回值小于0

字符串1=字符串2 返回值等于0

猜数字游戏的实现

规则:电脑随机生成一个1-100的数字------>猜数字------>如果猜小了告知猜小了,如果猜大了告知猜大了,猜对了就告知猜对了

step1 进入界面
void menu()
{
    printf("*************************************\n");
    printf("****************1.play***************\n");
    printf("****************0.exit***************\n");
    printf("*************************************\n");
}
step2 主体搭建

对于用户输入的1/0(是/否)来进入不同的情况:用switch-case语句作为整个函数的主体(也是main函数内容)

do{
	menu();
    printf("请选择:>");
	scanf("%d", &input);
	switch (input)                   //根据用户选择是否进入游戏
	{
	case 1:
		game();                      //创建game函数作为游戏内容
		break;
	case 0:
		printf("退出游戏\n");
		break;
	default:
		printf("选择错误,重新选择!\n");
		break;
	}
} while (input);                      //根据用户输入来执行下一步内容

step3 生成随机数

rand函数可以生成随机数,随机数的范围在0~RAND_MAX(32767)之间

在使用rand函数之前,需要调用srand函数,设置随机数的生成起点

srand函数:void srand (unsigned int seed);需要传入一个整数

//生成随机数
	srand();
    int ret=rand();
	printf("%d",ret);	

当我们在调用srand时,当srand的值确定后,生产的随机数就确定不变了,这一点也不随机。我们知道,一个变化的srand值可以对应不同的随机数值,而在电脑中,时间就是那个一直在变化的值。对于每个变化的时间,我们都有唯一的数字可以表示它,这个数字叫做时间戳,此时就要运用到time函数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3FjjlSnn-1662121712427)(C:\Users\kevin\AppData\Roaming\Typora\typora-user-images\image-20220831110341595.png)]

time函数格式:time_t time(time_t* timer);

​ |

													time函数的参数

一般的,我们在使用time函数时,只需要它的返回值,不需要参数,而srand函数需要传入的数据类型是unsigned in,因此这里我们还需要进行一步强制类型转换,修改后如下:

//设置随机数生成器
	srand(unsigned int)time(NULL);       //强制类型转换

srand函数(生成随机数的起点)只需调用一次,在需要生成随机数的地方直接使用rand即可

按照题目要求,我们需要限定生成随机数的范围(1100):**将生成的随机数模100,那么生成的余数就在099之间,我们再在此基础上加一,就可以得到1~100的随机数了。整个生成随机数完整程序如下:

#include<stdio.h>
#include<stdlib.h>                          //使用srand函数的头文件
#include<time.h>                            //使用time函数的头文件
int main(){
    srand((unsigned int)time(NULL));        //函数格式:srand(xx)注意括号
    int ret=rand();
    int final=(ret%100)+1;
    printf(" %d ",final);                   //这里我们方便检测结果打印出随机数,实际上不打印
    return 0;
}

这样就生成了一个100以内的随机数了:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Kx8nsrZ6-1662121712427)(C:\Users\kevin\AppData\Roaming\Typora\typora-user-images\image-20220831113031602.png)]

step4 猜数字

这里的思路很简单,即读取用户输入与生产的随机数final作大小的比较,而用户可以有多次机会,因此这里可以使用循环,当用户猜对后循环停止

//猜数字
	while1{
        int guess=0;
	printf("请猜数字:\n");
	scanf("%d",&guess);
	if(guess<final){
        printf("猜小了\n");
    	 }
	else if(guess>final){
        printf("猜大了\n");
   		 }
	else{
        printf("猜对了\n");
    	break;                         //猜对了循环停止,否则循环会一直进行下去
    	}
	}
step5 完整程序
#include<stdio.h>
#include<stdlib.h>                          //使用srand函数的头文件
#include<time.h>    

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

void game()
    {   
        srand((unsigned int)time(NULL));        //函数格式:srand(xx)注意括号
        int ret=rand();
        int final=(ret%100)+1;                  //取模结果有可能相同
        int guess=0;
	    
        while (1)
        {
        printf("请猜数字:\n");
	    scanf("%d",&guess);
	    if(guess<final){
            printf("猜小了\n");
    	    }
	    else if(guess>final){
            printf("猜大了\n");
   		    }
	    else{
            printf("猜对了\n");
    	    break;                         //猜对了循环停止,否则循环会一直进行下去
    	    }
        }
	}

int main(){
	int input;
	do{
	    menu();
        printf("请选择:>");
	    scanf("%d", &input);
	    switch (input)                   //根据用户选择是否进入游戏
	    {
	    case 1:
		    game();                      //创建game函数作为游戏内容
		    break;
	    case 0:
		    printf("退出游戏\n");
		    break;
	    default:                         //对于其它值
		    printf("选择错误,重新选择!\n");
		    break;
	    }
    } while (input);                      //根据用户输入来执行下一步内容
	return 0;
}  

运行结果如下:

image-20220831142209514

goto语句

goto语句是低级语言的表征。它很灵活,灵活到没有任何拘束,在函数体内直来直往。goto语句允许把控制无条件转移到同一函数内的被标记的语句

例如下面这段程序:

#include<stdio.h>
int main(){
    flag:
    	printf("hello sir");
    	goto flag;
    return 0;
}

运行结果如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5OlCo2B9-1662121712428)(C:\Users\kevin\AppData\Roaming\Typora\typora-user-images\image-20220831143907602.png)]

可以看到,再第一个打印输出后goto语句跳到了flag的位置,继续打印输出然后形成了死循环

不太建议使用goto语句,但不代表goto语句一无是处

goto语句的适用场景:多重循环的嵌套

关机程序

设计一个在60秒后自动关机的程序,当用户输入stop后取消关机

关机命令: shutdown -s -t 60 代表电脑在60秒后执行关机

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main()
{
    system("shutdown -s -t 60");
    again:
    printf("您的电脑将在一分钟后关机,如果输入stop,就取消关机");
    char input[20] = {0};
    scanf("%s", input);
    if(strcmp(input, "stop") == 0){
        system("shutdown -a");
        printf("关机已取消");
    }
    else{
        goto again;
    }
    return 0;
}

关机程序

设计一个在60秒后自动关机的程序,当用户输入stop后取消关机

关机命令: shutdown -s -t 60 代表电脑在60秒后执行关机

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main()
{
    system("shutdown -s -t 60");
    again:
    printf("您的电脑将在一分钟后关机,如果输入stop,就取消关机");
    char input[20] = {0};
    scanf("%s", input);
    if(strcmp(input, "stop") == 0){
        system("shutdown -a");
        printf("关机已取消");
    }
    else{
        goto again;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值