文章目录
时隔将近一个星期,整顿好自己,今天开始继续更新博客。今天分享的是近期见过做过的一些习题。
1.计算n的阶乘。
不考虑溢出情况
#include<stdio.h>
int main()
{
int n = 0;
//输入
scanf("%d", &n);
//计算n的阶乘
int i = 0;
int ret = 1;
for (i = 1; i <= n; i++)
{
ret *= i;
}
printf("%d\n", ret);
return 0;
}
运行结果图:
但是,这里有个注意点:当我们输入100时,运行结果却是:
很显然我们可以发现,输出结果为0。
这是因为100!已经出现溢出的现象了。
引申
若想知道一个整型所表达的最大值,我们可以:
#include<limits.h>
INT_MAX
由此可知整型是有上限的。
2.计算1!+2!+…+10!
在例题1的基础上,让阶乘累加,代码如下:
#include<stdio.h>
int main()
{
int n = 0;
//输入
int i = 0;
int ret = 1;
int sum = 0;
for (n = 1; n <= 10; n++)
{
ret = 1;//**需要将ret的值每次初始到1,否则会影响sum的值**
//计算n的阶乘
for (i = 1; i <= n; i++)
{
ret *= i;
}
sum += ret;
}
printf("%d\n", sum);
return 0;
}
但是!以上代码中会有许多重复性的工作,于是我们可以这样优化代码:
#include<stdio.h>
int main()
{
int n = 0;
//输入
int i = 0;
int ret = 1;
int sum = 0;
for (n = 1; n <= 10; n++)
{
ret *= n;
sum += ret;
}
printf("%d\n", sum);
return 0;
}
3.在一个有序数组中查找具体的某个数字n。(二分查找详解)
#include<stdio.h>
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
// 0 1 2 3 4 5 6 7 8 9 下标
int k = 7;//k是要查找的数字
int i = 0;
int sz = sizeof(arr) / sizeof(arr[0]);//求元素个数
int flag = 0;
for (i = 0; i < sz; i++)
{
if (k == arr[i])
{
flag = 1;
printf("找到了,下标是%d\n", i);
break;
}
if (flag == 0)
printf("找不到\n");
}
return 0;
}
以上代码效率低下。
以下是二分查找思路:
#include<stdio.h>
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
// 0 1 2 3 4 5 6 7 8 9 下标
int k = 7;//k是要查找的数字
int i = 0;
int sz = sizeof(arr) / sizeof(arr[0]);//求元素个数
//折半查找(二分查找)前提是在【有序数组】
int left = 0;
int right = sz - 1;
int flag = 0;
while(left <= right)
{
int mid = (left + right) / 2;
if (arr[mid] < k)
{
left = mid + 1;
}
else if (arr[mid] > k) {
right = mid - 1;
}
else
{
printf("找到了,下标是%d\n", mid);
flag = 1;
break;
}
if (flag == 0)
{
printf("找不到。\n");
}
}
return 0;
}
运行结果:
但是,此代码还是具有一定的风险
int mid = (left + right) / 2;
可能会出现 left+right 的值溢出int,所以对代码可进行以下优化:
#include<stdio.h>
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
// 0 1 2 3 4 5 6 7 8 9 下标
int k = 7;//k是要查找的数字
int i = 0;
int sz = sizeof(arr) / sizeof(arr[0]);//求元素个数
//折半查找(二分查找)前提是在【有序数组】
int left = 0;
int right = sz - 1;
int flag = 0;
while (left <= right)
{
//int mid = (left + right) / 2;///有潜在风险
int mid = left + (right - left) / 2;
if (arr[mid] < k)
{
left = mid + 1;
}
else if (arr[mid] > k) {
right = mid - 1;
}
else
{
printf("找到了,下标是%d\n", mid);
flag = 1;
break;
}
if (flag == 0)
{
printf("找不到。\n");
}
}
return 0;
}
4. 编写代码,演示多个字符从两端移动,向中间汇聚。
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[] = "welcome to my gitee!!";
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);
left++;
right--;
}
return 0;
}
其中int right = strlen(arr1) - 1;
,因为 arr 是从0开始计,而 strlen 是计算字符长度从1开始计,故需要strlen去减1。
运用strlen
需要引用#include <string.h>
运行结果如图:
同时,若追求运行结果的呈现,我们可以引用 #include<windows.h> Sleep(1000);
即
#include<stdio.h>
#include<string.h>
#include<windows.h>
int main()
{
char arr1[] = "welcome to my gitee!!";
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);
left++;
right--;
}
return 0;
}
就会有动态效果。
若是想改良welcome to my gitee在同一行呈现,可使用system(“cls”);
系统清屏。
#include<stdio.h>
#include<string.h>
#include<windows.h>
int main()
{
char arr1[] = "welcome to my gitee!!";
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");
left++;
right--;
}
printf("%s\n", arr2);
return 0;
}
for循环来写的话呢:
#include<stdio.h>
#include<string.h>
#include<windows.h>
int main()
{
char arr1[] = "welcome to my gitee!!";
char arr2[] = "*********************";
int left = 0;
int right = strlen(arr1) - 1;
for (left = 0, right = strlen(arr1) - 1;left <= right;left++,right--)
{
arr2[left] = arr1[left];
arr2[right] = arr1[right];
printf("%s\n", arr2);
Sleep(1000);
system("cls");
}
printf("%s\n", arr2);
return 0;
}
5. 编写代码实现,模拟用户登录情景,并且只能登录三次。(只允许输入三次密码,如果密码正确则提示登录成功,如果三次均输入错误,则退出程序。
#include<stdio.h>
int main()
{
int i = 0;
char password[20] = { 0 };
int flag = 0;
for (i = 0; i < 3; i++)
{
printf("请输入密码:>");
scanf("%s", password);
//判断
if (strcmp(password, "123456") == 0)
{
flag = 1;
printf("密码正确\n");
break;
}
else
{
printf("密码错误\n");
}
}
if (flag == 0)
printf("三次密码均错误,退出程序\n");
return 0;
}
注意点
1.== 不能判断两个字符串是否相等,得使用:strcmp
strcmp(password, "123456") == 0
2.其次,char password[20] = { 0 };
数组名本来就是地址,所以使用scanf不需要取地址
scanf("%s", password);
6.猜数字游戏的实现
流程:
关于随机数的生成
rand()函数
相关介绍:
1.rand()函数用来产生随机数,但是,rand()的内部实现是用线性同余法实现的,是伪随机数,由于周期较长,因此在一定范围内可以看成是随机的。
2.rand()会返回一个范围在0到RAND_MAX(至少是32767)之间的伪随机数(整数)。
在调用rand()函数之前,可以使用srand()函数设置随机数种子,如果没有设置随机数种子,rand()函数在调用时,自动设计随机数种子为1。随机种子相同,每次产生的随机数也会相同。
3.rand()函数需要的头文件是:<stdlib.h>
4.rand()函数原型: int rand(void);
5.使用rand()函数产生1-100以内的随机整数:int number1 = rand() % 100+1;
srand函数
相关介绍
1.srand()函数需要的头文件仍然是:<stdlib.h>
2.srand()函数原型:void srand (usigned int seed);
3.srand()用来设置rand()产生随机数时的随机数种子。参数seed是整数,通常可以利用time(0)或getpid(0)的返回值作为seed。
运用:
***void game()
{
int ret = rand();
printf("%d\n", ret);
}***
可以发现代码两次运行的结果一致,随机数不随机。
问题出在:使用rand()函数的方式有问题。
在调用rand()函数之前,应该使用srand函数对伪随机数生成器进行种子处理。
先测试srand
void game()
{
srand(1);
int ret = rand();
printf("%d\n", ret);
}
结果:
void game()
{
srand(100);
int ret = rand();
printf("%d\n", ret);
}
结果:
所以我们应该在srand()括号内加一个随机数,即可以添加时间戳。
关于时间戳
如何获得时间戳呢
使用time函数 time_t time(time_ttimer* )
time函数相关总结
void game()
{
//设置随机数的生成器
srand((unsigned int)time(NULL));
int ret = rand();
printf("%d\n", ret);
}
但是当我们按1的速度较快时,生成的随机数比较接近。
所以我们可以把srand((unsigned int)time(NULL));
转移至主函数中
int main()
{
***srand((unsigned int)time(NULL));***
int input = 0;
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误\n");
break;
}
} while (input);
return 0;
}
这样子生成的随机数才随机。
如何生成1~100的随机数呢
int ret = rand()%100;//0~99
int ret = rand()%100+1;//1~100
游戏主干
//2.猜数字
int guess = 0;
while (1)
{
printf("请猜数字:>");
scanf("%d", &guess);
if (guess < ret)
{
printf("猜小了\n");
}
else if (guess > ret)
{
printf("猜大了\n");
}
else
{
printf("恭喜你,猜对了\n");
break;
}
}
菜单生成
void menu()
{
printf("*********************************\n");
printf("********* 1. play *********\n");
printf("********* 0. exit *********\n");
printf("*********************************\n");
}
总代码:
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
void menu()
{
printf("*********************************\n");
printf("********* 1. play *********\n");
printf("********* 0. exit *********\n");
printf("*********************************\n");
}
//rand函数会返回一个0-32767之间的随机数
RAND_MAX--rand函数能返回随机数的最大值。
//时间戳
void game()
{
//时间戳的获得 time函数
//设置随机数的生成器
// srand((unsigned int)time(NULL));
//1.生成随机数字
//rand用来生成随机数的函数
int ret = rand()%100+1;//0~99+1---->1~100
// printf("%d", ret);
//2.猜数字
int guess = 0;
while (1)
{
printf("请猜数字:>");
scanf("%d", &guess);
if (guess < ret)
{
printf("猜小了\n");
}
else if (guess > ret)
{
printf("猜大了\n");
}
else
{
printf("恭喜你,猜对了\n");
break;
}
}
}
int main()
{
srand((unsigned int)time(NULL));
int input = 0;
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误\n");
break;
}
} while (input);
return 0;
}
运行结果:
7.九九乘法表
#include<stdio.h>
int main()
{
int i = 0;
for (i = 1; i < 9; i++)
{
//打印一行的数据
int j = 0;
for (j = 1; j <= i; j++)
{
printf("%d*%d=%-2d ", i, j, i * j);
}
printf("\n");
}
return 0;
}
8.求十个整数中最大的数
这种题的思路就好比在10个人中,两两打擂台,最终获胜者即为最大数
#include<stdio.h>
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
// 下标 0,1,2,3,4,5,6,7,8,9
//类比于10个人
int max = arr[0]; //选出一个人迎接擂台赛
int i = 0;
//打擂台
for (i = 1; i < 10; i++)
{
if (arr[i] > max)
max = arr[i];
}
printf("%d\n", max);
return 0;
}
9.分数求和:计算1/1-1/2+1/3-1/4+1/5 …… + 1/99 - 1/100 的值,打印出结果。
#include<stdio.h>
int main()
{
int i = 0;
float sum = 0.0;
for (i = 1; i <= 100; i++)
{
sum += 1 / i;//问题所在
}
printf("%f\n", sum);
return 0;
}
//输出结果:1.000000
//改进:
#include<stdio.h>
int main()
{
int i = 0;
float sum = 0.0;
int flag = 1;
for (i = 1; i <= 100; i++)
{
sum += flag*1.0f / i;//改进之处,sum += 1.0f / i
flag = -flag;
}
printf("%f\n", sum);
return 0;
}
10.编写程序数一下 1到 100 的所有整数中出现多少个数字9.
#include<stdio.h>
int main()
{
int i = 0;
int count = 0;
for (i = 1; i <= 100; i++)
{
if (i / 10 == 9)//十位
count++;
if (i % 10 == 9)//个位
count++;
}
printf("%d\n", count);
return 0;
}
以上也就是2023_2_19所总结与循环有关的习题,明天也会继续更新一些习题,在此也祝各位新年快乐!