C语言选择语句和循环语句

条件判断

        0表示假,非0表示真。条件成立为1,条件不成立为0。

        布尔类型,false表示假,true表示真。

选择语句

if

        根据条件判断是否选择执行,选择语句中,如果执行了一条分支后,别的分支不再进去。if语句默认后面只跟一条语句,如果需要跟多条语句,需要加 {} 。

选择语句的三种情况

单分支

if (条件判断)

{

        执行语句;

}

int a = 20;
int b = 10;
if (a > b)
{
    printf("a 大于 b");
}

对立分支

if (条件判断)

{

        执行语句1;

}

else

{

        执行语句2;

}

int a = 20;
int b = 10;
if (a > b)
{
    printf("a 大于 b");
}
else
{
    printf("a 小于等于 b");
}

多分支 

if (条件判断)

{

        执行语句1;

}

else if (条件判断)        //可以写多个

{

        执行语句2;

}

else        //根据情况是否需要,并不是一定有else

{

        

}

int a = 20;
int b = 10;
if (a > b)
{
    printf("a 大于 b");
}
else if (a < b)
{
    printf("a 小于 b");
}
else
{
    printf("a 等于 b");
}

分支语句可以嵌套使用

if (条件判断)

{

        执行语句1;

        if (条件判断)

        {

                执行语句;

        }

        执行语句2;

}

易错点

        请问这个输出的结果是什么?

int a = 20;
int b = 10;

if (a < b)
    if(b)
        printf("%d\n", b);
else
    printf("%d\n", a);

        答案是没有输出,因为else是和第二个if匹配的,第一个if的条件不满足,不进入。if和else没有明确使用 {} ,可能会出现理解错误 ,else是和最近的if匹配的,并不是和对齐的匹配的。养成良好的代码风格(可以阅读一下电子版的高质量 C++/C 编程),写选择语句的时候最好加上 {} 。(注:if没加 {} 的时候只能跟一条语句,这里的if else 是一条语句,因为只会执行其中一条。)

        请问这两个代码的test函数有没有区别

int test()
{
	int a = 10;
	if (a > 0)
	{
		return a;
	}
	return 0;
}

int main()
{
	int n = test();

	return 0; 
}
int test()
{
	int a = 10;
	if (a > 0)
	{
		return a;
	}
	else
	{
		return 0;
	}
}

int main()
{
	int n = test();

	return 0; 
}

        答案是没有区别,虽然第一个代码的return 0 没有带else,但是这两个return本质上就只会执行一个,条件满足,函数返回a就结束,代码不会执行到第二个return的地方。

        请问代码输出的结果是什么。(因为板书问题,有时候不会加上 {} )

int a = 100;
if(a = 10)
    printf("%d", a);
    
return 0;

        答案是输出 10 。条件判断是一个赋值表达式,将10赋值给a,已经改变了a的值,非0为真,执行代码。如果判断两个数是否相等,并且有一个是常量的时候,可以把常量写在左边,常量具有常属性,不能修改值,编译错误,很容易发现问题。

int a = 100;
if(10 == a)
    printf("%d", a);
    
return 0;

switch

        常使用于多分支语句。

switch(整型表达式)

{

case 整型常量表达式:

        执行语句;

        break; //break都是根据情况是否需要加

default:

        //处理不存在的情况。

        break;

}

        整型表达式可以有变量,整型常量表达式不能不变量,都不能出现浮点数。

        case和default没有顺序要求,在哪都行,一般default会在最坏。

        break的作用是执行完对应的case语句后,退出swtich选择语句。如果没有break,代码会从上往下执行,default的语句也会执行,直到遇到break,或者swtich结束。

#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;
	default:
		printf("输入错误\n");
		break;
	}

	return 0; 
}

        break按需写。

#include <stdio.h>

int main()
{
	int day = 0;
	scanf("%d", &day);
	switch (day)
	{
	case 1:
	case 2:
	case 3:
	case 4:
	case 5:
		printf("工作日\n");
		break;
	case 6:
	case 7:
		printf("休息日\n");
		break;
	default:
		printf("输入错误\n");
		break;
	}
	return 0; 
}

        switch可以嵌套使用

switch (整型表达式)

{

case 整型常量表达式:

        switch (整型表达式)

        {

        case 整型常量表达式:

                执行语句;

        }

......

}

循环语句

while

        条件成立进入循环,执行循环语句,条件不成立,不进入循环。

while (条件判断) {循环语句;}

#include <stdio.h>

int main()
{
	int n = 0;
	while (n < 5)
	{
        printf("%d ", n);
		n++;
	}
	return 0; 
}

        break的作用是直接退出循环。

#include <stdio.h>

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

        程序输出0 1 2,if条件成立,执行break,结束循环。 

        continue的作用是跳过本次循环后面的循环语句。

#include <stdio.h>

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

        程序输出0 1 2之后进入死循环,当n的值为3的时候,if条件成立,continue跳过本次循环后面的循环语句,程序无法来到改变n的位置,n一直是3,程序死循环。 

        如果n++在continue之前出现

#include <stdio.h>

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

        程序输出结果是1 2 4 5。 

        在牛客网刷题可能会遇到多组输入的情况。

int n = 0;

while (scanf("%d", &n) != EOF) {        }

#include <stdio.h>

int main()
{
	int n = 0;
	while (scanf("%d", &n) != EOF)
	{
		printf("%d\n", n);
	}
	return 0;
}

        scanf库函数的返回类型是int类型的,当scanf读取数据成功的时候,会返回读取的个数,如果读取数据失败,会返回EOF(end of file)——文件结束标志,本质是-1。按住键盘的 ctrl 加 z ,然后回车就会让scanf读取数据失败,scanf返回EOF。(注:在VS2019要ctrl 加 z 回车连续三次才会结束。) 

        getchar的功能是读取一个字符,读取成功就返回读取的字符,读取数据失败也会返回EOF,结束也是ctrl 加 z 然后回车。getchar的返回类型是int类型的,因为EOF(-1)是整型,所以需要int类型作为返回类型。

#include <stdio.h>

int main()
{
	char password[15];
	scanf("%s", password);
	printf("%s\n", password);
	printf("请输入 Y/N 确认密码\n");
	int n = getchar();
	if ('Y' == n)
		printf("确认成功\n");
	else if ('N' == n)
		printf("确认失败\n");
	else
		printf("输入错误\n");
	return 0;
}

        这个程序在你输入密码之后,会直接确认失败,键盘输入的数据会先到缓冲区中,输入的回车也是一个字符 '\n' ,它也进入到了缓冲区,再从缓冲区提取数据到password数组中,但是不会提取字符 '\n',getchar提取字符,发现缓冲区还有数据就直接提取了,以至于我们还没有输入Y或者N就结束了。

#include <stdio.h>

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

        不单单用一个getchar清理 '\n' ,是因为scanf的%s的输入格式,不能提取空格和回车,如果输入为abcd空格1234回车,那么password数组只会提取abcd,而空格1234回车\n会留在缓冲区中,一个getchar不能解决问题。

for

for(单次表达式; 条件判断; 末尾循环体) {循环语句;}

        for循环与while循环相比,for循环更加方便控制,for 循环将循环变量的初始化、条件判断和循环变量调整都放在了一行。

#include <stdio.h>

int main()
{
    // for循环里面定义的i,出了循环销毁
	for (int i = 0; i < 5; i++)
	{
		printf("%d ", i);
	}
	return 0;
}

        break退出for循环的效果跟while循环一样。

#include <stdio.h>

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

        程序输出0 1 2,然后退出循环结束。 

        continue跳过本次循环后面的循环语句,但是不跳过循环变量调整部分

#include <stdio.h>

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

        程序输出0 1 2 4,循环结束。

        建议不要在for循环内部改变循环变量,防止循环变量无法控制。

        for循环的判断条件省略了,判断条件恒为真。

易错

1.

for (; ;)
{
    printf("%d ", 1);
}

        程序死循环,一直打印。

2.

#include <stdio.h>

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

        程序输出0 1 2 3 4,都是在i为0进入第二个for循环输出的,第二次没有进入第二个for循环,是因为j第一个for出了之后,j已经是5了,条件不成立。

do while循环

do {循环语句;} while (条件判断);

        先进入循环体执行循环语句,再判断条件是否进入循环。

#include <stdio.h>

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

        break退出循环

#include <stdio.h>

int main()
{
	int n = 0;
	do
	{
		if (3 == n)
			break;
		printf("%d ", n);
		n++;
	} while (n < 5);
	return 0;
}

        程序输出0 1 2,if条件成立,执行break,退出循环结束。 

        continue跳过本次循环后面的循环语句。

#include <stdio.h>

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

        程序输出0 1 2之后进入死循环,当n的值为3的时候,if条件成立,continue跳过本次循环后面的循环语句,n无法改变,一直是3,导致程序死循环。 

练习

1.输入一个数(非负数),计算N的阶乘。

2.输入一个数(非负数),计算1! + 2! + ... + N!

3.打印100-200的素数。

4.一个整型数组中,有序数组1,2,3,4,5,输入一个数,使用二分算法查找下标,找到了打印下标,找不到打印找不到。

练习答案

1.

#include <stdio.h>

int main()
{
	int n = 0;
	int sum = 1;
	printf("请输入一个数(非负数)\n");
	scanf("%d", &n);
	for (int i = 1; i <= n; i++)
		sum *= i;
	printf("%d的阶乘是%d\n", n, sum);
	return 0;
}

        整型最大值是0x7FFFFFFF,阶乘大于这个数存储在整型是错误的数据。

2.

#include <stdio.h>

int main()
{
	int n = 0;
	int factorial = 1;
	int sum = 0;
	printf("请输入一个数(非负数)\n");
	scanf("%d", &n);
	//sum先计算i的阶乘,然后add再把每个阶乘加起来
	for (int i = 1; i <= n; i++)
	{
		factorial *= i;
		sum += factorial;
	}
	printf("1的阶乘到%d的阶乘的和是%d\n", n, sum);
	return 0;
}

3. 

#include <stdio.h>

int main()
{
    int i = 0;
    int j = 0;
    // 100-200的范围找素数
    for (i = 100; i <= 200; i++)
    {
        // 从2开始尝试求余,每次加1
        for (j = 2; j < i; j++)
        {
            // 如果求余等于0,证明不是素数
            if (i % j == 0)
            {
                // 结束循环
                break;
            }
        }
        // 如果for循环没有break结束循环,最后会i等于j
        if (i == j)
            printf("%d ", i);
    }

	return 0;
}

优化:

#include <stdio.h>

int main()
{
    int i = 0;
    int j = 0;
    // 100-200的范围找素数
    // i从奇数开始,每次加2
    for (i = 101; i <= 200; i += 2)
    {
        // 从2开始尝试求余,每次加1
        // sqrt是求正平方根,因为找因数最大走到根号i
        for (j = 2; j <= (int)sqrt(i); j++)
        {
            // 定义一个变量,求余为0改变该变量
            int flag = 1
            // 如果求余等于0,证明不是素数
            if (i % j == 0)
            {
                flag = 0;
                break;
            }
        }
        // 求余没有一次为0,是素数
        if (flag == 1)
            printf("%d ", i);
    }

	return 0;
}

4.

#include <stdio.h>

int main()
{
	int arr[] = { 1,2,3,4,5 };
	//sizeof(数组名)计算的整个数组的大小,除以元素的大小,得到元素的个数
	int sz = sizeof(arr) / sizeof(int);
	int l = 0;
	int r = sz - 1;
	int n = 0;
	scanf("%d", &n);
	while (l <= r)
	{
		//有序查找使用二分算法
		//查找中间值最好不要两个相加再除2,如果l和r比较大,相加大于整型的最大值,导致数据错误
		int mid = l + (r - l) / 2;
		//中间的值比查找数大,查找数在mid的左边,需要把r的范围重新限制
		if (arr[mid] > n)
			r = mid - 1;
		//中间的值比查找数小,查找数在mid的右边,需要把l的范围重新限制
		else if (arr[mid] < n)
			l = mid + 1;
		//中间的值和查找值相同
		else
		{
			printf("找到了,下标是%d\n", mid);
			break;
		}
	}
	//如果没有查到,l大于r
	if (l > r)
		printf("找不到\n");
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值