C语言第二课,分支语句和循环语句

1.什么是语句?

C语句可分为以下五类:

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

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

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

2.分支语句

单分支语句-if

C语言中,0表示假,非0表示真。如果表达式结果为真(age >= 18),表示执行该条件下的语句:printf(“成年\n”);

int main()
{
	int age = 0;
	scanf_s("%d", &age);
	//单分支
	if (age >= 18)
		printf("成年\n");
	return 0;
}

多分支语句-if-else

双分支语句:

int main()
{
	int age = 0;
	scanf_s("%d", &age);
	
	//双分支
	if (age >= 18)
		printf("成年\n");
	else
		printf("未成年\n");

}

多分支语句:

int main()
{
	//多分支
	if (age < 18)
		printf("少年\n");
	else if (age >= 18 && age < 40)
		printf("青年\n");
	else if (age >= 40 && age < 60)
		printf("壮年\n");
	else
		printf("老年\n");
	return 0;
}

默认情况下,if后面只能跟一条语句,如果有两条,需要加上大括号。例如上面的程序为了更加清晰,可以做如下修改。

int main()
{
	int age = 0;
	scanf_s("%d", &age);
	//双分支
	if (age >= 18)
		{
			printf("成年\n");
		}
	else
		{
			printf("未成年\n");
		}
	return 0;
}

if语句总是和他最近的else语句配对。如果代码写法不规范,就会产生误解。
代码的书写风格非常的重要,如果你写出了下面的代码,估计你去面试,面试官直接把你刷掉了!!那么如何培养自己写代码的风格呢,这里我推荐一本书,《高质量的C++/C编程》。

int main()
{
int a = 0;
int b = 2;
if (a == 1)
if (b == 2)
printf("hehe\n");
else
printf("haha\n");//编译器会把这一个else自动对齐
return 0;
}

对于判断条件,我有一个小小的建议:if(num == 5),如果我写成了if(num =5),代码任然可以运行,如果我写成 if(5 ==num),那么即使我少写了一个等号,代码就会报错,更容易发现问题。

int main()
{
    int a = 10;
    if (5 = a)
    {
        printf("hehe\n");
    }
    return 0;
}

例如这个题目
BC44 判断整数奇偶性

#include<stdio.h>
int main()
{
    int a=0;
    while(~scanf("%d",&a))
    {
        if(a%2==1)
            printf("Odd\n");
        else
            printf("Even\n");
    }
    return 0;
}

switch-break语句

比如:
输入1,输出星期一
输入2,输出星期二
输入3,输出星期三
输入4,输出星期四
输入5,输出星期五
输入6,输出星期六
输入7,输出星期日
那我没写成 if…else if …else if 的形式太复杂,那我们就得有不一样的语法形式这就是switch 语句。
case 后面必须是整型表达式!

int main()
{
    int day = 0;
    scanf("%d", &day);
    switch (day)
    {
    case 1:
        printf("Monday"); break;
    case 2:
        printf("Tuesday"); break;
    case 3:
        printf("Wensday"); break;
    case 4:
        printf("Thurday"); break;
    case 5:
        printf("Friday"); break;
    case 6:
        printf("Saturday"); break;
    case 7:
        printf("Sunday"); break;
    }
    return 0;
}

case语句后面不是一定要加上break的,不加break目的就是让程序继续执行,下面来一个后面不加break的程序。
输入1-5,输出的是“weekday”; 输入6-7,输出“weekend”

int main()
{
    int day = 0;
    scanf("%d", &day);
    switch (day)
    {
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
        printf("weekday"); break;
    case 6:
    case 7:
        printf("weekend"); break;
    }
    return 0;
}

default语句

当 switch 表达式的值并不匹配所有 case 标签的值时,这个 default 子句后面的语句就会执行。
所以,每个switch语句中只能出现一条default子句。
没有规定case必须在default之前,一般case最好放在default之前。

int main()
{
    int day = 0;
    scanf("%d", &day);
    switch (day)
    {
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
        printf("weekday"); break;
    case 6:
    case 7:
        printf("weekend"); break;
    default:
        printf("输入有误,请输入1~7的数字!");//这个语句可前可后
        break;
    }
    return 0;
}

循环语句

while

当条件满足的情况下,if语句后的语句执行,否则不执行。但是这个语句只会执行一次。

由于我们发现生活中很多的实际的例子是:同一件事情我们需要完成很多次。
那我们怎么做呢?C语言中给我们引入了: while 语句,可以实现循环。
例:打印1~10之间的整数。

int main()
{
    int i = 0;
    while (i < 10)
    {
        printf("%d ", i);
        i++;
    }
    return 0;
}
while中的break和continue

break在循环中,永远终止循环。

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

continue,跳过当前循环。

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

这里顺便介绍一下缓冲区(Buffer):就是在内存中预留指定大小的存储空间用来对I/O的数据做临时存储,这部分预留的内存空间。
例如,我是用scanf函数来接收一个字符串,我输入的是12345‘\n’,这些输入会被放入缓存区。scanf函数会把这12345拿走,留下了一个’\0’在缓存区。而getchar通常用来清理缓存区,getchar拿走这个’\n’赋值给了ch,直接导致我还没有输入程序,就会爆出确认失败。

正确的改法应该是在空的那一行加上getchar();

int main()
{
	char input[20] = { 0 };
	printf("请输入密码:>");
	scanf("%s", input);//数组名不用取地址,因为他本来就是一个地址
	
	printf("请确认密码(Y/N:>");
	int ch = getchar();//这里的代码有误,getchar和scanf都会从缓冲区拿字符串,而之间输入的 回车,被getchar拿走了
	if (ch == 'Y')
	{
		printf("确认成功");
	}
	else
	{
		printf("确认失败");
	}

	return 0;
}

其实,这个代码还可以再优化一下:比如我输入的密码为12345 678,中间有一个空格,任然会出现错误。再次优化代码就不会出现问题了。

int main()
{
	char input[20] = { 0 };
	printf("请输入密码:>");
	scanf("%s", input);
	//清理缓冲区
	int tmp = 0;
	while ((tmp = getchar()) != '\n')
	{
		;//空语句
	}
	printf("请确认密码(Y/N:>");
	int ch = getchar();
	if (ch == 'Y')
	{
		printf("确认成功");
	}
	else
	{
		printf("确认失败");
	}
	return 0;
}

getchar获取一个字符,
当getchar读取失败的时候,返回一个EOF。按住Ctrl键,然后单击鼠标,可以看到EOF的定义:定义为-1。

int main()
{
	int ch = 0;
	while ((ch = getchar()) != EOF)
	{
		putchar(ch);
	}
	return 0;
}

运行结果

for

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

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

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

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

例:打印1~10的整数

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

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

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

建议:

  1. 不可在for 循环体内修改循环变量,防止 for 循环失去控制。
int main()
{
	int i = 0;
	int j = 0;
	for (i = 0; i < 3; i++)
	{
		for (j = 0; j < 3; j++)
		{
			printf("hehe\n");
		}
	}
	return 0;
}//打印9个hehe

失去控制了,只打印三个呵呵

int main()
{
	int i = 0;
	int j = 0;
	for (; i < 3; i++)
	{
		for (; j < 3; j++)
		{
			printf("hehe\n");
		}
	}
	return 0;
}//打印9个hehe
  1. 建议for语句的循环控制变量的取值采用“前闭后开区间”写法。这样代码的可读性会更高一些
    for (i = 0; i < 3; i++);这里面的i<3,刚好表示三次循环。如果写成for (i = 0; i < =2; i++),大可不必!

不过无论如何,for语句,yyds!!!

do while

就是把while循环倒过来写了,先执行里面的调整部分,再执行判断语句。
如果这里面也有break和continue会发生什么呢?
break:

int main()
{
	int i = 0;
	do
	{
		if (i == 5)
			break;//break 只能跳出自己所在的循环
		printf("%d ", i);
		i++;
	} while (i<10);
}//输出0 1 2 3 4

continue:输出 0 1 2 3 4 ,然后进入死循环。因为i=5时,跳过了这个循环,没有变成6,又一次进入了这个循环。此时程序其实很忙。

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

练习题

求素数的程序:
求平年闰年的程序:
3 求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;
}

4 求阶层的累加:

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

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

写出来也不要太骄傲。

5 查找具体的某一个数字n
方法一:顺序遍历

int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int k = 7;

	int i = 0;
	for (i = 0; i < 10; i++)
	{
		if (arr[i] == k)
		{
			printf("找到了,下标是%d\n", i);
			break;
		}
	}
	if (i == 10)
	{
		printf("没找到\n");
	}
	return 0;
}

方法二:折半查找,但是对于无序的数是行不通的。

int main()
{
	int arr[] = {1,2,3,4,5,6,7,8,9,10};
	int k = 7;
	int sz = sizeof(arr) / sizeof(arr[0]);
	//         40           4
	int left = 0;
	int right = sz - 1;
	int mid = (left + right) / 2;

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

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

#include<string.h>
#include<Windows.h>
int main()
{
//	char arr[] = "abc";
	//            [a b c \0]
	//  下标       0 1 2
	char arr1[] = "hello bit!!!!!!!";
	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(1000);//单位是毫秒,需要调用Windows.h
		system("cls");//windows+R 打开的窗口,窗口命令clc可以清空屏幕。
		left++;
		right--;
	}
	printf("%s\n", arr2);
	return 0;
}

7 编写代码实现,模拟用户登录情景,并且只能登录三次。
仅仅只模仿了他的逻辑,真实的情况是:密码会加密放入数据库中。

#include<stdio.h>
#include<string.h>
int main()
{
	int i = 0;
	char password[20] = "";//初始化的时候也要动脑筋

	for (i = 0; i < 3; i++)
	{
		printf("请输入密码:");
		scanf("%s",password );//数组名本来就是地址
		//if (password == "123456")//比较两个字符串是否相等,不能使用==,必须使用strcmp这个函数
		//{

		//}
		if ((strcmp(password, "123456"))==0)
		{
			printf("登录成功\n");
			break;
		}
		else
			printf("密码错误!\n");
	}
	if (3 == i)
	{
		printf("三次均错误,退出程序\n");
	}
	return 0;
}

go to 语句

C语言中提供了可以随意使用的 goto语句和标记跳转的标号。
从理论上 goto语句是没有必要的,实践中没有goto语句也可以很容易的写出代码。
但是某些场合下goto语句还是用得着的,最常见的用法就是终止程序在某些深度嵌套的结构的处理过
程。
多层循环这种情况使用break是达不到目的的。它只能从最内层循环退出到上一层的循环,而goto语句可以实现一次跳出多个循环。

这里写一个关机程序,只要程序启动,就倒计60s关机,输入:“我傻逼了”才能取消关机。
关机命令:shutdown
60s内关机:shutdown -s -t 60
取消关机命令:shutdown -a

#include<stdlib.h>
#include<string.h>
int main()
{
	char input[20] = { 0 };
	system("shutdown -s -t 60");
again:
	printf("请注意,你的电脑在1min内关机,输入'我傻逼了',就取消关机");
	scanf("%s", input);
	//判断
	if (strcmp(input, "我傻逼了") == 0)
	{
		//取消关机
		system("shutdown -a");
	}
	else
	{
		goto again;//使用的goto语句
	}
	return 0;
}

只需要把编译生成的exe文件,改个名字再发给你的好友,就可以整蛊对方了!
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值