伊吖学C笔记(4、循环、自定义函数、二级菜单)

一、循环

如果说分支结构是计算机做出判断和选择,在智力上的进化,那循环就是不厌其烦的重复和遍历,在速度上的进化。c语言有三种循环结构。

1.while循环

1.1格式:

++while++ ++(条件){循环体;}++

当条件为真时,执行循环体,执行完一次判断一下,为真,重复执行循环体...直到条件不成立(或遇到break;),跳出循环。

1.2例子:

【如果没有{},循环体就是紧跟着的一句。单语句可省略{}】

本例解答:首先判断 n--是否为真,实际上就是判断n是否为真,判断完后再把n减1。n原为4,非0,条件为真,顺道执行n--,此时n=3,执行循环体。打印--n的值,n原为3,--n,先减1再输出,n=2,即控制台输出2。第一次循环完成。

再次判断n--的值,此时n=2,非0为真,并执行n--,n=1后,再次执行循环。打印输出--n,即0。

每三次判断 n--,n=0非真,结束循环。

while,判断比循环总是多一次。当然程序调试经常出现死循环,Crtl+c中断。

再看一个例子:

2.do while循环

2.1格式:

++do++ ++{循环体;}while(条件);++

不管三七二十一,先执行循环体,再判断条件真假,来决定要不要执行。

2.2例子:

本例:先执行printf("%3d",x-=2); 这句x=x-2=1,结果输出1,3d的3表示位数,忽略。

再判断!(--x)是否为真?x=1,--x为0,非0为真,继续执行循环体printf("%3d",x-=2); 输出-2,x=0-2=-2。

再判断!(--x),x=-2,--x为-3,非-3为假,循环结束。

(判断一个量是否为真时,以0表示假,非0表示真,正数、负数都表示真,!2、!(-3)等都表示假,只有!0表示真。)

例子:

编程思路:

总体来说,是个数列求和,需要用到循环语句。如果求到第n项,则循环n次;本题不知道循环次数,要求通过精度来确定循环次数,即第n项小于0.00001时停止循环,可用do{...}while(an>0.00001)循环。

奇数项与偶数项符号不同,可用if语句进行分支判断;也可在前一次循环基础上取负。

参考代码:

float x,a=1.0,n=1.0,s=1.0;

printf("请输入一个大于1的数:");

scanf("%f",&x);

do{

a=-a/x;n=-n/x;

a=a+n;

s=s+a;

}while(fabs(a)>0.00001);//大于精度执行

printf("S=%lf\n",s);

说明:对数列类型的循环,需要搞清楚第n项是在前一项的基础上,是怎么变来的?变化的差异是不是相同的?

本例:后一项的分母,总是在前一项分母的基础上除以x;分子总是在前一项的分子的基础上加1;符号总是在前一项的基础上取负。

所以,a=-a/x;表示分母在前一项的基础上除以x,并且符号在前一项基础上取负;而n=-n/x;表示分子加1的,n开始为1,分母同步变化的部分。

a=a+n;相当于数列的通项式an。

s=s+a;相当于数列求和Sn。

fabs(a)>0.00001,大于精度就执行,如果第n项小于这个数了,就停止。实际执行上,第n项已经执行了,超过了0.00001这个精度。++do while循环是先执行再判断。++

如果第n项不能小于这个数,即不包含0.00001,意思是超过精度就丢弃,那循环就要用到++while(){}语句,先判断再执行。++实际上第n项未执行。

这就是为什么有while与do while的区别。

3.for循环

3.1格式:

++for++ ++(初始值;条件;增量){循环体;}++

**初始值:**通常用i=1或i=0,这个i要先声明:int i;如果初始值在条件范围内,执行循环体。

**条件:**初始值i的变化范围,比如i<20。

**增量:**在执行循环体一次后,计算增量,通常用i++, i自动增1。并再次判断i,如果在范围内继续:执行循环体->增量->判断,直到超出范围退出循环。

典型结构如下:

int i;

for(i=0;i<20;i++){...}

for后面的小括号中要用两个分号";",

3.2 例子:

依次输出1-9一行,数字之间用空格。

i在依次变化过程中,每个节点只与i有关,好比排队,一人一号。

再比如:依次输出1-9一列。

每次输出加个"\n"回车,好比电梯,一层一停。

3.3循环+判断

题目:所谓"水仙花数"是指一个三位数,其各位数字立方和等于该数本身。例如:153是一个"水仙花数",因为153=1的三次方+5的三次方+3的三次方。编程输出所有水仙花数。

编程思路:这个题目,显然是把所有的三位数(100-999)依次拿来计算验证,看是不是符合水仙花数的规律,是则输出。所有三位数依次进行验证,涉及到循环。循环有三种:++while(.){.}++ 、++do{.}whie(.)++ 、++for(.){.}++三种,用哪种好呢?如果次数是确定的,用for;如果满足条件才做,用while;如果先做再判断条件,用do while。显然本例用for更好。

本例,在每次循环中,都要计算一次,看结果符合不,这涉及到判断,用到if语句。编程如下:

if作判断时,先要把百位、十位、个位上3个数字取出来,再分别三次方,然后求和,最后比较。

【 "循环+判断"是电脑程序最美丽的存在,**++循环里面套分支++**是最常用的手段。循环体现"快",比如图书馆有三百万册书,把含有"生命"的书名找出来。如果我们用300个人来查找,每人查找10000册,可想有多慢。如果是电脑,把300万条书名循环一遍,只要一瞬间。判断体现为"智",通过计算、比对,筛选出有用的部分。】

再比如输出10以内的奇数:

再比如矩阵输出1-100:

3.4双层for结构的矩阵输出

如果说单层for是线性结构,那双层for就是平面结构,可以很轻松输出一些矩阵花样。

双层for结构。如下:

int i,j;//双层for ,声明两个变量

for(i=1;i<10;i++){

for(j=1;j<10;j++){

...}..}

双层for结构,用i控制行,用j控制列,对于在屏幕上输出各种花式图案,是个不错的选择。双层for是一个二维结构,i好比第几层楼,j表示一层楼里的第几个房间;在排队中,i代表第几个队,j表示一个队里的第几号。简单理解:i是主干号,j是主干里的分支号。如果需要三层、四层,就再引入k,m等,用k表示第三层编号,m第四层编号。

比如输出一个5*5矩阵:

i=1时,先运行j这个单层,分别是j=1...j=5,完了,加个回车,再上二楼i=2,再次运行j这个单层,又是j=1...j=5,...直到i=5运行完毕。

有时,++充分利用i与j之间的关系++,挖掘i与j变化相关性,可以输出一些特殊变形。

如果要求输出这样一个形状,怎么做?

观察发现:双层循环,当i=j时,输出"*",其他输出空格,代码如下:

如果是下面这种情况呢?

什么规律呢?i+j=常数,每个*到上边、左边的距离和为定值。代码如下:

如果是下面的图案呢:

显然,紧跟上例,改条件为:j+i>=10。还有

如果是下面的图案呢,又是什么规律?

找规律:从矩阵(我们也可以叫方阵)的第一个位子开始,打一个,空一个,从左到右,再从上到下。这正好是所说"奇偶性",把i+j的和当作一个数,如果这个数是偶数,就打"*",否则打空格。条件语句可以这样写:if((i+j)%2==0)printf("* ");完整代码如下:

以上只是几种最基本的造型,对于更复杂的图案,需要分别计算空格和符号"*"变化规律与i、j之间的联系。比如:

紧紧抓住横坐标j、纵坐标i之间的关系。

如果是平面几何的图形,比如输出一个圆,怎么弄呢?

我们首先要模拟一个坐标系,大致确定坐标原点o的位置,比如:x的范围-10~10,y的范围-10~10;然后再根据图形的边界调整这个范围。比如单位圆的边界为1,那x、y就调整到-1.5~1.5,反正大于1,也不能太大,不然不成比例,细节丢失。接下来,设置一个变化量△d,去分切这个范围。分切把握一个原则,分切的数量小于80,因为C语言输出屏宽默认为80。另外要注意,x水平字符间距小,y垂直字符间距大,变化量△d要作调整(通常2倍)。代码如下:

再来两个例子:

题目:输出9*9口诀(乘法表)。

这是一个典型的双层for循环,并且输出呢,只输出整个矩阵的一半,即j(列)<=i(行)的情况。第一层循环:行数9行,设置条件:for (i=1;i<10;i++),第二层循环:列数是变化的,依次从1到9,设置条件:for(j=1;j<i+1;j++),注意条件"j<i+1",与"j<=i"等价,即包含j=i的情况。

完整代码如下:

"%-3d"表示整数输出,格式三位宽度,并且靠左对齐。其实"两位+空格"也可。

二、自定义函数

C语言就是一个个函数,从main()开始,你调用我,我调用你。系统默认的(比如:printf()、scanf()、if()、for()、while()...等),括号即函数,我们拿来用就行。

如果我们有一个功能块(一段程序,完成某个功能),要在不同地方多次调用,你不能总是复制粘贴到这些地方,那样会造成程序臃肿,参数过多,难以阅读。

正确的做法是:把这个功能块定义为一个函数,取个名字,调用时喊名字就行。这样主次分明,结构清晰,易读。同时呢,这种函数结构使C变的很容易扩展。比如一个数开平方,很多人各写一段代码来完成,通过专家团评审,其中一种最好。我们就把这个最好的代码段定义为函数sqrt()。同样的方法,对数函数log()、指数函数exp()...最后将这些函数打包,在程序开始用#include<math.h>声明。当然函数扩展可以包含很多方面:图像处理包、语音处理包、人脸识别包、网页处理包、AI包...等等。很多东西不需要你具体去写,你拿来用就行,减少了程序开发时间,提高了开发效率。

1.C语言++自定义函数++语法结构。

++类型 函数名(参数){代码段;}++ 比如:

void(空的) 表示类型为无类型,即不需要返回任何类型的值。此类型函数直接出结果。

int、double、char表示返回值的类型。在{}中的代码中要加入return 语句,表示返回函数中的哪个值。为什么要有返回值呢?因为返回的值只是个中间值,后面还要参与其他操作运算,是可以给它安个变量名的。

a()即为自定义函数名,跟定义变量名一样,任意取,但不能与C本有的函数重名。为便于记忆,通常用英文单词或缩写,比如求和sum()。

(参数)小括号中的参数可有可无,根据需要而设。设定时同样要声明类型如(int a)(double x)(int a[])等。这种参数只对该函数有效,在内部使用,在其他地方(主函数、其它函数)无效,又叫形式参数(形参)。

下面举例说明:

void类型不用返回,直接出结果。当然换成int,不加return也是可以的。

函数调用,输名字即可,有参数带参数,无参数带括号。

有返回值的函数,相当于一个变量名,可以传给其他变量,参与计算,也可出现在其他语句之中。

2.全局变量的顺序。

如果在前面在函数外已声明的变量,在函数内使用即可,如下:

如果在自定义函数++后面++声明变量,通不过,如下:

怎么办?这时需要用到++extern(外来的)++作声明,同时这个int ss=2;放在main()里也是不行的:

要放到main()主函数的外面:

自定义函数sum()也可跟main()平级,不需要被包含在main()之中。

这个"int ss=2;"中ss不属于哪一个函数,属于文件,对全局有效,又称全局变量。上例中"int s;"中s只属于sum()函数,叫局部变量或动态变量。

3.形参和实参。

上例中,自定义函数sum()中的a、b叫形参,函数内部使用,离开函数不能使用;c、d叫实参,出现在主调函数中,把数字传递给形参,在函数内不能使用。

4.静态变量。

函数中的局部变量,动态分配 存储空间,函数调用结束时,会释放这些存储空间,变量的生存周期结束,变量值失效。如果想保留某个关键变量的值,可以用static(静止的)进行声明。

可以看出,这个s产生了记忆,每调用一次函数,它的值不会消失。至于逆序输入,应该是先全部计算完,压入堆栈,最后一次性输出。

5.函数的递归调用。

在定义函数时,在语句中加入一句,调用自己,就是递归。咋一看,不是产生了死循环吗?是的,加个退出条件即可。递归在某些特定的场合很有用处。

三、二级菜单

菜单的设计,是方便与计算机交流的主要方式,包括登录、主菜单、二级菜单等。程序设计会用到循环、分支、函数等。举例如下:

复制代码
	//二级菜单设计	
	int login(){ //登录函数 
		printf("	月球资源开发有限公司管理系统	\n");
		printf("============================================\n\n");
		printf("	请输入管理员账号:");
		char id[20],pw[20],id1[]="huang",pw1[]="123456";
		gets(id);
		int i=0;
		printf("	请输入管理员密码:");
		while ((pw[i]=getch())!='\r') {// 当输入回车时停止读取密码
			printf("*");// getch()输入不回显,\r结束,也有_getch() 
			i++;		// getchar()输入回显,\n结束 
		}
		pw[i] = '\0';  // 结束字符串
		if( strcmp(id,id1)!=0||strcmp(pw,pw1)!=0){
			printf("账号或密码错误!\n");
			return 0; 
		}
	}
	int menu(){  //主菜单函数 
		system("cls");
		printf("月球资源开发有限公司管理系统	\n");
		printf("============================================\n\n");
		printf("		   主菜单\n\n");
		printf("	1.功能A模块  	3.功能C模块\n");
		printf("	2.功能B模块  	4.功能D模块\n");
		printf("	            	0.退出\n");
		printf("请选择:");
	}
	int submenu1(){ //子菜单1函数 
		system("cls");
		printf("\n月球资源开发有限公司管理系统	\n");
		printf("============================================\n\n");
		printf("		 功能A子菜单\n\n");
		printf("	1.A1模块  	3.A3模块\n");
		printf("	2.A2模块  	4.A4模块\n");
		printf("	           	0.返回\n");
		printf("请选择:");
	}
	int submenu2(){  //子菜单2函数 
		system("cls");
		printf("\n月球资源开发有限公司管理系统	\n");
		printf("============================================\n\n");
		printf("		 功能B子菜单\n\n");
		printf("	1.B1模块  	3.B3模块\n");
		printf("	2.B2模块  	4.B4模块\n");
		printf("	           	0.返回\n");
		printf("请选择:");
	}
	login();
	int choice,subchoice;
	while(1){
		menu();
		scanf("%d",&choice);
		switch(choice){
			case 1:while(1){
				submenu1();
				scanf("%d",&subchoice);
				switch(subchoice){
					case 1:printf("这是A1功能。");system("pause");break;
					case 2:printf("这是A2功能。");system("pause");break;
					case 3:printf("这是A3功能。");system("pause");break;
					case 4:printf("这是A4功能。");system("pause");break; 
					case 0:break;
					default:printf("无效选择。"); 
				}
				if(subchoice==0)break;	
			}break;
			case 2:while(1){
				submenu2();
				scanf("%d",&subchoice);
				switch(subchoice){
					case 1:printf("这是B1功能。");system("pause");break;
					case 2:printf("这是B2功能。");system("pause");break;
					case 3:printf("这是B3功能。");system("pause");break;
					case 4:printf("这是B4功能。");system("pause");break; 
					case 0:break;//退出switch 
					default:printf("无效选择。"); 
				}
				if(subchoice==0)break;//退出while	
			}break;
			case 3:break;//略 
			case 4:break;//略 
			case 0:return 0;
			default:printf("无效选择。");
		}
	}
相关推荐
__如果2 小时前
深度学习复习笔记
人工智能·笔记·深度学习
锦瑟居士2 小时前
Docker 笔记 -- 借助AI工具强势辅助
笔记·docker·eureka
两点王爷3 小时前
Java spingboot项目 在docker运行,需要含GDAL的JDK
java·开发语言·docker
find_element_by_id4 小时前
adb 常用命令笔记
笔记·adb
云泽8085 小时前
模块化设计,static和extern(面试题常见)
c语言·面试·职场和发展
万能螺丝刀15 小时前
java helloWord java程序运行机制 用idea创建一个java项目 标识符 关键字 数据类型 字节
java·开发语言·intellij-idea
朱剑君5 小时前
编程之巅:语言的较量
开发语言
jiuweiC5 小时前
hive 笔记
hive·hadoop·笔记
Humbunklung6 小时前
Rust 编程实现猜数字游戏
开发语言·后端·rust
vvilkim6 小时前
深入理解C#数据类型:从基础到高级应用
开发语言·c#