业精于勤荒于嬉,行成于思毁于随。
今天就来综合的联系一下前面的知识。
第十篇
一、for语句,两种方法计算阶乘1.1、一层for循环求阶乘1.2、实现阶乘累和1.3、两层for循环求阶乘 二、if语句,二分查找(在一个有序数组里查找某个具体的数字n)三、模拟字符串向中间汇聚四、模拟用户登录一、for语句,两种方法计算阶乘
计算阶乘,我们就得明白,阶乘是怎么乘的(思考过程很重要)。我们用一个例子来看一下:
1.1、一层for循环求阶乘
5!=54321,那么我们发现它其实就是12345,我们使用for循环实现一下:
#include<stdio.h>int main(){int i, ret = 1;int n;scanf("%d", &n);for (i = 1; i <= n; i++){ret *= i;}printf("%d!=%d\n", n, ret);return 0;}
当然,我们发现,阶乘还有别的特点,比如:
5!= 54!,4!=43!,3!=32!,2!=21,所以我们还可以使用两层for循环实现阶乘,同时,这跟计算阶乘的累和也一样,所以我们先看一看如何实现阶乘的累和:
1.2、实现阶乘累和
阶乘累和,也就是把多个阶乘加起来,那么我们可以使用一个for循环来计算阶乘,再使用一个for循环改变阶乘的对象,也就是下面的代码:
#include<stdio.h>int main(){int i, j, ret, sum = 0;int n;scanf("%d", &n);for (i = 1; i <= n; i++){ret = 1;for (j = 1; j <= i; j++){ret *= j;}//这一个for循环用来计算阶乘sum += ret;}//这一个for循环用来求和printf("%d!=%d\n", n, sum);return 0;}
结果如图:
1.3、两层for循环求阶乘
那么现在我们再来看看两层for循环实现求阶乘(主要是锻炼思维):
5!= 5 * 4!,4!=4 * 3!,3!=3 * 2!,2!=2 * 1
这个该怎么改代码?
其实式子需要修改成这样:
5!=5 * 4 * 3 * 2 * 1 = 4 * 4!+4!,现在是不是豁然开朗?
现在我们把式子写完全:
5!=4 * 4!+4!
4!=3 * 3!+3!
3!=2 * 2!+2!
2!=1 * 1!+1!
所以n!=(n-1)(n-1)! + … + 44!+33!+22!+1!+1
所以我们发现,求阶乘本身其实本质就是求阶乘的累和(所以也可以递归求解阶乘,笔者递归求阶乘的链接:递归:斐波那契数列、阶乘、求字符串长度、n的k次方的分析):
#include<stdio.h>int main(){int i, j, ret, sum = 0;int n;scanf("%d", &n);for (i = 1; i <= n - 1; i++){ret = 1;for (j = 1; j <= i; j++){ret *= j;}//这一个for循环用来计算阶乘sum += i * ret;}//这一个for循环用来求和printf("%d!=%d\n", n, sum + 1);return 0;}
分析的过程很重要:
二、if语句,二分查找(在一个有序数组里查找某个具体的数字n)
二分查找,也叫折半查找,当然,使用的前提是数组有序,就是说:
搜索过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜索过程结束;如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。如果在某一步骤数组为空,则代表找不到。这种搜索算法每一次比较都使搜索范围缩小一半。
我们以在1-10的数字中查找7为例:(只需查找四次)
假设我们查找的数字是7,那么第一步,会首先查找下标(0+9)/2 = 4,判断比5大还是比5小;
而后发现比5大,所以右移,与5 - 9的中间数字(5 + 9) / 2 = 7比较;
这个时候,发现8比7大,所以right下标左移,移到下标7的左边;
而后left下标所指的数字比我们要找的小,所以右移,但因为不能超过right,所以最终left = right,查找结束。
注意前提条件:数组必须有序!
现在我们代码实现一下这个过程:
int main(){int arr[] = {1,2,3,4,5,6,7,8,9,10 };//查找kint sz = sizeof(arr) / sizeof(arr[0]);int k = 7;int left = 0;int right = sz - 1;while (left <= right) {//一次查找:int mid = (left + right) / 2;if (arr[mid] < k)//小了就left右移{left = mid + 1;}else if (arr[mid] > k)//大了就right左移{right = mid - 1;}else{printf("找到了,下标是:%d\n", mid);break;}}if (left > right)printf("没找着\n");return 0;}
重在分析。
三、模拟字符串向中间汇聚
比如:
Hello World! 应该这样出现:
H########!
He######d!
Hel#####ld!
…
Hello World!
这个其实比较简单,我们定义两个字符数组,然后覆盖赋值就可以,直接看代码吧:
#include<stdio.h>#include<string.h>#include<windows.h>int main(){char str1[] = {"Hello World!" };char str2[] = {"############" };int left = 0;int right = strlen(str1) - 1;while (left <= right){str2[left] = str1[left];str2[right] = str1[right];printf("%s\n", str2);Sleep(500);//每次延迟500毫秒left++;right--;}return 0;}
结果如图:
当然,也可以使用system(“cls”)来实现每次清屏,让结果看起来更有汇聚的感觉,使用延迟就是为了让程序体现出慢慢汇聚的感觉,感兴趣的小伙伴可以用代码试一试。
四、模拟用户登录
我们编写代码模拟用户登录的情景,并且只允许登录三次(就是只能三次输入密码,密码正确就登录成功,如果三次均失败,就退出程序)
这里我们使用一个库函数:strcmp:
这里只需要注意它的返回值:
我们假设密码是确定的(也可以先让用户输入),那么我们来看一看代码吧:
#include<stdio.h>#include<string.h>int main(){int i = 0;char password[20] = {0 };//假设密码是“abcdef”char pw[] = {"abcdef" };for (i = 0; i < 3; i++){printf("请输入密码:\n");scanf("%s", password);if (strcmp(password, pw) == 0){printf("密码正确,登陆成功!\n");break;}elseprintf("密码错误,请重新输入:\n");}if (i == 3)printf("三次密码均输入错误,退出程序\n");return 0;}
运行结果如图:
C语言中阶第四篇:分支与循环语句练习 求阶乘的多种方法(两层for循环求阶乘) 二分查找 字符串汇聚以及模拟用户登录