1.for循环:
正常的while循环语句结构:
int main()
{
int i = 0;//初始化
while (i < 10)//判断
{
//......
i++;//调整
}
return 0;
}
担当代码块中的初始化、判断及调整区域三个部分离得很远的话,
就会出现不方便调整的问题,因此使用循环结构时一般使用 for 循环:
for(表达式1; 表达式2; 表达式3)
循环语句;
表达式1为初始化部分,用于初始化循环变量。
表达式2为条件判断部分,用于判断循环时候终止。
表达式3为调整部分,用于循环条件的调整。
举例:使用for循环,在屏幕上打印1~10的数字:
int main()
{
int i;
//初始化 //判断 //调整
for (i = 1; i <= 10; i++)
{
printf("%d ", i);
}
return 0;
}
可见相比于 while循环,for循环相对来说更加简洁,方便修改调整循环中的参数。
总体上while循环和for循环看似没什么太大区别,但还是存在一些差异,比如:
当在这两个循环中加入 continue 后
for循环:在 i=5 时,执行continue语句后返回到调整阶段,i 自增,
最终打印结果为:1 2 3 4 6 7 8 9 10
while循环:在 i=5 时,执行continue语句后返回到判断阶段,不经过i自增,
最终打印结果为:1 2 3 4
for语句的循环控制变量建议:
①不可在for循环体内修改循环变量,防止for循环失去控制。
②建议for语句的循环控制变量的取值采用“前闭后开区间”写法。
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int i;
for (i = 0; i < 10; i++)
{
if (i = 5)
printf("hehe\n");
printf("haha\n");
}
return 0;
}
譬如上述代码中在for循环内部给 i 赋值为 5,则for循环会一直进行,
持续不断地打印 hehe 和 haha,这样for循环就会失去控制。
因此不可以在for循环体内修改变量,最好应在调整部分修改。
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int i;
//10个元素
//10次循环
//10次打印
for (i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
上述代码中,利用数组arr[10]将1~10十个元素包括起来可视为一个闭区间,
在for循环的条件判断部分可以写成 i<=9 ,但是写成 i<10 更好,
因为这样可以清晰明了地知道 for循环进行了10次,打印了10遍, 包含了10个元素。
2.for循环的变种:
①for循环表达式的省略:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
for (;;)
{
printf("hehe");
}
return 0;
}
如图,当省略了 for循环 中的初始化、判断和调整部分时,程序执行后
会出现不断地打印“hehe”的现象,for循环一直在循环往复地执行,
那么为什么 for循环 中省略了这三个部分程序还能执行呢?
接下来就是一些重点:
for循环的初始化、调整、判断都可以省略
但是:
for循环的判断部分如果被省略,那判断条件就是:恒为正
这就是上述的代码for循环会一直循环往复执行的原因。
②for循环控制多个循环变量:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
int x, y;
for (x = 0, y = 0; x < 2 && y<5; ++x, y++)
{
printf("hehe\n");
}
return 0;
}
如图可看到 for循环 控制着两个循环变量,这样的语法也是成立的,
最终输出结果为2个“hehe”
3.do......while循环:
语法:
do
循环语句;
while(表达式);
例:打印数字1~10:
int main()
{
int i=1;
do
{
printf("%d ", i);
i++;
}
while (i <= 10);
return 0;
}
4.应用练习:
①计算n的阶乘:
int main()
{
int i,n;
int ret = 1;
scanf("%d", &n);
for (i = 1; i <= n; i++)
{
ret = ret * i;
}
printf("ret = %d\n", ret);
return 0;
}
利用 for循环 可以实现,但这只是其中一种方法。
②计算1!+2!+3!:
int main()
{
int i, n;
int ret = 1;
int sum = 0;
for (n = 1; n <= 3; n++)
{
ret = 1;
for (i = 1; i <= n; i++)
{
ret = ret * i;
}
sum = sum + ret;
}
printf("sum = %d\n", sum);
return 0;
}
我们会发现第二个 for循环 中,每次 i 都要从1开始循环,
这就会导致代码的效率很低。
我们其实可以发现一个规律,1!*2=2!,2!*3=3!
按照这个规律我们可以这样优化代码:
int main()
{
int i, n;
int ret = 1;
int sum = 0;
for (n = 1; n <= 3; n++)
{
ret = ret * n;
sum = sum + ret;
}
printf("%d\n", sum);
return 0;
}
这样就少了一个 for循环,代码的执行效率也更高了。
③在一个有序数组中查找具体的某个数字n。
编写int binsearch(int x, int v[], int n);
功能:在v[0]<=v[1]<=v[2]<=......<=v[n-1]的数组中查找x.
如,编写一串代码,在有序的数组arr中找到数字7:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
int i, k;
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
k = 7;
int sz = sizeof(arr) / sizeof(arr[0]);
for (i = 1; i < sz; i++)
{
if (k = arr[i])
{
printf("找到啦!下标是:%d\n", i);
break;
}
}
if (i == sz)
{
printf("没找到\n");
}
return 0;
}
上面是一个笨方法,比较容易理解,但是要实现起来不够高效,
如果整个数组有n个数,那么其复杂度就是n,即最多尝试n次才能找到目标数字7。
假设一个数字是500,我们不可能像1,2,3,...,500这样去数,
因此我们可以比如猜1,250,500,750,猜到750的时候,
当我们发现超过了要查找的目标数字后,就返回在(250,750)
这样的一个范围里去找,这样就高效很多,
这种方法我们称之为二分(折半)查找法,其复杂度仅为log2n
下面就是采用二分查找法优化后的代码:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
int k = 7;
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int left = 0;
int sz = sizeof(arr) / sizeof(arr[0]);
int right = sz - 1;
while (left <= right)
{
int mid = (right + left) / 2;
if (k < arr[mid])
{
right = mid - 1;
}
else if (k > arr[mid])
{
left = mid + 1;
}
else
{
printf("找到啦!下标是:%d\n", mid);
break;
}
}
if (left > right)
{
printf("找不到%d\n");
}
return 0;
}
④编写代码,演示多个字符从两端移动,向中间汇聚:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include<string.h>
int main()
{
char arr1[] = "welcome to sgu!!!" ;
char arr2[] = "##################";
int left = 0;
int right = strlen(arr1);
while (left <= right)
{
arr2[left] = arr1[left];
arr2[right] = arr1[right];
printf("%s\n", arr2);
left++;
right--;
}
return 0;
}
⑤编写代码实现,模拟用户登录情景,且只能登录三次:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include<string.h>
int main()
{
char arr[17];
int i = 0;
while (i<3)
{
printf("请输入密码:\n");
scanf("%s", &arr);
if ((strcmp(arr, "1314")) == 0)
//==不能用来比较两个字符串是否相等
//应该使用一个库函数-strcmp
{
printf("输入正确\n");
break;
}
printf("输入错误\n");
i++;
}
if (i == 3)
{
printf("密码错误已超过3次,禁止登录");
}
return 0;
}
要注意:
数组不能使用==判断相等,应该用库函数strcmp( )
头文件是:
#include<string.h>;
语法是:
strcmp(要进行比较的字符串1,要进行比较的字符串2)
输出结果:
- 如果返回值小于 0,则表示 str1 小于 str2
- 如果返回值大于 0,则表示 str1 大于 str2
- 如果返回值等于 0,则表示 str1 等于 str2