小练习

判断下面这段代码的输出是什么:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>

int main()
{
	int n=1;
	int m=2;
	switch(n)
	{
	case 1: m++;
	case 2: n++;
	case 3: 
		switch(n)
		{
		case 1: n++;
		case 2: n++;
				m++;
		}
	case 4: m++;
			break;
	default:
			break;
	}
	printf("m=%d  n=%d\n",m,n);
	return 0;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.

答案是“m=5  n=3”,需要对switch语句的解读有一定认知,注意break是逐层跳出switch代码块。


循环语句

while循环

while(1)死循环,while的循环结构是这样的:

while(表达式)
	循环语句;
  • 1.
  • 2.

首先判断表达式是否为真,若为真执行循环语句并且再次判断,直到表达式为假,此时跳出循环。

通过下面这段代码讨论continue的作用:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>

int main()
{
	int i=1;
	while(i<=10){
		if(i==5)
		{
			continue;
		}
		printf("%d   ",i);
		i++;
	}
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.

此时打印出来的结果是“1 2 3 4”,并且打印4之后程序并没有结束而是陷入了死循环,原因是i==5判断为真时continue中止了本次循环,也就是本次循环中continue后面的语句不会再执行,而是直接跳转到下一次的while语句进行下一次的条件判断,进行下一次的入口判断。

对应的break的作用就好理解很多,在一个循环内部执行到break语句,会立刻中止后续所有循环并跳出该循环体。

再来看几个代码:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>

int main()
{
	int ch = 0;
	while ((ch = getchar()) != EOF)
	{
		putchar(ch);
	}
	return 0;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.

这里涉及了一对新的函数getchar()和putchar(),为什么这里可以使用int型变量来接收键盘输入的字符型数值,我的理解是getchar接收的是键入的字符对应的ASCII码值,并将这个整型的ASCII码值赋值给ch,而putchar()将这个ASCII码值对应的字符输出打印出来,这里putchar()和直接printf打印效果是一样的。还要注意判断条件不等于EOF,这里键入EOF并不能停止程序,他的意思是end of file文件结束标志,可以用组合键Ctrl+z结束程序。

再研究一段代码:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>

int main()
{
	int ret = 0;
	char password[20]={0};
	printf("请输入密码:");
	scanf("%s",&password);
	printf("请确认(Y/N):");
//	scanf("%s",&ret);
	getchar();
	ret = getchar();
	if(ret == 'Y')
	{
		printf("确认成功\n");
	}
	else
	{
		printf("确认失败\n");
	}
	return 0;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.

为什么这里要两次使用getchar()来接收输入缓冲区的值呢?实际操作发现如果只用一个getchar(),输入密码没问题,但是在确认的时候程序不会等待我们输入,而是直接判断确认失败并且打印结果。原因是,我们输入密码之后是以回车键结束的,而scanf读取的缓冲区内容只包括密码留下了回车键”\n“,下一步getchar()读取缓冲区时读到了“\n”,因此不会等待我们进一步输入Y/N而是用“\n”直接进行判断,那么得出的结果永远都是确认失败。

解决办法目前想到的就是使用两次getchar()去读取缓冲区,让第一个去读取掉遗留下来的“\n”,这样第二个判断值就可以读取到正常我们键入的Y或者N。

for循环

for循环是用的最多的循环结构,for循环的语法结构如下:

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

表达式1是初始化部分,用于初始化循环变量。表达式2是条件判断部分,用于判断循环甚麽时候终止。表达式3为调整部分,用于循环条件的调整。(表达式3是每次循环的最后执行)

最简单的for循环的实现,输出打印1-10:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>

int main()
{
	int i = 0;
	for(i = 1;i <= 10; i++)
	{
		printf("%d ",i);
		if(i == 10)
			printf("\n");
	}
	return 0;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.

注意for循环结构不会香while一样因为内部的continue导致的死循环,在for循环中执行到continue会跳过循环体中后续的操作,跳到循环条件的调整这一步,下一步才进行判断,有效的避免了由于跳过调整代码造成的死循环。下例:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>


int main()
{
	int i = 0;
	for(i = 1;i <= 10; i++)
	{

		if(i == 5)
			continue;
		printf("%d ",i);
	}
	return 0;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.

输出结果如图:

7.31C语言学习日志_while循环

for循环的一些建议:

  1. 不可以在for循环体内改变循环变量,防止for循环失去控制。
  2. 建议for语句的循环控制变量采取“前闭后开区间”写法。

第一个比较好理解,前闭后开指的是i的初始化和判断条件,比如“for(i=0 ; i<10; i++)”这里面i的判断范围就是[0,10 ),方便习惯具有某种意义,在某些情况下更合适。

for循环的一些变种:

  1. for循环的初始化、调整、判断都可以省略
  2. for循环的判断部分被省略,那么判断条件默认恒为真
  3. 在不熟练的情况下,不建议省略for循环中的3个表达式

变种1,下方是错误案例,我们预期省略初始化的这一步,两层for循环嵌套打印100个输出:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>

int main()
{
	int i = 0;
	int j = 0;

	for( ;i < 10 ;i++ )
	{
		for( ;j < 10; j++)
		{
			printf("输出\n");
		}
	}
	return 0;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.

但是结果未达到我们的预期,只打印了10个输出:

7.31C语言学习日志_数组_02

原因是我们省略了j的初始化,导致外层循环第一次结束之后,当再次进入内层循环时,j的值并为得到初始化,j仍然是10,因此内部循环中的打印语句自然无法执行,最终直到i的值调整到10也并没有再打印任何输出,这就是省略表达式可能造成的一种bug。

变种2,使用两个循环变量来控制一个for循环:

int main()
{
  int x,y;
  for(x=0,y=0;x<2 && y<5; x++,y++)
  {
    printf("hehe");
  }
  return 0;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
do while

do语句的语法:

do
	循环语句;
while(表达式);
  • 1.
  • 2.
  • 3.

小尝试,打印输出1-10,要求使用do循环:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>

int main()
{
	//使用do-while语句打印1-10
	int i =1;
	do
	{
		printf("%d ",i);
		i++;
	}
	while(i<=10);
	return 0;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.

这种循环的特点是先循环后判断,先判断再循环,至少循环一次,这种循环用法在哪里比较突出呢?

练习任务

  1. 计算n的阶乘。
  2. 计算1!+2!+...+10!
  3. 在一个有序数组中查找具体的某个数字n。编写int binsearch(int x,int v[],int n);功能:在v[0]<=v[1]<=v[2]<=...<=v[n-1]的数组中查找x。

第一题:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>



//计算n的阶乘
int main()
{
	int n = 0;
	int i = 0; 
	long num = 1;
	printf("请输入一个整数:");
	scanf("%d",&n);
	if(n == 0)
	{
		num = 1;
	}
	else
	{
		for(i = n;i > 0;i-- )
		{
			num = num*i;
		}
	}
	printf("它的阶乘=%d\n",num);
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.

第二题:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>

//计算1!+2!+...+10!
int main()
{
	int i = 0; 
	int j = 0;
	long num = 1;
	long sum = 0;
	for(i=1;i < 11;i++)
	{
		num = 1;
		for(j = i;j > 0;j-- )
		{
			num = num*j;
		}
		sum = sum + num;
	}
	printf("1!+2!+...+10!=%d\n",sum);
	return 0;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.

第三题,写的不是很好,但是目前我只能写出这样的,函数用的很不熟练想法也很局限:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>

//在一个有序数组中查找具体的某个数字n。编写int binsearch(int x,int v[],int n);
//功能:在v[0]<=v[1]<=v[2]<=...<=v[n-1]的数组中查找x。

int binsearch(int x,int v[], int n)
{
	int i = 0;
	int res = 0;
	for(i=0 ; i<n;i++ )
	{
		if(v[i] == x)
		{
			res =i;
			break;
		}
	}
	return res;
}

int main()
{
	int v[]={10,20,30};
	int t = 0;
	int i = 0;
	int n = 0;
	int j = 0;
	printf("请输入一个有序数组(以非零字符结束):");
	while(scanf("%d",&v[t]) == 1)
	{
		t++;
	}
	printf("您输入的数组为:");
	for(i=0;i<t;i++)
	{
		printf("%d ",v[i]);
	}
	printf("  请输入你想查找的数:");
	scanf("%d",&n);
	j = binsearch( n,v,t);
	printf("您查找的数字对应的数组下标为%d\n",j);
	printf("即v[%d]=%d\n",j,n);
	return 0;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.

运行结果如下图:

7.31C语言学习日志_数组_03