Bootstrap

C++研发笔记15——C语言程序设计初阶学习笔记13

        本篇笔记我们继续来学习第三部分《分支语句和循环语句》,在上一篇中我们详细学习了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语句进行了详细的讲解。在下一篇笔记中,我们将继续第三部分的学习。

;