(入门C语言)一、分支语句和循环语句

C语言是结构化的程序设计语言。

因此有了顺序结构选择结构(if、switch、case)循环结构(while、for、do...while)

分支语句:if、switch

循环语句:while、for、do...while

goto语句

1.什么是语句?

C语言语句可以分为以下五类:表达式语句、函数调用语句、控制语句、复合语句、空语句

1.表达式语句和函数调用语句

表达式语句比如b=a+2;函数调用语句是对一个函数直接使用并用该函数的名字表示的语句

2.控制语句

控制语句用于程序的执行流程,以实现程序的各种结构方式(C语言支持三种结构:顺序结构、选择结构、循环结构),他们由特定的语句定义符组成,而C语言有9种控制语句。

可以分为以下三类:

1.条件判断语句也叫分支语句:if语句、switch语句;

2.循环执行语句:do while语句、while语句、for语句;

3.转向语句:break语句、goto语句、continue语句、return语句

分支语句(选择语句)

if(表达式)
 语句;//1

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

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

如果条件成立,表达式中如果不仅仅只有一条语句,需要使用代码块。(但是建议一般书写if else语句带上大括号。)

#include<stdio.h>
int main()
{
if(表达式)
{
语句列表1;
}
else
{
语句列表2;
}
return 0;
}

表达式的判断问题

在C语言如何判断真假?0表示为真,非0表示为假。

同时要注意在表达式中不可以多个判断,可能会导致错误例如

if(age<18)
{
printf("未成年");
}
else if(18<= age <30)
{
printf("青年");
}//如果输入20,会输出青年
//如果输入50,也会输出青年
//因为(18<=age)的值为真,所以为1而(1<30)所以就输出"青年"了

正确写法为:

else if(age>=18 && age<30)

多条语句if else 的使用提醒

if (age < 18)
{
printf("未成年\n");
}
else if (age>=18 && age<30)
{
printf("青年\n");
}
else if (age >= 30 && age < 60)	
{
printf("中年\n");
}
else if (age >= 60 && age < 90)
{
printf("老年\n");
}
else
{
printf("老寿星\n");
}

虽然有很多if else语句,但是执行只会选择一条进行执行。

同时如果条件的数据层次是严格划分的话,那么就不需要前半部分的条件了,因为已经判断过该范围了,不需要再限定了。例如(age >= 30 && age < 60),只需写成(age < 60)。

悬空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组成一个if else语句整体,而不是和外面的if为一个整体。运行程序时,首先进行if条件语句是否等于a==1,如果a不等于1那么无法执行下面的语句,最终什么东西都没有输出。

故可以注意的点是:1.else会与最近的if组成一个整体。2.其次排版也非常重要,空格的合理使用还有缩进 3.同时尽量加上括号书写,避免错误。

if书写形式的对比

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

//代码2
if(condition)
{
    return x;
}
else
{
    return y;
}
//代码1和代码2的表达逻辑是一样的,但是代码1的可读性没有代码2可读性高

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

//代码4
int num = 1;
if(5 == num)
{
    printf("hehe\n");
}
//代码4可以避免=缺失的错误

补充:return的作用

return可以让该函数结束,同时带回值。

int test()
{
	int a = 0;
	scanf("%d", &a);
	if (a > 5)
		return 1;
	else
		return 2;
	printf("hehe3\n");
}
int main()
{
	printf("hehe1\n");
	int ret = test();
	printf("hehe2\n");
	return 0;
}//输入a=8则结果为hehe1、hehe2(ret=1)
//return返回了值为1,而且让函数提前结束了,故不论a等于多少,都无法打印hehe3

switch语句

switch语句也是一种多分支语句。常常用于多分支语句。

switch(整形表达式)
{
    语句项;//case语句表达式:  语句;
}

例:输入1,输出星期一;输入2,输出星期二.....依次类推

int day = 0;
	scanf("%d", &day);
	switch (day)
	{
	case 1:
		printf("星期1\n");
		break;
	case 2:
		printf("星期2\n");
		break;
	case 3:
		printf("星期3\n");
		break;
	case 4:
		printf("星期4\n");
		break;
	case 5:
		printf("星期5\n");
		break;
	case 6:
		printf("星期6\n");
		break;
	case 7:
		printf("星期天\n");
		break;//在最后一个语句的break理论上是不需要写,但是如果后面有做修改可能会忽略掉,从而导致错误所以建议在目标语句结束加上break收尾
	default:
		printf("选择错误\n");
		break;
	}

注意事项:

1、switch括号里的表达式是整形表达式;(如果定义day时int改成float,则会报错)

2、case+空格+整形常量表达式(case后面如果接非整形常量表达式也会报错;但是可以用字符,因为字符的存储是通过ASCII的值存储的,其实是整数,此时switch括号的整形表达式的数据类型可以接char、short、int、long、longlong)如果接多个语句,需要加上大括号。

3、case里面顺序可以乱序,处理时只需按照逻辑进行处理,遇到break结束即可

再例如:星期1-5为工作日,星期6-7为休息日

	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;
		}

如果逻辑相同可以把case罗列在一起。

同时从此看出,case是按照某个点进行判断的(是根据day的值,也就是switch括号里的整形表达式),而if是按照范围判断的。

循环语句

  • while
  • for
  • do...while

3.1while循环

如果有同一件事情需要我们重复多次,那么我们可以用while循环。

总结:break在循环中的作用

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

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

总结:continue在循环的作用

continue是用于终止本次循环的,也就是本次循环中continue后边的代码不会再执行

而是直接跳转到while语句的判断部分。进行下一次循环的入口判断

getchar读取到字符的时候返回的是字符的ASCII码值,如果读取失败,返回的是EOF(EOF的值为-1,ASCII的范围是:0-127)

再看几个代码:

//代码1
#include <stdio.h>
int main()
{
 int ch = 0;
 while ((ch = getchar()) != EOF)
       putchar(ch);
    return 0;
}//这段代码适当的修改是可以来清理缓冲区的

输入函数(scanf、getchar)不是直接从键盘读取数据,而是通过输入缓冲区来读取数据的。

如果缓冲区没有东西,那么调试窗口的光标会一直闪烁等待输入,输入后放入输入缓冲区,你输入A并且按回车确认,此时会打印一个A,之后又把\n放入ch,此时打印\n,所以之后光标在第三行闪烁。

//代码2
#include <stdio.h>
int main()
{
	printf("请输入密码:>");
	char password[20] = { 0 };
	scanf("%s", password);
	//清理缓冲区
	while (getchar() != '\n')
	{
		;
	}//在\n结束
	printf("请确认密码(Y/N):>");
	int ch = getchar();
	if (ch == 'Y')
	{
		printf("确认成功\n");
	}
	else
	{
		printf("确认失败\n");
	}

	return 0;
}

运行结果:

运行过程:首先键盘输入的"123456 abc"进入缓冲区,scanf将缓冲区的内容读入在空格前就结束了,只读入了”123456“,但是后面的“ "和"abc”没有读入,而后面的getchar将缓冲区中的“ ”和“123456”清除了,以至于在输入scanf时,ch没有值,而此时的值需要重新键盘输入,若选择输入"Y"则确认成功。

那么如何解决只在空格前并读把所有输入读完呢?可以修改代码

char arr[20]={0};
scanf("%[^\n]",arr);//读取直到\n
scanf("%d",arr);//原

这样就可以在\n之前写入什么,读入什么。

//代码3
#include <stdio.h>
int main()
{
    char ch = '\0';
    while ((ch = getchar()) != EOF)
    {
        if (ch < '0' || ch > '9')
            continue;
        putchar(ch);
    }
    return 0;
}

此函数的功能:只打印数字字符

for循环

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

{循环语句}

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

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

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

int main()
{
int i = 0 ;
for(i=1;i<=10;i++)
{
if(i==5)
continue;//break;
printf("%d",i);

}

//while和for循环中,break始终是终止循环;continue是直接进入下一个循环,对for来说只是不执行后面的语句,但是仍然执行i++(表达式3)。

.1for语句的循环控制变量

注意:1、不要在for循环体内修改循环变量,防止for循环失去控制。

2、建议for语句的循环控制变量的取值采用“前闭后开区间”写法。比如【0,10)因为比较直观

//代码1
int main()
{
int i=0;
for(i=1;i<=100;i++)
{
//程序代码
i=0;//指此类在for中重新对i进行赋值、修改等的操作,尽可能避免重新定义以免出现错误
}
return 0;
}

.2for循环的变种

//代码1 省略for的所有条件
for(;;)
{
printf("hello");//死循环执行
}

//代码2 省略for的初始化部分
int i = 0;
int j = 0;
for(;i<3;i++)
{
   for(;j<3;j++)
   {
        printf("hello");//i=0,j=0,j=1,j=2,j=3;
   }
}//打印3次
//因为重新进入循环时未对j进行初始化,导致i重新进入j的值还是为3

//代码3 (与条件2对照)
int i = 0;
int j = 0;
for(i=0;i<3;i++)
{
   for(j=0;j<3;j++)
   {
        printf("hello");
   }
}//打印9次

//代码4(判断条件可多个)
 int x, y;
    for (x = 0, y = 0; x<2 && y<3; ++x, y++)
   {
        printf("hello\n");
   }
 return 0;
}

注意:1、for循环的初始化,判断,调整三个部分均可以省略。但是如果吧判断部分省略了,意味着判断恒为真,进入死循环。2、for循环内的初始化一定要写,防止出现错误。

例题:

//请问循环要循环多少次?
#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”使得条件为0,即为假,则不进入循环
//一个=为赋值,两个==为判断

 do...while语句

do...while()循环的语法

do
      {
        循环语句;
      }
   while(表达式);//判断

执行流程图

//break在for、while、do...while、switch中使用

//continue在for、while、do...while中使用

do语句的特点

循环至少执行一次,条件比较特殊,使用场景有限,所以不是经常使用。

练习

1、n的阶乘

#include <stdio.h>
    int main()
        {
        	int n = 0;
        	//输入
        	scanf("%d", &n);
        	//计算n的阶乘
        	int i = 0;
        	int ret = 1;
        	for (i = 1; i <= n; i++)
        	{
        		ret *= i;
        	}
        
        	printf("%d\n", ret);
        
        	return 0;
        }

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

//代码1
int main()
{
	int n = 0;
	//输入
	//计算n的阶乘
	int i = 0;
	int ret = 1;
	int sum = 0;
	//1+2+6 = 9
	for (n = 1; n <= 10; n++)
	{
		ret = 1;
		//计算n的阶乘
		for (i = 1; i <= n; i++)
		{
			ret *= i;
		}
		sum += ret;
	}

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

	return 0;
}
//代码2
int main()
{
	int n = 0;
	//输入
	//计算n的阶乘
	int i = 0;
	int ret = 1;
	int sum = 0;
	//1+2+6 = 9
	for (n = 1; n <= 10; n++)
	{
		ret *= n;//用不断变大的ret与n乘,减少不必要的循环
		sum += ret;
	}

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

	return 0;
}

3、在一个有序数组中查找具体的某个数字n(有序数组可以用二分法查找)

//二分法查找(折半查找),前提是数组有序
#include<stdio.h>
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int k = 14;
	int sz = sizeof(arr) / sizeof(arr[0]);//计算给定数组长度
	int left = 0;
	int right = sz - 1;
	int flag =  0;//作为一个标志,用于检验是否找到
	while (left <= right)
	{
		int mid = (left + right) / 2;//这里是为了每次找到中间的值来确定被查找数字的区间
		//同时这里还有另一种写法:
		//int mid = left + (right - left) / 2
		if (arr[mid] > k)
		{
			right = mid - 1;
		}
		else if (arr[mid] < k)
		{
			left = mid + 1;
		}
		else
		{
			printf("找到了,该数下标为%d", mid);
			flag = 1;
			break;//结束了及时跳出
		}
		
	}
	if (flag == 0)
	{
		printf("没有找到!");
	}
	return 0;
}

 第二种取中间值的思路:

 两个值不直接相加,是为了防止在某些情况下发生溢出的现象。这种方法通过将两者多出的部分进行平均处理,来避免数字溢出带来的影响。

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

编写代码,演示多个字符从两端移动,向中间汇聚。
#include<stdio.h>
#include <string.h>
#include <windows.h>//Sleep函数头文件
int main()
{
	char arr1[] = "welcome to bit!!!!";
	char arr2[] = "******************";
	int left = 0;
	int right = strlen(arr1)-1;

	while (left<=right)//或者用for循环
//用for循环写的,这里的变化就是定义写在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);//让程序慢一点执行
		system("cls");//清屏
		left++;
		right--;
	}
	printf("%s\n", arr2);

	return 0;
}

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

// 5. 编写代码实现,模拟用户登录情景,并且只能登录三次
//(只允许输入三次密码,如果密码正确则提示登录成,如果三次均输入错误,则退出程序。
#include<stdio.h>
#include<string.h>
int main()
{
	int i = 0;
	char password[20] = { 0 };
	int flag = 0;
	for (i = 0; i < 3; i++)
	{
		printf("请输入密码>:");
		scanf("%s", password);//数组名本身就是地址,不需要取地址
		if (strcmp(password, "123456") == 0)//判断
		{
			printf("密码正确!\n");
			flag = 1;
			break;
		}
		else
		{
			printf("密码错误\n");
		}
	}
	if (flag == 0)
	{
		printf("三次密码均错误,退出程序!");
	}
	return 0;
}

6、猜数游戏实现

//猜数字游戏实现
//电脑生成一个1-100的随机数,
//猜大了 就告诉你:猜大了,猜小了 就告诉你:猜小了;猜对了就告诉你:恭喜你,猜对了
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void menu()
{
	printf("******************\n");
	printf("****  1.play  ****\n");
	printf("****  0.exit  ****\n");
	printf("******************\n");
}
void game()
{
	int ret = rand()%100+1;//1.生成随机数
	//rand函数会返回一个0-32767之间的随机数
	//“Use the srand function to seed the pseudorandom-number generator before calling rand.”
	//所以需要调用srand函数生成伪随机数生成器种子
	//同时为了避免对函数多次调用产生的随机数相近,把随机数生成器放入主函数中,每次猜数只调用一次即可
	// %100是可以取0-99之间的数字,然后加一;可以取到1-100之间的数字
	//2.猜数字
	int guess = 0;
	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));//设置随机数的生成器

	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;
}

1.生成随机数。

随机数的生成需要我们使用rand函数,rand函数会返回一个0-32767之间的随机数,rand在用法中:“Use the srand function to seed the pseudorandom-number generator before calling rand.”所以需要调用srand函数生成伪随机数生成器种子。

然而srand生成随机数,需要srand括号里是一个随机数,我们可以引用时间戳。因为每一个不同的时间都会对应一个时间戳,我们可以运用时间戳来让srand函数产生随机值。而获得时间戳需要调用time函数,而该函数头文件为:include <time.h>,该函数返回的值是一个时间戳,而这个时间戳可以作为一个随机值。

2.其次就是需要注意取1-100之间的数,那么就需要取余0-99之间的数。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值