C语言笔记:循环语句

目录

1.while循环

1.1 语法

1.2 while语句中的break和continue

1.2.1 break在while循环中的作用:

1.2.2 continue在while循环中的作用:

2.for循环

2.1 语法

2.1 for循环中的break和continue

2.2 for语句的循环控制变量

2.3 一些for循环的变种

3.do...while循环

3.1 语法

3.2 do语句的特点

3.3 do while循环中的break和continue

补充:goto语句的使用方法

练习题:

习题一:计算 n的阶乘

习题二:计算 1!+2!+3!+……+10!

习题三:在一个有序数组中查找具体的某个数字n。(二分查找)

习题四*:编写代码,演示多个字符从两端移动,向中间汇聚。

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

习题6***:猜数字游戏 - 1.电脑随机生成一个数字 2.玩家猜数字 (返回值只能是猜大了、猜小了、猜对了)直到猜对为止


1.while循环

1.1 语法

while(表达式) 循环语句;

while语句执行的流程:

1.2 while语句中的break和continue

1.2.1 break在while循环中的作用:

在循环中只要遇到break,就停止后期的所有的循环,直接终止循环。

while中的break是用于永久终止循环的。

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

1.2.2 continue在while循环中的作用:

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

如:

#include <stdio.h>
int main()
{
     int i = 1;
     while(i<=10)
     {
         if(i == 5)
             continue;
         printf("%d ", i);
         i = i+1;
     }
     return 0;  //1 2 3 4 但陷入死循环,因为i始终等于5
}

练习1:

//代码什么意思?
//代码1
#include <stdio.h>
int main()
{
    int ch = 0;        //此处用的int需要重视下方的解释
    while ((ch = getchar()) != EOF)  
        putchar(ch);
    return 0;
}//输入字符则打印字符,直到键盘输入 Ctrl Z 结束循环

笔记:getchar( ):从键盘获取一个字符(对应的ASCII码值),int getchar(void);

           注:getchar获取的字符实际上是获取的ASCII码值,而EOF本质上是-1,此处ch是可能等                      于EOF(-1)的,而char类型不能存储-1,所以此处用int定义ch

           putchar( ):打印一个字符到屏幕上

           EOF - end of file:文件结束的标志 (注:上面代码并非是输入"EOF"结束循环而是输入Ctrl                                           Z)

*练习2(重点注意):分析下述代码运行结果为什么达不到预期效果,并学会如何清空缓冲区

#include <stdio.h>
int main()
{
    int ch = 0;
	char password[20] = {0};

	printf("请输入密码:>");
	scanf("%s", password);

	printf("请确认(Y/N):>");
	ch = getchar();

	if('Y' == ch)
	{
		printf("确认成功\n");
	}
	else
	{
		printf("放弃确认\n");
	}

	return 0;
}

运行结果如下:

分析:scanf函数和getchar函数都是从键盘上获取数据的函数(并非直接获取),实际上该函数与键盘之间存在输入缓冲区。当程序执行到该函数时,该函数会检查输入缓冲区是否有数据,若有,则会直接取走,若没有则需要键盘输入数据进入输入缓冲区,该函数再取走数据。

当用户在键盘输入123+回车(\n)时, “123\n”进入输入缓冲区,当scanf函数拿走数据时只会拿走“123”,'\n'则留在了输入缓冲区,当程序执行到 ch == getchar( )时,getchar不会等待用户输入而是直接取走缓冲区中的“\n”,由于'\n'!=‘Y’,所以造成了上述运行结果。

如何修改代码呢?

初步方法:在程序执行到 ch == getchar( )前,先使用一次getchar取走输入缓冲区里的‘\n’

#include <stdio.h>
int main()
{
    int ch = 0;
	char password[20] = {0};

	printf("请输入密码:>");
	scanf("%s", password);
    //处理\n
    getchar();

	printf("请确认(Y/N):>");
	ch = getchar();

	if('Y' == ch)
	{
		printf("确认成功\n");
	}
	else
	{
		printf("放弃确认\n");
	}

	return 0;
}

但实际情况可能远比上述示例复杂,如,当输入"123456 abcdef"时,又会出错。

出错的原因在于:当scanf读取字符串到空格的时候就认为已经结束了,只拿走了123456,剩下的 " abcdef"仍在缓冲区中,如何处理呢?

答案如下:

#include <stdio.h>
int main()
{
    int ch = 0;
	char password[20] = {0};

	printf("请输入密码:>");
	scanf("%s", password);

    //处理缓冲区多余的字符
    while(getchar() != '\n')
    {
        ;                     //当getchar()没有读取到'\n'时,该循环会让getchar()不停的读取
    }
	printf("请确认(Y/N):>");
	ch = getchar();

	if('Y' == ch)
	{
		printf("确认成功\n");
	}
	else
	{
		printf("放弃确认\n");
	}

	return 0;
}

*练习3:

#include <stdio.h>
int main()
{
    int ch = 0;
 while ((ch = getchar()) != EOF)
 {
     if (ch < '0' || ch > '9')
        continue;
     putchar(ch);
 }
 return 0;
}
//这个代码的作用是:只打印数字字符,跳过其他字符的

2.for循环

2.1 语法

for(表达式1; 表达式2; 表达式3) 循环语句;

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

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

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

现在我们对比一下for循环和while循环:

int i = 0;
//实现相同的功能,使用while
i=1;                       //初始化部分
while(i<=10)               //判断部分
{
 printf("hehe\n");
 i = i+1;                  //调整部分
}

//实现相同的功能,使用for
for(i=1; i<=10; i++)
{
 printf("hehe\n");
}

 可以发现在while循环中依然存在循环的三个必须条件,但是由于风格的问题使得三个部分很可能偏离较远,这样查找修改就不够集中和方便。

所以,for循环的风格更胜一筹,for循环使用的频率也最高

2.1 for循环中的break和continue

在for循环中也可以出现break和continue,他们的意义和在while循环中是一样的。

但是还是有些差异:

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

2.2 for语句的循环控制变量

编程好习惯

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

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

int i = 0;
//前闭后开的写法
for(i=0; i<10; i++)
{}
//两边都是闭区间
for(i=0; i<=9; i++)
{}

2.3 一些for循环的变种

#include <stdio.h>
int main()
{
     //代码1
     for(;;)
     {
         printf("hehe\n");
     }
    //for循环中的初始化部分,判断部分,调整部分是可以省略的,但是不建议初学时省略,容易导致问
题
    
    //代码2
    int i = 0;
    int j = 0;
    //这里打印多少个hehe?                             //100
    for(i=0; i<10; i++)
   {
        for(j=0; j<10; j++)
       {
           printf("hehe\n");
       }
   }
    
    //代码3
    int i = 0;
    int j = 0;
    //如果省略掉初始化部分,这里打印多少个hehe?         //10
    for(; i<10; i++)
    {
        for(; j<10; j++)
       {
           printf("hehe\n");
       }
    }
    
    //代码4-使用多余一个变量控制循环
    int x, y;
    for (x = 0, y = 0; x<2 && y<5; ++x, y++)
   {
        printf("hehe\n");
   }
 return 0;
}

 面试题:

//请问循环要循环多少次?  0次
#include <stdio.h>
int main()
{
 int i = 0;
 int k = 0;
 for(i =0,k=0; k=0; i++,k++)
        k++;
 return 0;
}

当判断语句是k = 0时,是把0赋值给k,表达式的结果为0,0为假,所以不执行循环

3.do...while循环

3.1 语法

do

        循环语句;

while(表达式);

3.2 do语句的特点

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

3.3 do while循环中的break和continue

#include <stdio.h>
int main()
{
     int i = 1;
    
     do
     {
            if(5 == i)
                break;
            printf("%d\n", i);
            i++;
     }while(i <= 10);
    
     return 0;
}                                   // 1 2 3 4 程序结束
#include <stdio.h>
int main()
{
     int i = 1;
    
     do
     {
            if(5 == i)
                continue;
            printf("%d\n", i);
            i++;
     }while(i <= 10);
    
     return 0;                     // 1 2 3 4 程序未结束,陷入死循环
}

补充:goto语句的使用方法

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

从理论上 goto语句是没有必要的,实践中没有goto语句也可以很容易的写出代码。

goto语句容易让代码的逻辑变乱

但在某些场合下goto语句还是用得着的,最常见的用法就是终止程序在某些深度嵌套的结构的处理过程。

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

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

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

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

如:一个关机程序

用goto语句:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
    char input[10] = {0};
    system("shutdown -s -t 60");
again:
    printf("电脑将在1分钟内关机,如果输入:我是猪,就取消关机!\n请输入:>");
    scanf("%s", input);
    if(0 == strcmp(input, "我是猪"))
   {
        system("shutdown -a");
   }
    else
   {
        goto again;
   }
    return 0;
}
//shutdown -a 取消关机
//shutdown -s -t 时间(秒) 设置关机倒计时
//system需要<stdlib.h>,strcmp需要头文件<string.h>

不用goto语句:

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

练习题:

习题一:计算 n的阶乘

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

习题二:计算 1!+2!+3!+……+10!

代码一:

#include <stdio.h>
int main()
{
     int j = 1;
	 int i = 1;
	 int ret = 1;
	 int sum = 0;
	 
	 for (j = 1;j <= 10; j++)
	 {
        ret = 1;    //最关键的一步,每次内层循环结束让ret回到初始值1
		for (i = 1;i <= j; i++)
		{
			 ret *= i;
		}
		sum += ret;
	 }

	 printf("%d\n", sum);
}

*优化后的代码:

#include <stdio.h>
int main()
{
     int j = 1;
	 int ret = 1;
	 int sum = 0;
	 
	 for (j = 1;j <= 10; j++)
	 {
			 ret *= j;
		     sum += ret;
	 }

	 printf("%d\n", sum);
}

习题三:在一个有序数组中查找具体的某个数字n。(二分查找)

//实现在主函数内:
int main()
{
 int arr[] = {1,2,3,4,5,6,7,8,9,10};
 int left = 0;
 int right = sizeof(arr)/sizeof(arr[0])-1;  //重点
 int key = 7;
 int mid = 0;
 while(left<=right)
 {
     mid = (left+right)/2;
     if(arr[mid]>key)
     {
         right = mid-1;
     }
     else if(arr[mid] < key)
     {
         left = mid+1;
     }
     else
         break;
 }
 if(left <= right)
     printf("找到了,下标是%d\n", mid);
 else
     printf("找不到\n");
}

习题四*:编写代码,演示多个字符从两端移动,向中间汇聚。

#include <stdio.h>
int main()
{
    char arr1[] = "welcome to bit!!!!!";
    char arr2[] = "###################";
    int left = 0;
    int right = strlen(arr1)-1;   //strlen()用于计算字符串长度
    
    while(left<=right)
    {   
        arr2[left] = arr1[left];
        arr2[right] = arr1[right];
        printf("%s\n", arr2);
        Sleep(1000);             //停顿1000ms
        system("cls");           //清空屏幕 需要头文件#include <windows.h>
        left++;
        right--;
    }
    printf("%s\n", arr2);
    return 0;
}

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

#include <stdio.h>
#include <string.h>
int main()
{
	int i = 0;
	//假设正确密码是"123456"
	char password[20] = {0};
	for(i = 0; i < 3; i++)
	{
		printf("请输入密码:>");
		scanf("%s", password);
		//判断密码的正确性 - 比较2个字符串的大小关系
		//strcmp - 用于比较字符串的大小关系,库函数,所需要的头文件是:string.h
		if(strcmp(password,"123456")==0)
		{
			printf("密码正确\n");
			break;
		}
		else
		{
			printf("密码错误,请重新输入\n");
		}
	}
    if(3 == i)
    {
        printf("三次密码错误,退出程序\n");
    }
	return 0;
}

笔记:strcmp函数是string compare(字符串比较)的缩写,用于比较两个字符串并根据比较结果返回整数。基本形式为strcmp(str1,str2),若str1=str2,则返回零;若str1str2,则返回正数。为库函数,所需要的头文件是:string.h

习题6***:猜数字游戏 - 1.电脑随机生成一个数字 2.玩家猜数字 (返回值只能是猜大了、猜小了、猜对了)直到猜对为止

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

void game()
{
	//1.生成随机数 1-100之间的随机数 所以让rand()对100取模再+1

	//C语言中有一个生成随机数的函数 - rand() (但每一轮生成的随机数是相同的) 
	//需要头文件<stdlib.h>
	//调用rand()前,需要使用srand()设置一个随机的起点
	//()内为时刻发生变化的数字 - 电脑上的时间一直在变化 =》时间戳=》time函数
	//time 获取系统时间,需要头文件<time.h> 此处想使用向time函数中传入一个空指针即可

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

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

int main()
{
	int input = 0;
	srand((unsigned int)time(NULL)); 
	do
	{
		//1.打印一个菜单
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
			case 1:
				//游戏的逻辑
				game(); //猜数字游戏的代码
				break;
			case 0:
				printf("退出游戏\n");
				break;
			default:
				printf("选择错误,重新选择!\n");
				break;
		}
	}while(input);
	return 0;
}

笔记:1.为了该小游戏可以第一把能执行,选择do while循环

           2.生成随机数的函数 - rand() 需要头文件<stdlib.h>     int rand(void)      但每一轮生成的                  随机数是相同的,所以调用rand()前,需要使用srand()设置一个随机的起点 srand()同样为                库函数需要头文件<stdlib.h>  void srand(unsigned int seed)  想在括号内放入时刻发                    生变化的数字 - 电脑上的时间一直在变化 =》时间戳=》time()函数 功能为获取系统时                    间,需要头文件<time.h>,不多赘述,此处想使用向time函数中传入一个空指针即可

           3.将srand((unsigned int)time(NULL)); 放入main函数即可

           4.为了生成1-100之间的随机数,所以让rand()对100取模再+1
 

猜你喜欢

转载自blog.csdn.net/m0_62934529/article/details/123158560