哔哩大学计算机学院-C语言编程2023-P38练习 https://www.bilibili.com/video/BV1cq4y1U7sg
1.计算 n的阶乘。 首先初始化n和temp两个局部变量,n用来存放输入的数值,temp用来存放循环计算的中间值,最后输出temp。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> int main () { int n = 0 ; int temp = 1 ; scanf ("%d" , &n); for (int i = 1 ; i <= n; i++) { temp = temp * i; } printf ("n的阶乘是:%d\n" , temp); return 0 ; }
2.计算 1!+2!+3!+..+10! 在上一题的思路上进行扩展,此时已指定为1!+2!+3!+..+10!,则不需要再输入n作为操作数。
同样设置temp_1和temp_2两个变量作为中间值的缓存,其中temp_1存放所有temp_2相加的值,即“temp_1 = temp_1 + temp_2;” 放在第一个for循环里。
第一个for循环里面嵌套一个for循环用于计算当前i的值所属的阶乘,i则从1取到10,最后将结果存放在temp_1中,输出temp_1即1!+2!+3!+..+10!的值,可以通过将i设置为小一点的数如3进行验证。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> int main () { int temp_1 = 0 ; for (int i = 1 ; i <=10 ; i++) { int temp_2 = 1 ; for (int j = 1 ; j <= i; j++) { temp_2 = temp_2 * j; } temp_1 = temp_1 + temp_2; } printf ("1!+2!+3!+..+10!=%d\n" , temp_1); return 0 ; }
当然,两层循环的时间复杂度更高,有没有更优的算法呢?通过继续观看视频发现老师的思路非常妙,从阶乘中寻找规律:
2!= 1 * 2;
3!= 1 * 2 * 3;
4!= 1 * 2 * 3 * 4;
……
由此可以发现,往后的阶乘都是在前一个阶乘的基础上乘以他本身,所以得出一个更优的算法,只用一次循环,就可以计算出1!+2!+3!+..+10! 降低时间复杂度。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> int main () { int temp_1 = 0 ; int temp_2 = 1 ; for (int i = 1 ; i <=10 ; i++) { temp_2 = temp_2 * i; temp_1 = temp_1 + temp_2; } printf ("1!+2!+3!+..+10!=%d\n" , temp_1); return 0 ; }
3.在一个有序数组中査找具体的某个数字n; 当数据量小的时候可以使用直接使用循环进行对比查找,如果想等则输出v[i]。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> int main () { int v[10 ] = { 1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 }; int n = 0 ; scanf ("%d" , &n); for (int i = 0 ; i < 10 ; i++) { if (n == v[i]) printf ("您要找的数字是%d\n" , v[i]); } return 0 ; }
但是对于一个有序的数组来说,或者当数据量较大的时候,还从头循环进行比对效率太低。因为他是有序的数组,不管数字多少,都是从小到大排列的,假设我每次都从中间开始进行判断,如果中间的数字比他大,就说明这个数在前半段区间,然后往复比较中间值最后得出结果,这样的方法肯定效率更高。(二分法)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <string.h> int main () { int v[10 ] = { 1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 }; int len = sizeof (v) / sizeof (v[0 ]); int n = 0 ; scanf ("%d" , &n); int left = 0 ; int right = len; int mid = 0 ; while (left <= right) { mid = (left + right) / 2 ; if (v[mid] < n) { left = mid + 1 ; } else if (v[mid] > n) { right = mid - 1 ; } else { printf ("要查找的数字为:%d\n" , mid + 1 ); break ; } } if (left > right) { printf ("error" ); } return 0 ; }
当输入数字不在数组中,则输出error。
4.编写代码,演示多个字符从两端移动,向中间汇聚。 要实现的目标即类似如下:
假设要打印”Hello World!”,则不断从两端打印,最后输出完整字符串。
“H————–!”
“He———–d!”
……
“Hello World!”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <string.h> #include <Windows.h> int main () { char arr1[] = "Hello World!" ; char arr2[] = "************" ; int left = 0 ; int right = strlen (arr1)-1 ; for (int i = 0 ; i < strlen (arr1); i++) { if (left > right) { break ; } arr2[left] = arr1[left]; arr2[right] = arr1[right]; printf ("%s\n" , arr2); Sleep(500 ); system("cls" ); left++; right--; } printf ("%s\n" , arr2); }
通过替换数组的左右下标的值达到效果,逐行输出。引用”windows.h”头文件的Sleep()函数达到一个延时输出的效果。
5.编写代码实现,模拟用户登录情景,并且只能登录三次。(只允许输入三次密码,如果密码正确则提示登录成,如果三次均输入错误,则退出程序。) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <string.h> #include <Windows.h> int main () { char password[20 ] = "123456" ; char input[20 ] = { 0 }; for (int i = 0 ; i < 3 ; i++) { printf ("请输入密码:>" ); scanf ("%s" , input); if (strcmp (input, password) == 0 ) { printf ("登录成功\n" ); break ; } else if (i == 2 ) { printf ("错误次数超过三次,退出程序\n" ); break ; } else { printf ("登录失败,请重试!\n" ); } } }