(四)循环语句
1.while循环
1.1语法
while (表达式)
{
循环语句;
} //不用花扩号,只能表示while后一句为循环语句。

#include
int main()
{
int i = 1;
while (i <= 10)
{
printf(" %d", i);
i++;
}
return 0;
}
我们可以发现while语句先做判断,再执行语句;
因此例句中判断了11次,执行语句10次。
1.2while中的break
#include
int main()
{
int i = 1;
while (i <= 10)
{
if(i==5)
{
break;
}
printf(" %d", i);
i++;
}
return 0;
}
结果如下:

在while循环中,只要遇到break,就停止后期的所有循环,直接跳出。
所有while中的break用于永久终止循环。
1.3while中的continue。
#include
int main()
{
int i = 1;
while (i <= 10)
{
if(i==5)
{
continue;
}
printf(" %d", i);
i++;
}
return 0;
}

我们发现程序既没有报错,也没有停止,而是进入死循环。
continue用于终止本次循环,也就是本次循环中continue后面的程序不再执行。而是直接跳转到while语句的判断部分,进入下一次循环的入口判断。
1.4示例
#include
int main()
{
int ch = 0;
while ((ch = getchar()) != EOF)
{
}
putchar(ch);
return 0;
}
用于输出一段字符中的数字字符

1.5拓展
密码输入
#include
int main()
{
int ret = 0;
char password[20] = { 0 };
printf("请输入密码:>");
scanf("%s", password);
printf("请确认(Y/N):>");
ret = getchar();
if (ret == 'Y')
{
printf("确认成功\n");
}
else
{
printf("放弃确认\n");
}
return 0;
}
为什么结果为此?

首先我们要明白,scanf和getchar都属于输入函数,会去检测输入缓冲区。
scanf会先等待输入缓冲区出现东西,当我们输入123456 \n(回车),它会拿走123456,剩下\n;
程序往下运行,此时输入缓冲区还有\n,因此getchar不会等待,而是直接拿走\n;
\n在ascii码中为10,10!=‘Y’,因此走else语句。
那我们便可以再使用getchar读走\n
#include
int main()
{
int ret = 0;
char password[20] = { 0 };
printf("请输入密码:>");
scanf("%s", password);
getchar();
printf("请确认(Y/N):>");
ret = getchar();
if (ret == 'Y')
{
printf("确认成功\n");
}
else
{
printf("放弃确认\n");
}
return 0;
}

但是,当我们输入123456 abcd时,又出现了问题

这是因为scanf读走了123456
第一个getchar读走了空格
第二个getchar读走了abcd
那我们能不能写一个循环使缓冲器被读干净?
当然可以:
#include
int main()
{
int ret = 0;
int ch = 0;
char password[20] = { 0 };
printf("请输入密码:>");
scanf("%s", password);
while((ch=getchar())!='\n')
{
;
}
printf("请确认(Y/N):>");
ret = getchar();
if (ret == 'Y')
{
printf("确认成功\n");
}
else
{
printf("放弃确认\n");
}
return 0;
}

2.for循环
2.1语法
for(表达式1;表达式2;表达式3) //三个条件都可以不要
循环语句;
表达式1为初始化部分,用于初始化循环变量
表达式2为条件判断部分,用于判断循环时候终止
表达式3为调整部分,用于循环条件的调整
2.2示例
输入1-10的数字
#include
int main()
{
int i=0;
for(i=1;i<=10;i++)
{
printf(" %d",i);
}
return 0;
}

2.3while和for对比
while循环中依然存在实现循环的三个条件,但分离远,风格上不如for
2.4break和continue在for循环中
意义和在while中一样,但还是有区别

continue只跳过了printf,没跳过i++

continue跳过了printf和i++
2.5建议
不可在for循环体内修改循环变量,防止for循环失去控制。
建议for语句的循环控制变量的取值采用前闭后开的写法。
for(i=1;i<10;i++) //前闭后开
for(i=1;i<=9;i++) //前闭后闭
2.6变式
#include
int main()
{
int i=0;
int counter=0;
for(i=1;i<=10;i++)
{
int j=0;
for(j=1;j<=10;j++)
{
printf("ha\n");
counter++;
}
}
printf("counter = %d",counter);
return 0;
}

2.7小测
//请问循环次数
#include
int main()
{
int i=0;
int k=0;
for(i=0,k=0;k=0;i++,k++)
k++;
return 0;
}
答案0次
注意是;k=0;为假直接出循环
3.do while 循环
3.1语法

3.2特点
至少执行一次,使用场景有限。
#include
int main()
{
int i=1;
do
{
printf("%d\n",i);
i++;
}
while(i<10);
return 0;
}
3.3break和continue在do while中的应用
#include
int main()
{
int i=10;
do
{
i--;
if(5==i)
;
printf("%d\n",i);
}
while(i>1);
return 0;
}

#include
int main()
{
int i=10;
do
{
i--;
if(5==i)
continue;
printf("%d\n",i);
}
while(i>1);
return 0;
}

4.练习
编写代码,演示多个字符从两端移动,向中间汇聚
#include
#include
int main()
{
char arr1[] = "for this night,and all the nightsto come!";
char arr2[] = "#########################################";
int left = 0;
int right = strlen(arr1) - 1;
while (left <= right)
{
Sleep(1000);
arr2[left] = arr1[left];
arr2[right] = arr1[right];
left++;
right--;
printf("%s\n", arr2);
}
return 0;
}
#include
#include
int main()
{
char arr1[] = "for this night,and all the nightsto come!";
char arr2[] = "#########################################";
int left = 0;
int right = strlen(arr1) - 1;
for (left = 0, right = strlen(arr1) - 1;left<=right;left++,right--)
{
Sleep(1000);
arr2[left] = arr1[left];
arr2[right] = arr1[right];
printf("%s\n", arr2);
}
return 0;
}
阶乘
#include
int main()
{
int i = 0;
int s = 1;
printf("请输入一个数\n");
scanf("%d", &i);
for (; i > 0; i--)
s = s * i;
printf("%d", s);
return 0;
}
折半查找算法
#include
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int sz = sizeof(arr) / sizeof(arr[0]);//计算元素个数
int left = 0;//左下标
int right =sz -1;//右下标
int key = 7;
int mid = 0;
while (left <= right)
{
mid = (left + right) / 2;
if (arr[mid] > key)
{
right = mid - 1;
}
else if (arr[mid] < key)
{
left = mid + 1;
}
else break;
}
if (left <= right)
printf("找到了,下标是%d\n", mid);
else
printf("找不到\n");
return 0;
}
三个数从大到小排序
#include
int main()
{
int a, b, c,tep;
scanf("%d%d%d", &a, &b, &c);
if (a < b)
{
tep=a;
a = b;
b = tep;
}
if (a < c)
{
tep = a;
a = c;
c = tep;
}
if (b < c)
{
tep = b;
b = c;
c = tep;
}
printf(" %d %d %d", a, b, c);
return 0;
}
输入一个数,判断1到这个数中间有多少素数
#include
int main()
{
int a = 0;
int i = 0;
int j = 0;
int counter = 0;
printf("请输入一个数\n");
scanf("%d", &a);
for (i = 1; i <= a; i++)
{
for (j = 2; j < i; j++)
{
if (i % j == 0)
{
break;
}
} //break会使循环跳到这里
if (j == i)
{
counter++;
printf(" %d\n", i);
}
}
printf("counter = %d\n", counter);
return 0;
}
打印九九乘法表
#include
int main()
{
int i = 0;
for (i = 1; i < 9; i++)
{
int j = 0;
for (j = 1; j <= i; j++)
printf(" %d* %d= %-2d", i, j, i * j);
printf("\n");
}
return 0;
}
(五)goto语句
可以一次跳出多层循环,适用于如下场景
for(...)
for(...)
{
for (...)
{
if (disaster)
goto error;
}
}
...
error: