一、while循环
(一)、语法:
while(表达式)
循环语句;
示例:
#include<stdio.h>
int main()
{
int i = 0;
while(i<=10)
{
printf("%d ",i);
i++;
}
printf("\n");
// 以下易疏漏的死循环样例
while(i<=10)
{
if(i==5)
continue; // i==5 时,直接跳过后面语句,回到表达式,导致死循环
printf("%d ",i);
i++;
}
return 0;
}
getchar()在while中的应用:
#include<stdio.h>
int main()
{
int ch = 0;
while((ch = getchar()) != EOF) // EOF代表文件结束输入标志符
{
putchar(ch); // 此处while会一直循环来接受字符;按ctrl + c 会传入EOF,即可停止循环
}
return 0;
}
二、do while循环
(一)、语法:
do
{循环体}while(表达式);
示例:
#include<stdio.h>
int main()
{
int i = 11;
do // 首先执行循环语句,然厚在判断while中的表达式的值,为真则再次执行循环语句
{
printf("%d ",i);
}while(i>=0 && i<=10);
return 0;
}
三、for 循环
(一)、语法:
for(表达式1;表达式2;表达式3)
循环体;
表达式1:为初始化部分,通常用于初始化循环变量
表达式2:为条件判断部分,通常用于判断循终止条件
表达式3:调整部分,通常用来调整循变量
示例:
#include<stdio.h>
int main()
{
int i;
for(i = 0;i<10;i++)
{
printf("%d ",i);
}
for(int j = 0,int k = 1;j<10 && k<=10;j++,k++)
{
printf("哈哈 j=%d\n",j);
printf("呵呵 k=%d\n",k);
}
// for表达式列表为空的情况
for( ;;) // 死循环
{
printf("hehe\n");
}
return 0;
}
for与while的比较:
#include<stdio.h>
int main()
{
int i = 0 ;
/* while(i<=10)
{
if(i==5)
continue; // i==5 时,直接跳过后面语句,回到表达式,导致死循环
printf("%d ",i);
i++;
}
*/
for(i = 0;i<=10;i++)
{
if(i==5)
continue; // for不会死循环,而是跳过5,不输出5,但是会输出其后的数字
printf("%d ",i);
}
return 0;
}
#include<stdio.h>
int main()
{
int i = 0,j = 0;
for( i = 0 ;i<10;i++)
{
for( j = 0;j<10;j++) // 会打印 10 行 0~9
{
printf("%d ",j);
}
printf("\n");
}
i = 0;
j = 0;
// for表达式列表为空的情况
for( ;i<10;i++) // 死循环
{
for( ;j<10;j++)
{
printf("%d "); // 0,1,2,3,4,5,6,7,8,9 j=10不再满足判断表达式,不会打印下去了
} // 结果只有一行 0~9
printf("\n");
}
return 0;
}
#include<stdio.h>
int main()
{
int i,j;
for(i=0,j=0; j=0; i++,j++) // 请问会循环几次?
{ // 答案:0次。因为判断表达式j赋值为了0,表达式值为假,不执行循环语句
j++;
}
return 0;
}
小建议:尽量不要在for循环体中更改循环变量,防止for循环失去控制
四、习题
1、计算1!+2!+3!+4!……+10!
include<stdio.h>
int main(){
// 冗余写法
int n,ret;
int sum = 0;
for(n=1;n<=10;n++){
ret = 1;
for(int i=1;i<=n;i++)
ret *= i;
sum += ret;
}
printf("%d",sum); //4037913
// 优化后
int n = 0;
int ret = 1;
int sum = 0;
for(n=1;n<=10;n++){
ret *= n;
sum += ret;
}
printf("%d",sum); //4037913
// 1!+2!+3!+4!……
// 解析:
// 2!等于1!*2
// 3!等于2!*3
// 4!等于3!*4
// …… …… ……
// n!等于 (n-1)!*n
return 0;
}
2、有序数组的折半查找(二分):
时间复杂度:log(2^n)
include<stdio.h>
void search(int x,int arr[],int n){
int left=0,right=n-1; // 数组的左右下标
int mid; // 数组的中间下标
while(left<=right){
mid = (right+left)/2;
if(arr[mid]<x)
{
left = mid+1; // 更新左下标
}
else if(arr[mid]>x)
{
right = mid-1; // 更新右下标
}
else
{
printf("%d的下标:%d\n",x,mid);
break;
}
}
if(left>right) printf("找不到数字:%d",x); // -1 代表没找到
}
int main(){
void search(int x,int arr[],int n);
int order[10] = {1,2,3,4,5,6,7,8,9,10};
int sz = sizeof(order)/sizeof(order[0]); // 计算元素个数
search(0,order,sz);
return 0;
}
3、多个字符从两端向中间移动
思路:①每次输出字符串sign;②用words字符串中的第一个字符和最后一个字符替换sign字符串中相应位置的字符
include<stdio.h>
include<string.h>
int main()
{
char words[] = "Welcome to bit!!!";
char sign[] = "#################";
int sz = sizeof(words)/sizeof(words[0]); // sizeof()会把字符串末尾的\0也统计,所以字符串最后一个字母的下标为sz-2;
// int sz1 = sizeof(sign)/sizeof(sign[0]); // strlen()不会统计字符串末尾的\0,所以字符串最后一个字母的下标为sz-1;
int l=-1,r=sz-1;
do
{
l++;
r--;
printf("%s\n",sign);
sign[l] = words[l];
sign[r] = words[r];
}while(l<=r);
// printf("%s\n",sign);
// for(l=0,r=sz-2;l<=r;l++,r--)
// {
// sign[l] = words[l];
// sign[r] = words[r];
// printf("%s\n",sign);
// }
return 0;
}