【C语言】第二章-分支和循环语句-2

第二章 分支和循环语句

第2节

  在本节中,我会用代码实现几个例子,来供大家深入了解和学习分支以及循环语句。

查找

  查找的含义就是在一个表中找出关键字与所给值相同的元素,如果找到了则返回下标,找不到则返回-1

  这里先演示最为普通的查找,逐个查找,这是最为普通的算法思想。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>//添加头文件
#include <stdlib.h>
int main()//主函数,函数入口
{
int index = -1;
int num = 5;//假设我们要查找的元素是5
int arr[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
for (int i = 0; i < 10; i++)//通过循环遍历数组
{
if (arr[i] == num)
{
index = i;//找到目标元素将下标赋值给index
}
}
printf("%d\n", index);
system("pause");
}

  但是往往这种普通的遍历查找过为复杂,因此在有序的数组中,我们给出第二种更为简单的查找方式,叫做折半查找,这种查找只适用于在有序的素组中,利用减而制之的思想,每次只将目标区域最中心的元素与目标元素(mid)进行对比,如果目标元素大于mid,则将下界更为mid + 1,如果小于mid则将上界改为mid - 1.每一次循环之后都将目标查找区域缩小一半,直到找到目标元素,或是退出循环。

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
37
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>//添加头文件
#include <stdlib.h>
/*
二分查找
参数:数组,目标区间,目标值
返回值:找到则返回元素下标,未找到返回-1
*/
int binFind(int* arr, int low, int high, int num)
{
int mid = 0;
int index = -1;
while (low <= high)
{
mid = (low + high) >> 1;
if (num > arr[mid])
{
low = low + 1;
}
else if (arr[mid] > num)
{
high = high - 1;
}
else
{
index = mid;
break;
}
}
return index;
}
int main()//主函数,函数入口
{
int arr[10] = { 0,1,2,3,4,5,6,7,8,9 };
printf("5在数组中的下表为:%d\n", binFind(arr, 0, 10, 5));
system("pause");
}

  很显然这是极为聪明的一种查找方法,极大的缩短了我们查找的时间,如果学过数据结构的同学自然可以明白其在算法分析上的美妙。这两个查找的示例也同时让我们感受到,一样的目标不一样的程序编写方法,会给我们的程序带来更快的便捷。除此之外,我们还有归并查找,抽样查找等等,对算法感兴趣的同学可以深入了解。

猜数字游戏

  我相信很多同学小时候可能都会玩过一个游戏,规则是由系统随机给出一个数,而我们则在目标区间内进行猜测,知道猜中系统给定的数字为止,那么今天我们就来实现这么一个小游戏。

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>//添加头文件
#include <stdlib.h>
#include <windows.h>
#include <time.h>
int menu()//开始菜单
{
int choice;//选择
printf("1、开始游戏\n");
printf("0、退出\n");
printf("请选择:");
scanf_s("%d", &choice);
return choice;
}
void game()//游戏主逻辑
{
srand(time(0));//设置随机数种子(需要time.h头文件)
int riddle = 0;//用户猜的数字
int num = rand() % 101;//设置随机数,范围0 - 100(需要windows.h头文件)
while (1)
{
printf("请输出你猜的数字:");
scanf_s("%d", &riddle);
if (riddle < num)
{
printf("低了!\n");
}
else if (riddle > num)
{
printf("高了!\n");
}
else
{
break;
}
}
printf("恭喜你猜中了!\n");
}
void gameNumRiddle()//游戏总逻辑
{
while (1)
{
if (menu() == 1)//调用菜单函数
{
game();//游戏开始
}
else
return;//退出游戏
}
}
int main()//主函数,函数入口
{
gameNumRiddle();
system("pause");
}

  在这个游戏的实现中,我们引入了随机数rand()的使用方法,rand()是随机生成一个随机数列,范围是0~至少是65535,也就是说如果我们想让他生成某个范围内的数,我们就用这个随机数列%范围的上界,比如说我们此时需要0 ~ 100的数,我则使用给他% 101,那么问题来了,rand() % 100 + 1的范围是多少呢?我相信很多同学或许猜的出来,就是1 ~ 100。是的关于rand()还有很多灵活的用法,大家可以自行琢磨,但是在使用之前都千万不要忘记加上srand(time(NULL)),那么这句话又有什么含义呢?其实很简单,我们用rand()每次生成的随机数列都是固定的,就是说如果rand()的参数不变那么产生的随机数也不会变,大家在这个程序里可以试一下,我们如果去掉srand()我们每次执行程序所猜的第一个数字永远都只会是一个唯一值。并不会改变。为了改变随机数,我们就要不停地改变参数,但是有什么参数是会一直改变的?时间。因此我们srand()的参数给的正是时间这个参量。但是time()函数准确的来说并不是返回当前的时间。大家可以去参考这个函数的官方文档。

  The value returned generally represents the number of seconds since 00:00 hours, Jan 1, 1970 UTC (i.e., the current unix timestamp). Although libraries may use a different representation of time: Portable programs should not use the value returned by this function directly, but always rely on calls to other elements of the standard library to translate them to portable types (such as localtime, gmtime or difftime).(摘自官方文档)

  总的来说我们用srand()和rand()两个函数创造了随机数,并且赋值利用循环和分支语句让用户进行猜数字,整个程序的算法逻辑还是很简单的。

ATM系统

  最后是一个ATM的密码验证系统,密码输入正确则通过,三次错误退出系统。

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
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>//添加头文件
#include <stdlib.h>
#include <string.h>
void atmPassword()//ATM登陆系统
{
char password[7] = "123456";//默认密码是“123456”
int turn = 0;
char enter[7];
while (turn < 3)//通过循环控制三次输入密码的机会
{
printf("请输入密码:");
scanf("%s", enter);
if (strcmp(enter, password) == 0)//字符串对比函数,如果前后相同返回0
{
break;
}
turn++;
printf("密码输入错误,还有%d次机会!\n", 3 - turn);
}
if (turn < 3)
{
printf("密码正确!\n");
}
else
{
printf("登陆失败!\n");
}
}
int main()//主函数,函数入口
{
atmPassword();
system("pause");
}

  这个程序的逻辑也十分简单,其中借用了一个string.h的库函数字符串对比函数int strcmp ( const char * str1, const char * str2 );,这个函数里有两个参数,分别是指向两个字符串的指针,如果两个字符串相同返回0,如果前面的字符串大于后面的返回大于0的数,反之返回小于0的数,具体比较方法大家也可以去看官方说明文档。

  今天举得几个例子一是为了熟悉分支与循环语句的使用,二是说明一个道理,只凭我们自己手写是无法快捷的写出代码的,因此我们有时需要借助C语言贫瘠的库函数,而使用库函数的具体方法大家一定要多去官方文档查看,看得久了对英文有帮助,同时也可以是我们对库函数的使用有更深的理解。

-------------本文结束感谢您的阅读!-------------
记录学习每一分,感谢您的赞助