C语言学习 2.分支语句与循环语句

分支语句与循环语句

1. 什么是语句

在c语言中语句分为以下五类:

  1. 表达式语句
  2. 函数调用语句
  3. 控制语句
  4. 复合语句
  5. 空语句

本章介绍的是控制语句

控制语句用于控制程序的执行流程,以实现程序的各种结构方式,它由特定的语句定义符组成,c语言有九种控制语句,可以分为以下三类:

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

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

  • if
  • switch

1. if语句

1.1 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;
}
//结果打印 haha

else的匹配:else是和离它最近的if匹配的。

//代码1
int num = 1;
if(num==5)
{
  printf("haha\n");
}

//代码2
int unm = 1;
if(5==num)
{
  printf("haha\n");
}
//代码2比代码1更好,不容易出错
1.2 练习
  1. 判断一个数是否为奇数
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>

int main()
{
	int a = 0;
	scanf("%d", &a);
		
	if (a % 2 ==1)
	{
		printf("a是奇数");
	}
	else
	{
		printf("a不是奇数");
	}
	return 0;
}
  1. 输出1-100之间的奇数
#include<stdio.h>

//for循环
int main()
{
	int i = 0;
	for (i = 1;i <= 100;i++)
	{
		if (i % 2 ==1)
		{
			printf("%d ", i);
		}
	}
	return 0;
}

//while循环
  int i = 1;
  while(i <= 100)
 {
		printf("%d ", i);
		i += 2;
 }

2. switch语句

switch(整型表达式)
{
  语句项;
}
//语句项为case语句,如下
case 整型常量表达式:
   语句;
2.1 在switch语句中的break

在switch语句中没法直接实现分支,搭配break才能实现真正的分支。

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>

int main()
{
	int day = 0;
	scanf("%d", &day);
	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;
	}
	return 0;
}

改变需求

  1. 输入1-5,输出weekday
  2. 输入6-7,输出weekend
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
//没有break,程序会自动向下执行
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 6:
	case 7:
		printf("weekend");
		break;
	}
	return 0;
}

缺少break容易导致结果发生改变

int func(int a)
{
       int b;
       switch(a)
       {
         case1:b = 20;
         case2:b = 30;
         case3:b = 40;
         default b = 0;
       }
       return b;
}
//没有default,fun(1)=b=0
2.2 default语句

当switch表达式的值并不匹配所有case标签的值时,这个default子句后面的语句就会执行,所以每个switch语句中只能有一个default子句,但它可以出现在语句列表的任意位置。

#include<stdio.h>

int main()
{
	int n = 1;
	int m = 2;
	switch (n)
	{
	case 1:
			m++;
	case 2:
		    n++;
	case 3:
		switch (n)//switch可以嵌套使用
		{
		case 1:
			n++;
		case 2:
			m++;
			n++;
			break;//结束内层的switch,外层继续
		 }
	case 4:
		m++;
		break;
	default:
		break;
	}
	printf("m = %d,n = %d\n", m, n);
	return 0;
}

在这里插入图片描述

3. 循环语句

  • while
  • for
  • do while

1. while语句

//while 语法结构

while(表达式)
  循环语句;
1.1 while语句中的break和continue

break在while循环中的作用:

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

#include<stdio.h>

int main()
{
	int i = 1;
	while (i <= 10)
	{
		if (i == 5)
			break;
		printf("%d ", i);
		i += 1;
	}
	return 0;
}

在这里插入图片描述

continue在while循环中的作用:

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

#include<stdio.h>

int main()
{
	int i = 1;
	while (i <= 10)
	{
		if (i == 5)
			continue;
		printf("%d ", i);
		i += 1;
	}
	return 0;
}
//这种情况再输出1 2 3 4后会直接进入死循环

改:

#include<stdio.h>

int main()
{
	int i = 1;
	while (i <= 10)
	{
		i += 1;
		if (i == 5)
			continue;
		printf("%d ", i);
		
	}
	return 0;
}

在这里插入图片描述

再看这几个代码:

#include<stdio.h>
//EOF-end of file-文件结束标志

int main()
{
	int ch = 0;
	while ((ch = getchar()) != EOF)//getchar可以读取字符
		putchar(ch);//putchar可以输出字符

	return 0;
}

在这里插入图片描述

getchar()还可用来清理缓冲区

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>

int main()
{
	char password[20] = { 0 };
	printf("请输入密码:");
	scanf("%s", password);//数组名本身就是地址因此不用&
	printf("请确认密码(Y/N):");
	int ch = getchar();
	if (ch == 'Y')
	{
		printf("确认成功\n");
	}
	else
	{
		printf("确认失败\n");
		
	}
	return 0;
}

在这里插入图片描述

运行上述代码时可以发现,我们还没输入Y/N时,就自动显示确认失败了,这是因为没有清理缓冲区,当我们回车时,getchar()自动读取了\n,所以确认失败。

改进:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>

int main()
{
	char password[20] = { 0 };
	printf("请输入密码:");
	scanf("%s", password);//数组名本身就是地址因此不用&
	printf("请确认密码(Y/N):");
	int tmp = 0;
	while ((tmp = getchar() )!= '\n')//可以清理缓冲区直到读取到'\n'
	{
		;
	}
	int ch = getchar();
	if (ch == 'Y')
	{
		printf("确认成功\n");
	}
	else
	{
		printf("确认失败\n");
		
	}
	return 0;
}

在这里插入图片描述

  1. getchar()返回的时ASCII码值(整数)。
  2. getchar()在读取结束或失败时会返回EOF
//只打印数字字符,跳过其他字符
#include<stdio.h>

int main()
{
	int ch = 0;
	while ((ch=getchar())!=EOF)
	{
		if (ch < '0' || ch > '9')
			continue;
			putchar(ch);
	}
		
	return 0;
}

2. for循环

for(表达式1;表达式2;表达式3)
   循环语句;
//表达式1为初始化部分,用于初始化循环变量。
//表达式2为条件判断部分,用于循环变量终止时使用。
//表达式3为调整部分,用于循环条件的终止。

缺少或改变哪一部分都可能导致循环改变。

#include<stdio.h>

int main()
{
	int i = 0;
	int j = 0;
	for (i = 0;i < 3;i++)
	{
		for (j = 0;j < 3;j++)
		{
			printf("haha\n");
		}
	}	
	return 0;
}

在这里插入图片描述

当缺少初始化条件时:

#include<stdio.h>

int main()
{
	int i = 0;
	int j = 0;
	for (;i < 3;i++)
	{
		for (;j < 3;j++)//第一次外循环结束时j的值变为3,因为没有初始化,后面的循环中保持不变
		{
			printf("haha\n");
		}
	}		
	return 0;
}

在这里插入图片描述

2.2 break和continue在for循环中

意义和在while循环中差不多,但还是有些差别。

#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就结束循环

#include<stdio.h>

int main()
{
	int i = 0;
	for (i = 1;i <= 10;i++)
	{
		if (i == 5)
			continue;
		printf("%d ", i);
	}
	return 0;
}
//跳过5打印其余数字
2.3 for语句的循环控制变量

建议:

  1. 不可在for循环体内修改循环变量,防止for循环失去控制。
  2. 建议for语句的循环控制变量的取值采用"前闭后开区间"写法。
int i = 0;
//前闭后开写法
for (i = 0;i < 10;i++)
    
//两边都是闭区间
for (i = 0;i <= 9;i++)
2.4 一些for循环的变种
#include<stdio.h>
//使用多一个变量控制循环
int main()
{
	int x = 0;
    int y = 0;
	for (x = 0, y = 0;x < 2 && y < 5;x++, y++)
	{
		printf("hehe\n");
	}
	return 0;
}
#include<stdio.h>

int main()
{
	int i = 0;
	int k = 0;
	for (i = 0, k = 0;k=0;i++, k++)//条件判断部分k赋值为了0,恒为假,循环0次,若省略判断部分会死循环
	{
		k++;
	}
	return 0;
}

3. do…while()循环

循环至少执行依次,使用场景有限

do
   循环语句;
while(表达式)
3.1 do…while循环中的break和continue
int main()
{
	int i = 10;
	do {
		if (5 == i)
			break;
		printf("%d\n", i);
	} while (i < 10);

	return 0;
}
//只打印一个10就停止循环

#include<stdio.h>

int main()
{
	int i = 5;
	do 
	{
		if (5 == i)
			continue;
		printf("%d\n", i);
	} while (i < 10);

	return 0;
}
//continue直接跳转到while判断部分,所以结果不打印

4. goto语句

goto最常见用法时终止程序某些深度嵌套的结构的处理过程,例如:一次跳出两层或多层循环,多层循环中break是达不到目的的,它只能从最内层循环退出到上一层循环。

for(...)
   for(...)
   {
      for(...)
      {
         if(disaster)
            goto error;
      }
   }
   ...
error:
   if(disaster)
//处理错误情况
       
//goto 语句只能在一个函数范围内跳转,不能跨函数
void test()
{
   flag:
       printf("hahah")
}
int main()
{
    goto flag;//会报错!
    return 0;
}

关机程序

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<string>
int main()
{
	char input[10] = { 0 };
	system("shutdown -s -t 60");//system()执行系统命令,需添加头文件<stdlib.h>
again:
	printf("电脑将在一分钟后关机,如果输入:我是猪,可以取消关机");
	scanf("%s", input);
	if (0 == strcmp(input, "我是猪"))
	{
		system("shutdown -a");
	}
	else
	{
		goto again;
	}
	return 0;
}

也可以使用while循环

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

5. 综合练习

1. 计算n的阶乘
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>

int main()
{
	int n = 0;
	int i = 0;
	int ret = 1;
	scanf("%d", &n);
	for (i = 1;i <=n;i++)
	{
		ret *= i;
	}
	printf("%d", ret);
	return 0;
}

在这里插入图片描述

2. 计算1!+2!+3!+…+n!
//方法1
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>

int main()
{
	int n = 0;
	int i = 0;
	int ret = 1;
	int sum = 0;
	scanf("%d", &n);
	for (i = 1;i <=n;i++)
	{
		ret *= i;
		sum += ret;//后一个数只相当于比前一个数多乘了它本身
	}
	printf("%d", sum);
	return 0;
}
//方法2
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>

int main()
{
	int n = 0;
	int i = 0;
	int j = 0;
	int ret = 1;
	int sum = 0;
	scanf("%d", &n);
	for (j = 1; j <= n; j++)
	{
		ret = 1;//计算n的阶乘之前把ret初始化为1
		for (i = 1; i <= j; i++)
		{
			ret *= i;
		}
		sum += ret;
	}
	printf("%d", sum);
	return 0;
}

在这里插入图片描述

3. 编写代码,演示多个字符从两端移动,向中间汇聚。
//while循环写法
#include<stdio.h>
#include<string.h>
#include<windows.h>//Sleep()头文件和system
int main()
{
	char arr1[] = "welcome to sty";
	char arr2[] = "##############";
	int left = 0;
	int right = strlen(arr1) - 1;//通过字符个数得数组末尾元素下标,-1是减去'\0'
	printf("%s\n", arr2);
	while (left <= right)
	{
		Sleep(1000);
		arr2[left] = arr1[left];
		arr2[right] = arr1[right];
		printf("%s\n", arr2);
		left++;
		right--;
	}


	return 0;
}

//for循环写法
	for (left = 0, right = strlen(arr1) - 1;left < right;left++, right--)
	{
		arr2[left] = arr1[left];
		arr2[right] = arr1[right];
		printf("%s\n", arr2);
		Sleep(1000);//间隔1s出现
		system("cls");//清理屏幕
    }

在这里插入图片描述

//保留单行,逐步显示
#include<stdio.h>
#include<string.h>
#include<windows.h>
int main()
{
	char arr1[] = "welcome to sty";
	char arr2[] = "##############";
	int left = 0;
	int right = strlen(arr1)-1;
	
	for (left = 0, right = strlen(arr1) - 1;left < right;left++, right--)
	{
		arr2[left] = arr1[left];
		arr2[right] = arr1[right];
		printf("%s\n", arr2);
		Sleep(1000);//休眠1秒
		system("cls");//清空屏幕
    }
	printf("%s\n", arr2);
	return 0;
}
4. 在一个有序数组中查找某个具体数字n。
#include<stdio.h>
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", mid);
	}
	else
	{
		printf("找不到了");
	}
	return 0;
}

在这里插入图片描述

//二分查找函数
	int bin_search(int arr[], int left,int right,int key)
	{
		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 mid;//找到目标值
			}
		}
		return -1;//没有找到返回-1

	}
5. 猜数字游戏
#define _CRT_SECURE_NO_WARNINGS 1
#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 random_num = rand() % 100 + 1;//得到一个1-100之间的随机数
	int guess = 0;
	while (1)
	{
		printf("请猜数字:");
		scanf("%d", &guess);
		if (guess > random_num)
		{
			printf("猜大了\n");
		}
		else if (guess < random_num)
		{
			printf("猜小了\n");
		}
		else
		{
			printf("恭喜你,猜对了\n");
			break;
		}
	}
}
int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));//强制类型转化time的类型为与srand相同,time()为调用时间戳,需使用头文件<time.h>,srand()可以使用随机数生成器,其头文件为<stdlib.h>
	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;
}

在这里插入图片描述

6.将三个整数从大到小输出
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>

int main()
{
	int a = 0;
	int b = 0;
	int c = 0;
	int tmp = 0;
	scanf("%d%d%d", &a, &b, &c);
	if (a < b)
	{
		tmp = a;
		a = b;
		b = tmp;
	}
	if (a < c)
	{
		tmp = a;
		a = c;
		c = tmp;
	}
	if (b < c)
	{
		tmp = b;
		b = c;
		c = tmp;
	}
	printf("%d %d %d\n", a, b, c);

	return 0;
}

在这里插入图片描述

7. 打印1-100之间3的倍数
//方法1
#include<stdio.h>

int main()
{
	int i= 0;	
	for (i = 1;i <= 100;i++)
	{
		
	    if(i%3==0)
	    { 
		printf("%d ", i);
	     }
	}
	return 0;
}

//方法2
#include<stdio.h>

int main()
{
	int i= 0;	
	for (i = 3;i <= 100;i+=3)
	{
		printf("%d ", i); 
	}
	return 0;
}

在这里插入图片描述

8.给定两个数,求两个数的最大公约数
//方法1:辗转相除法
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>

int main()
{
	int i = 0;
	int j = 0;
	scanf("%d%d", &i, &j);
	int a = 0;//假设a为余数
	while (a=i % j)
	{
		i = j;
		j = a;
	}
	printf("最大公约数为:%d", j);

	return 0;
} 

//方法2:最大公约数一定在较小数的范围内
int main()
{
	int i= 0;	
	int j = 0;
	scanf("%d%d", &i, &j);
	int max = i < j ? i : j;
	while (1)
	{
		if (i % max == 0 && j % max == 0)
		{
			printf("最大公约数为:%d", max);
			break;
		}
		max--;
	}
	return 0;
}

//最小公倍数=i*j/最大公约数,或者最小公倍数一定是较大值的倍数,一直+1试就行

在这里插入图片描述

9. 打印1000年到2000年之间的闰年
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>

int main()
{
	int i = 0;
	int count = 0;
	for (i = 1000;i <= 2000;i++)
	{
		if ((i % 4 == 0) && (i % 100 != 0)||(i%400==0))
		{
			printf("%d ", i);
			count++;
		}
    }
	printf("\ncount=%d ", count);
	return 0;
}

在这里插入图片描述

10. 打印100-200之间的素数
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>

int main()
{
	int i = 0;
	int j = 0;
	for (i = 100;i <= 200;i++)
	{
		for (j = 2;j < i;j++)//用2-i-1之间的数看能否整除
		{
			if (i % j == 0)
				break;
		}
		if (i == j)
		{
			printf("%d ", i);
		}
	}
	return 0;
}

//改进,若m=a*b,则a和b中一定有一个数<=sqrt(m)
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<math.h>
int main()
{
	int i = 0;
	int j = 0;
	int count = 0;
	for (i = 100;i <= 200;i++)//也可改成(i=101;i<=200;i+=2)直接排除偶数
	{
		int flag = 1;
		for (j = 2;j <= sqrt(i);j++)//sqrt()为开平方根,需使用头文件<math.h>
		{
			if (i % j == 0)
			{
				flag = 0;
				break;
			}
		}
		if (flag==1)
		{
			printf("%d ", i);
			count++;
		}
	}
	printf("\ncount=%d", count);
	return 0;
}

在这里插入图片描述

11. 编写程序数一下1-100出现多少个数字9
#include<stdio.h>
#include<string.h>

int main()
{
	int i = 0;
	int count = 0;
	for (i = 1;i <= 100;i++)
	{
		if (i % 10 == 9)
		{
			count++;
		}
		if (i / 10 == 9)
		{
			count++;
		}
	}
	printf("%d", count);
	return 0;
}

在这里插入图片描述

12. 计算1/1-1/2+1/3-1/4+1/5-…+1/99-1/100的值,打印出结果
//方法1
#include<stdio.h>
#include<string.h>

int main()
{
	int i = 0;
	double sum = 0;
	
	for (i = 1;i <= 100;i++)
	{
		if (i % 2 == 0)
		{
			sum -= 1.0 / i;
		}
		else
		{
			sum += 1.0 / i;
		}
	}
	printf("%lf\n", sum);
	return 0;
}

//方法2
int main()
{
	int i = 0;
	double sum = 0;
	int flag = 1;
	for (i = 1;i <= 100;i++)
	{
		sum += flag * 1.0 / i;
		flag = -flag;
	}
	printf("%lf\n", sum);
	return 0;
}

在这里插入图片描述

13. 求10个整数中的最大值
#include<stdio.h>
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int max = arr[0];//既可以求正数也可以求负数
	int i = 0;
	for (i = 0;i < 10;i++)
	{
		if (arr[i > max])
		{
			max = arr[i];
		}
	}
	printf("%d\n", max);
	return 0;
}

在这里插入图片描述

14. 打印9*9乘法口诀表
#include<stdio.h>
int main()
{
	int i = 0;
	int j = 0;
	for (i = 1;i <= 9;i++)
	{
		for (j = 1;j <= i;j++)
		{
			printf("%d*%d=%-2d ", i, j, i * j);//%2d可以打印两位,%-2d可以左对齐
		}
		printf("\n");
	}
	return 0;
}

在这里插入图片描述

15. 模拟输入密码
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>

int main()
{
	int i = 0;
	char password[20] = { 0 };
	for (i = 0; i < 3; i++)
	{
		printf("请输入密码:");
		scanf("%s", password);
		if (strcmp(password, "777") == 0)//strcmp比较的是对应字符的ASCII大小
		{
			printf("密码正确\n");
				break;
		}
		else
		{
			printf("密码错误\n");
		}
	}
	if (i == 3)
	{
		printf("三次密码错误,退出程序");
	}
	return 0;
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值