本篇笔记我们继续来学习第三部分《分支语句和循环语句》,在上一篇中我们详细学习了xun语句——switch语句以及循环语句——while循环,接下来本部分的内容还包括:循环语句——for循环、循环语句——do while循环、折半查找算法、猜数字游戏、goto语句。
第三部分 分支语句和循环语句
五、循环语句(for循环)
1、for循环的语法结构
for (表达式1;表达式2;表达式3)
循环语句;
表达式1为初始化部分,用于初始化循环变量的。表达式2为条件判断部分,用于判断循环终止的条件。表达式3为调整部分,用于循环条件的调整。
for循环的执行流程:
我们使用一个简单的示例来观察for循环的语法结构:
// 使用for循环在屏幕上打印数字1-10。
#include <stdio.h>
int main()
{
int i = 0;
for(i=1/*初始化*/; i<=10/*判断部分*/; i++/*调整部分*/)
{
printf("%d ", i);
}
return 0;
}
2、while循环与for循环的比较
实现上面相同功能的代码,使用while循环应该写做这样:
// 使用while循环在屏幕上打印数字1-10。
#include<stdio.h>
int main()
{
int i = 1; // 初始化部分
while (i <= 10) // 判断部分
{
printf("%d ", i);
i += 1; // 调整部分
}
return 0;
}
这两段代码的功能是完全相同的,但是我们可以发现在while循环中依然存在循环的三个必须条件,但是由于风格的问题使得三个部分很可能偏离较远,这样查找修改就不够集中和方便。所以,for循环的风格更胜一筹。for循环使用的频率也最高。
3、for循环中的break语句和continue 语句
(1)break语句
break和while循环中的作用是类似的,会立即终止循环的执行,不管循环条件是否还成立。程序的控制流会直接跳转到for循环后面的代码继续执行。
下面我们来看这段代码,通过其输出结果体会break语句在for循环中的作用:
#include <stdio.h>
int main(){
int i = 0;
for (i = 1; i <= 10; i++){
if (5 == i)
break;
printf("%d ", i);
}
return 0;
}
(2)continue语句
当continue语句用在for循环中时,它会立即结束当前迭代的执行,并继续执行循环的下一次迭代。这意味着,continue之后的代码块将被跳过,循环变量会更新,然后循环条件会被重新检查。这里的作用和while循环中是有差异的。
这个差异导致while循环中更容易出现死循环的问题,这也是更加广泛使用for循环的原因之一。
下面我们来看这段代码,通过其输出结果体会continue语句在for循环中的作用:
#include <stdio.h>
int main()
{
int i = 0;
for (i = 1; i <= 10; i++)
{
if (5 == i)
continue;
printf("%d ", i);
}
return 0;
}
4、for循环的循环控制变量
(1)不可在for 循环体内修改循环变量,防止 for 循环失去控制。
(2)建议for语句的循环控制变量的取值采用“前闭后开区间”写法。
比如说我们在打印一个数组的前10个元素时应该采用以下写法:
#include<stdio.h>
int main(){
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int i = 0;
for (i = 0; i < 10; i++){ // 前闭后开的写法
printf("%d ",arr[i]);
}
return 0;
}
避免这样的写法:(这两种代码其实是等价的,但是在面试中使用前闭后开的写法更能够给面试官留下好印象)
#include<stdio.h>
int main(){
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int i = 0;
for (i = 0; i <= 9; i++){ // 两边都是闭区间的写法
printf("%d ", arr[i]);
}
return 0;
}
5、for循环语句的变种
(1)变种一
#include<stdio.h>
int main(){
for (;;){
printf("hello\n");
}
return 0;
}
for循环的初始化、调整和判断三个部分都可以被省略。但是一旦省略判断部分,则恒为真,便会成为一个死循环。例如上面的代码便会一直打印 hello 。
(2)变种2 —— for 循环的嵌套
#include<stdio.h>
int main(){
int i = 0;
int j = 0;
for (i = 0; i < 3; i++){
for (j = 0; j < 3; j++){
printf("hello\n");
}
}
return 0;
}
但是我们应该注意,for循环的三个表达式不要随便省略,否则会出现很多意外的结果,比如对上面的代码进行简单修改后结果完全不同:
#include<stdio.h>
int main() {
int i = 0, j = 0;
for (; i < 3; i++) {
for (; j < 3; j++) {
printf("hello\n");
}
}
return 0;
}
(3)变种3 —— 使用多于一个变量控制循环
#include<stdio.h>
int main(){
int x = 0;
int y = 0;
for (x = 0, y = 0; x < 2 && y < 5; ++x, y++){
printf("hello\n");
}
return 0;
}
6、一道笔试题
//请问循环要循环多少次?—— 0次
#include <stdio.h>
int main(){
int i = 0;
int k = 0;
for (i = 0, k = 0; k = 0; i++, k++)
k++;
return 0;
}
五、循环语句(do-while循环)
1、do-while循环的语法结构
do
循环语句;
while (表达式);
do-while语句执行的流程:
比如我们实现一个简单的问题来观察do-while循环的语法结构:
//在屏幕上打印1-10的数字。
#include<stdio.h>
int main()
{
int i = 1;
do
{
printf("%d ", i);
i++;
} while (i <= 10);
return 0;
}
2、do-while循环的特点
do-while循环是一种后测试循环,循环体至少会循环一次,使用的场景比较有限,所以并不是经常使用。我们最多使用的循环语句还是for循环。
3、do-while循环中的break语句和continue 语句
(1)break语句
break 语句在 do-while 循环中的作用是立即终止循环,跳出循环体,继续执行循环后面的代码。即使循环条件仍然为真,break 语句也会强制退出循环。
下面我们来看这段代码,通过其输出结果体会break语句在do-while循环中的作用:
#include<stdio.h>
int main()
{
int i = 1;
do
{
printf("%d ", i);
if (5 == i)
break;
i++;
} while (i <= 10);
return 0;
}
(2)continue语句
continue 语句用于跳过当前循环的剩余部分,并立即开始下一次循环迭代。如果 continue 语句后面还有代码,这些代码将被跳过,循环将直接回到循环条件的判断。
下面我们来看这段代码,通过其输出结果体会continue语句在do-while循环中的作用:
#include<stdio.h>
int main()
{
int i = 1;
do
{
printf("%d ", i);
if (5 == i)
continue;
i++;
} while (i <= 10);
return 0;
}
4、循环语句综合练习
(1)屏幕输入一个数字n,计算n的阶乘。
#include<stdio.h>
int main() {
int n = 0;
int ret = 1;
printf("请输入一个整数:");
scanf("%d", &n);
int i = 0;
for (i = 1; i <= n; i++)
{
ret = ret * i;
}
printf("数字 %d 的阶乘为 %d", n, ret);
return 0;
}
(2)计算1!+ 2!+ 3!+ …… +10!。
#include<stdio.h>
int main() {
int i = 0;
int n = 0;
int ret = 1;
int sum = 0;
for (i = 1; i <= 10; i++){
ret = 1;
for (n = 1; n <= i; n++){
ret = ret * n;
}
sum = sum + ret;
}
printf("1!+2!+3!+……+10!= %d", sum);
return 0;
}
下面我们来看一种更简单的算法,减少了运行的时间:
#include<stdio.h>
int main() {
int i = 0;
int ret = 1;
int sum = 0;
for (i = 1; i <= 10; i++){
ret = ret * i;
sum = sum + ret;
}
printf("1!+2!+3!+……+10!= %d", sum);
return 0;
}
(3)在一个有序数组中查找具体的某个数字n。
#include<stdio.h>
int main(){
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int a = 0;
int i = 0;
int flag = 0;
printf("请输入一个整数:");
scanf("%d", &a);
for (i = 0; i < 10; i++){
if (a == arr[i])
{
printf("找到了 %d ,下标是 %d", a, i);
flag = 1;
break;
}
}
if (0 == flag)
{
printf("没有找到");
}
return 0;
}
(4)演示多个字符从两端移动,向中间汇聚。
#include<stdio.h>
#include<string.h>
#include<windows.h>
#include<stdlib.h>
int main(){
char arr1[] = "hello liuboshi!!!!";
char arr2[] = "##################";
int left = 0; // 左下标
int right = strlen(arr1) - 1;
while (left <= right)
{
arr2[left] = arr1[left];
arr2[right] = arr1[right];
printf("%s\n", arr2);
Sleep(1000);
system("cls");//cls 是清空屏幕的命令
left = left + 1;
right = right - 1;
}
printf("%s\n", arr2);
return 0;
}
在C语言中,Sleep函数是用来让当前线程暂停执行指定的时间。Sleep函数的原型定义在windows.h头文件中,它是Windows操作系统提供的一个函数。表示要暂停的时间(以毫秒为单位)。
在C语言中,system函数是标准库中的一部分,它定义在<stdlib.h>头文件中。system函数用于执行操作系统的命令行指令。当你调用system函数时,它会创建一个新的进程来运行指定的命令,然后等待该命令执行完成后再继续执行后续的代码。
(5)编写代码模拟用户登录场景,并且只能登录三次。(只允许输入三次密码,如果密码正确,则提示登陆成功,如果三次都输入错误,则退出程序)
#include<stdio.h>
#include<string.h>
int main(){
int ch = 0;
char password[20] = { 0 };
int flag = 0;
printf("请输入你的密码:>>");
scanf("%19s", password);//数组名本质上就是地址,所以不需要取地址符号
while (getchar() != '\n');
printf("请确认密码(Y):>> ");
ch = getchar();
if (ch == 'Y'){
printf("确认成功\n");
printf("请等待三秒钟:\n");
Sleep(3000);
system("cls");
printf("请输入密码登录\n");
int i = 0;
char shuru[20] = { 0 };
for (i = 0; i <= 3; i++)
{
printf("请输入密码登录:>>");
scanf("%19s", shuru);
if (0 == strcmp(shuru, password))
{
printf("登录成功");
flag = 1;
break;
}
else
printf("第%d次密码错误\n", i + 1);
}
if (0 == flag)
printf("输入错误三次,退出程序\n");
}
else
printf("确认失败\n");
return 0;
}
在C语言中,strcmp函数是用来比较两个字符串的函数,它定义在<string.h>头文件中。strcmp函数会根据字符串的ASCII码值进行比较,它比较字符串中的字符直到找到不相等的字符,或者直到遇到字符串的终止符\0。
· 函数原型:
int strcmp(const char* str1, const char* str2);
· 返回值:
如果str1小于str2,返回值小于0。
如果str1等于str2,返回值等于0。
如果str1大于str2,返回值大于0。
· 示例代码
#include <stdio.h>
#include <string.h> // 包含 strcmp 函数的头文件
int main() {
char str1[] = "hello";
char str2[] = "world";
char str3[] = "hello";
// 比较 str1 和 str2
if (strcmp(str1, str2) < 0) {
printf("'%s' is less than '%s'\n", str1, str2);
}
else if (strcmp(str1, str2) > 0) {
printf("'%s' is greater than '%s'\n", str1, str2);
}
else {
printf("'%s' is equal to '%s'\n", str1, str2);
}
// 比较 str1 和 str3
if (strcmp(str1, str3) == 0) {
printf("'%s' is equal to '%s'\n", str1, str3);
}
return 0;
}
在这个示例中,strcmp函数被用来比较三个字符串str1、str2和str3。根据比较结果,程序会输出相应的信息。
当然在我们使用这个函数的时候也应该注意一下几点:
· 大小写敏感:strcmp 函数是区分大小写的,所以 "Hello" 和 "hello" 会被认为是不同的字符串。
· 非空字符串:strcmp 函数需要确保传入的字符串是非空的,否则可能会导致运行时错误。
· 返回值:strcmp 函数的返回值可以用于条件判断,但不要直接用于数值计算,因为它的确切值可能依赖于具体的实现。
5、变长数组的展示
变长数组的根本特征,就是数组长度只有运行时才能确定,所以变长数组不能初始化。它的好处是程序员不必在开发时,随意为数组指定⼀个估计的长度,程序可以在运行时为数组分配精确的长度。同时变长数组的大小⼀旦确定就不能再变化了。
#include<stdio.h>
int main()
{
int i = 10;
int arr[n];//变长数组,数组的大小是由变量n指定的
int n = 0;
for (n = 0; n < i; n++)
{
arr[n] = n + 1;
printf("%d ", arr[n]);
}
return 0;
}
很遗憾这段代码在VS 2022上由于标准更新的问题,并不能被运行,但这种写法的确是正确的,大家可以作为了解。
以上便是本篇笔记的全部内容,我们继续了第三部分的学习,介绍了循环语句——for循环以及循环语句——do-while语句进行了详细的讲解。在下一篇笔记中,我们将继续第三部分的学习。