【C语言】——分支语句和循环语句

目录

1.什么是语句

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

2.1 if语句

2.1.1悬空else

2.1.2 if书写形式的对比

2.2switch语句

2.2.1 在switch语句中的 break

2.2.2 default子句

2.2.3 练习

3. 循环语句

3.1.1 while语句中的break和continue

3.2for循环

3.2.1 语法

3.2.2 break和continue在for循环中

3.2.3 for语句的循环控制变量

3.2.4 一些for循环的变种

3.2.5一道笔试题

3.3 do...while()循环

3.3.1 do语句的语法:

3.3.3 do语句的特点

3.3.4 do while循环中的break和continue

3.4练习

4. goto语句


1.什么是语句

C语句可分为以下五类:
1. 表达式语句
2. 函数调用语句
3. 控制语句
4. 复合语句
5. 空语句
控制语句 用于控制程序的执行流程,以实现程序的各种结构方式
(C语言支持三种结构:顺序结构、选 择结构、循环结构),
它们由特定的语句定义符组成,C 语言有九种控制语句。
可分成以下三类:
1. 条件判断语句也叫分支语句:if语句、switch语句;
2. 循环执行语句:do while语句、while语句、for语句;
3. 转向语句:break语句、goto语句、continue语句、return语句。

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

2.1 if语句

语法结构:
if(表达式)
    语句;


if(表达式)
    语句1;
else
    语句2;



//多分支    
if(表达式1)
    语句1;
else if(表达式2)
    语句2;
else
    语句3;

代码演示:


#include <stdio.h>
//代码1
int main()
{
	int age = 0;
	scanf("%d", &age);
	if (age < 18)
	{
		printf("未成年\n");
	}
}


//代码2
#include <stdio.h>
int main()
{
	int age = 0;
	scanf("%d", &age);
	if (age < 18)
	{
		printf("未成年\n");
	}
	else
	{
		printf("成年\n");
	}
}


//代码3
#include <stdio.h>
int main()
{
	int age = 0;
	scanf("%d", &age);
	if (age < 18)
	{
		printf("少年\n");
	}
	else if (age >= 18 && age < 30)
	{
		printf("青年\n");
	}
	else if (age >= 30 && age < 50)
	{
		printf("中年\n");
	}
	else if (age >= 50 && age < 80)
	{
		printf("老年\n");
	}
	else
	{
		printf("老寿星\n");
	}
}
如果表达式的结果为真,则语句执行。
C语言中如何表示真假?
0表示假,非0表示真。
如果条件成立,要执行多条语句,怎应该使用代码块
 
#include <stdio.h>
int main()
{
	if (表达式)
	{
		语句列表1;
	}
	else
	{
		语句列表2;
	}
	return 0;
}


//这里的一对 { } 就是一个代码块。

2.1.1悬空else

当你写了这个代码:
#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;
}

//else具有就近原则,会和最近的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;
}

总结:

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

2.1.2 if书写形式的对比

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


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


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


//代码4
int num = 1;
if (5 == num)
{
	printf("hehe\n");
}
代码 2 和代码 4 更好,逻辑更加清晰,不容易出错。

2.2switch语句

switch 语句也是一种分支语句。
常常用于多分支的情况。
switch(整型表达式)
{
    语句项;
}

//语句项是什么呢?

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

2.2.1 switch语句中的 break

switch 语句中,我们没办法直接实现分支,搭配 break 使用才能实现真正的分支。
比如:
#include <stdio.h>
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;
	}
	return 0;
}
有时候我们的需求变了:
1. 输入 1-5 ,输出的是 “weekday”;
2. 输入 6-7 ,输出 “weekend”
所以我们的代码就应该这样实现了:
#include <stdio.h>
//switch代码演示
int main()
{
	int day = 1;
	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:
				break;
	}
	return 0;
}

default是默认选项,就是上面的1~7都不满足的话,就是满足默认选项
总结:
break语句 的实际效果是把语句列表划分为不同的分支部分。
break的实际效果是跳出当前语句
编程好习惯:
在最后一个 case 语句的后面加上一条 break 语句。
(之所以这么写是可以避免出现在以前的最后一个 case 语句后面忘了添加 break 语句)。

2.2.2 default子句

如果表达的值与所有的 case 标签的值都不匹配怎么办?
其实也没什么,结构就是所有的语句都被跳过而已。
程序并不会终止,也不会报错,因为这种情况在 C 中并不认为是个错误。
但是,如果你并不想忽略不匹配所有标签的表达式的值时该怎么办呢?
你可以在语句列表中增加一条 default 子句,把下面的标签
default
写在任何一个 case 标签可以出现的位置。
switch 表达式的值并不匹配所有 case 标签的值时,这个 default 子句后面的语句就会执行。
所以,每个 switch 语句中只能出现一条 default 子句。
但是它可以出现在语句列表的任何位置,而且语句流会像执行一个 case 标签一样执行 default 子句。
编程好习惯
在每个 switch 语句中都放一条 default 子句是个好习惯,甚至可以在后边再加一个 break

2.2.3 练习

#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;
		}
	case 4:
		m++;
		break;
	default:
		break;
	}
	printf("m = %d, n = %d\n", m, n);//m=5,n=3
	return 0;
}

3. 循环语句

while
for
do while

3.1while循环

由于我们发现生活中很多的实际的例子是:同一件事情我们需要完成很多次。
那我们怎么做呢?
C 语言中给我们引入了: while 语句,可以实现循环。
//while 语法结构
while(表达式)
 循环语句;
比如我们实现:
在屏幕上打印1-10的数字。
#include <stdio.h>
int main()
{
	int i = 1;
	while (i <= 10)
	{
		printf("%d ", i);//1 2 3 4 5 6 7 8 9 10
		i = i + 1;
	}
	return 0;
}

3.1.1 while语句中的break和continue

//break 代码实例
#include <stdio.h>
int main()
{
	int i = 1;
	while (i <= 10)
	{
		if (i == 5)
		{
			break;
		}
		printf("%d ", i);//1 2 3 4
		i = i + 1;
	}
	return 0;
}

总结:

break在while循环中的作用:

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

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

也就是跳过循环的末尾

也就是跳过整个循环

//continue代码实例
#include <stdio.h>
int main()
{
	int i = 1;
	while (i <= 10)
	{
		if (i == 5)
		{
			//break;
			continue;
		}
		printf("%d ", i);// 1 2 3 4 死循环
		i = i + 1;
	}
	return 0;
}

总结:

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

也就是跳到循环的开头

再看看几个代码:

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


//这里的代码适当的修改是可以用来清理缓冲区的.
//代码2
#include <stdio.h>
int main()
{
    char ch = '\0';
    while ((ch = getchar()) != EOF)
    {
        if (ch < '0' || ch > '9')
            continue;
        putchar(ch);
    }
    return 0;
}
//这个代码的作用是:只打印数字字符,跳过其他字符的、

//getchar是一次读取一个字符
///putchar是一次写出一个字符
int main()
{
	char password[20] = { 0 };
	printf("请输入密码:>");
	scanf("%s", password);
	//清理\n和空格
	while (getchar() != '\n')
	{
		;
	}

	printf("请确认密码(Y/N):");
	int ch = getchar();
	if (ch == 'Y')
	{
		printf("确认成功\n");
	}
	else
	{
		printf("确认失败\n");
	}

	return 0;
}

3.2for循环

3.2.1 语法

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

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

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

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

实际的问题:

使用for循环 在屏幕上打印1-10的数字。

#include <stdio.h>
int main()
{
	int i = 0;
	for(i=1/*初始化*/; i<=10/*判断部分*/; i++/*调整部分*/)
	for (i = 1; i <= 10; i++)
	{
		printf("%d ", i);//1 2 3 4 5 6 7 8 9 10
	}
	return 0;
}

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


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


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

总结:

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

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

3.2.2 break和continue在for循环中

我们发现在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);//1 2 3 4
	}
	return 0;
}


//代码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;
}

3.2.3 for语句的循环控制变量

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

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

int i = 0;
//前闭后开的写法
//i在0处可以取等号,i在10处不能取等号
for(i=0; i<10; i++)
{}



//两边都是闭区间
//i在0处可以取等号,i在10处也能取等号
for(i=0; i<=9; i++)
{}

3.2.4 一些for循环的变种

#include <stdio.h>
int main()
{
    //代码1
    for (;;)//省略判断部分,恒为真,就死循环了
    {
        printf("hehe\n");
    }
    //for循环中的初始化部分,判断部分,调整部分是可以省略的,但是不建议初学时省略,容易导致问题。

        //代码2
    int i = 0;
    int j = 0;
    //这里打印多少个hehe?
    //循环嵌套
    for (i = 0; i < 10; i++)
    {
        for (j = 0; j < 10; j++)
        {
            printf("hehe\n");//100个hehe
        }
    }

    //代码3
    int i = 0;
    int j = 0;
    //如果省略掉初始化部分,这里打印多少个hehe?
    for (; i < 10; i++)
    {
        for (; j < 10; j++)
        {
            printf("hehe\n");//10个hehe
        }
    }

    //代码4-使用多余一个变量控制循环
    int x, y;
    for (x = 0, y = 0; x < 2 && y < 5; ++x, y++)
    {
        printf("hehe\n");
    }
    return 0;
}

3.2.5一道笔试题

//请问循环要循环多少次?
#include <stdio.h>
int main()
{
    int i = 0;
    int k = 0;
    for (i = 0, k = 0; k = 0; i++, k++)
    {
        k++;
    }
    return 0;
}
//循环0次,k被赋值成0,循环一次都不会进去

3.3 do...while()循环

3.3.1 do语句的语法:

do
 循环语句;
while(表达式);

3.3.3 do语句的特点

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

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


int main()
{
	int i = 1;
	do
	{
		printf("%d\n", i);
		i++;
	} while (i < 10);
	return 0;
}

3.3.4 do while循环中的break和continue


#include <stdio.h>
int main()
{
    int i = 1;

    do
    {
        if (5 == i)
            break;
        printf("%d\n", i);//1 2 3 4
        i++;
    } while (i < 10);

    return 0;
}



#include <stdio.h>
int main()
{
    int i = 1;

    do
    {
        if (5 == i)
            continue;
        printf("%d\n", i);//1 2 3 4 死循环
        i++;
    } while (i < 10);

    return 0;
}

3.4练习

1. 计算 n的阶乘。

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

	printf("%d\n", ret);

	return 0;
}

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

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

	return 0;
}


//优化
int main()
{
	int n = 0;
	int i = 0;
	int ret = 1;
	int sum = 0;
	for (n = 1; n <= 3; n++)
	{
		ret = ret * n;
		sum = sum + ret;
	}

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

	return 0;
}

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

int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int sz = sizeof(arr) / sizeof(arr[0]);//数组的元素个数
	int left = 0;
	int right = sz-1;
	int k = 0;
	scanf("%d", &k);

	while (left<=right)
	{
		//int mid = (left + right) / 2;
		int mid = left + (right - left) / 2;
		if (arr[mid] < k)
		{
			left = mid + 1;
		}
		else if (arr[mid] > k)
		{
			right = mid - 1;
		}
		else
		{
			printf("找到了,下标是:%d\n", mid);
			break;
		} 
	}
	if (left > right)
		printf("找不到\n");

	return 0;
}

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

//welcome to aaa!!!!!
//###################
//w#################!
//we###############!!
//wel#############!!!
//..
//welcome to bit!!!!!

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

int main()
{
	char arr1[] = "welcome to aaa!!!!!";
	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);

		Sleep(100);//window下Sleep函数参数的单位是毫秒
		system("cls");//清理屏幕
		left++;
		right--;
	}
	printf("%s\n", arr2);

	return 0;
}

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

//假设正确的密码是:"123456"
//string compare - strcmp
#include <string.h>


//strcmp 的返回值
//>0 
//<0 
//==0
int main()
{
	int i = 0;
	char password[20] = { 0 };
	for (i = 0; i < 3; i++)
	{
		printf("请输入密码:>");
		scanf("%s", password);
		//判断密码正确性
		if (strcmp(password, "123456") == 0)
		{
			printf("密码正确,登陆成功\n");
			break;
		}
		else
		{
			printf("密码错误\n");
		}
	}

	if (i == 3)
	{
		printf("三次密码错误,退出程序\n");
	}
	return 0;
}

总结:

C语言中有字符串吗?  ---有   " "

C语言中有字符串类型吗?  没有

C++有字符串类型 string

6.猜数字游戏的实现

//猜数字游戏实现

//
//电脑随机生成一个1~100之间的数字
//猜数字
//如果你猜小了,告知猜小了
//如果你猜大了,告知猜大了
//如果你猜对了,告知猜对了

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

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

//rand函数可以生成随机数
//返回一个0~RAND_MAX(32767)
void game()
{
	int guess = 0;
	//1. 生成随机数
	int ret = rand()%100+1;//0~99-->1~100
	//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;
		}
	}
}

int main()
{
	int input = 0;
	//设置随机数的生成器
	srand((unsigned int)time(NULL));//srand每个工程中只需要执行一次就行了
									//srand和rand的使用基本上是固定的
	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;
}

4. goto语句

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

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

但是某些场合下goto语句还是用得着的,

最常见的用法就是终止程序在某些深度嵌套的结构的处理过程。

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

多层循环这种情况使用break是达不到目的的。

它只能从最内层循环退出到上一层的循环。

goto语句的随意性,使得代码不连贯,也容易出现一些隐患

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

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

下面是使用goto语句的一个例子,

然后使用循环的实现方式替换goto语句: 一个关机程序

goto方式的循环:

#include <stdio.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;
}

while方式的循环

#include <stdio.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;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

待己以诚

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

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

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

打赏作者

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

抵扣说明:

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

余额充值