一、随机数⽣成
1.rand
C语⾔提供了⼀个函数叫
rand
,这函数是可以⽣成随机数的,函数原型如下所⽰:
int
rand
(
void
);(其中void是“空”的意思,即不需要参数)
rand函数会返回⼀个伪随机数,这个随机数的范围是在0~
RAND_MAX
之间,这个RAND_MAX的⼤⼩是依赖编译器上实现的,但是⼤部分编译器上是32767。
rand函数的使⽤需要包含⼀个头⽂件是:
stdlib.h
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("%d\n", rand());
printf("%d\n", rand());
printf("%d\n", rand());
printf("%d\n", rand());
printf("%d\n", rand());
return 0;
}
运行结果为:
看似随机的五个数,当我们再次运行时,还是这五个数
我们可以看到虽然⼀次运⾏中产⽣的5个数字是相对随机的,但是下⼀次运⾏程序⽣成的结果和上⼀次⼀模⼀样,这就说明有点问题。
如果再深⼊了解⼀下,我们就不难发现,其实rand函数⽣成的随机数是
伪随机的
,伪随机数不是真正的随机数,是通过某种算法⽣成的随机数。真正的随机数的是
⽆法预测
下⼀个值是多少的。⽽rand函数是对⼀个叫
“种⼦”的基准值进⾏运算⽣成的随机数。
之所以前⾯每次运⾏程序产⽣的随机数序列是⼀样的,那是因为rand函数⽣成随机数的
默认种⼦是1。
如果要⽣成
不同的随机数
,
就要让种⼦是变化的
。
2.srand
C语⾔中⼜提供了⼀个函数叫
srand
,⽤来初始化随机数的⽣成器的,srand的原型如下:
void
srand
(
unsigned int
seed);
程序中在调⽤ rand 函数之前先调⽤ srand 函数,通过 srand 函数的参数seed来设置rand函数⽣成随机数的时候的种⼦,
只要种⼦在变化,每次⽣成的随机数序列也就变化起来了。
那也就是说给
srand的种⼦是如果是随机的,rand就能⽣成随机数;
在⽣成随机数的时候⼜需要⼀个随机数,这就⽭盾了。
3.time
在程序中我们⼀般是使⽤程序运⾏的时间作为种⼦的,因为时间时刻在发⽣变化的。
在C语⾔中有⼀个函数叫
time
,就可以获得这个时间,time函数原型如下:
time_t
time
(
time_t
* timer);
time 函数会返回当前的⽇历时间,
其实返回的是1970年1⽉1⽇0时0分0秒到现在程序运⾏时间之间的差值,单位是秒。
返回的类型是time_t类型的,
time_t 类型本质上其实就是32位或者64位的整型类型。(即int类型或者long long 类型)
time函数的参数 timer 如果是⾮NULL的指针的话,函数也会将这个返回的差值放在timer指向的内存中带回去。
如果 timer 是NULL(空指针),就只返回这个时间的差值。time函数返回的这个时间差也被叫做:
时间戳
。
时间戳网址:“https://tool.lu/timestamp/"
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
//使⽤time函数的返回值设置种⼦
//因为srand的参数是unsigned int类型,我们将time函数的返回值强制类型转换
srand((unsigned int)time(NULL));
printf("%d\n", rand());
printf("%d\n", rand());
printf("%d\n", rand());
printf("%d\n", rand());
printf("%d\n", rand());
return 0;
}
运行结果:(两次不同的随机数)
(第一次运行结果)
(第二次运行结果)
注意:srand函数是不需要频繁调⽤的,⼀次运⾏的程序中调⽤⼀次就够了
4.设置随机数的范围
· 如果我们要⽣成0~99之间的随机数,⽅法如下:
rand() %100;(余数的范围是0~99)
· 如果要⽣成1~100之间的随机数,方法如下:
rand()%
100
+
1
;
(%100的余数是0~99,0~99的数字+1,范围是1~100)
· 如果要⽣成100~200的随机数,⽅法如下:
100
+ rand()%(
200-100
+
1
)
(余数的范围是0~100,加100后就是100~200)
· 所以如果要⽣成a~b的随机数,⽅法如下:
a + rand()%(b-a+
1
)
二、猜数字游戏
源代码:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void game()
{
int r = rand() % 100 + 1;
int guess = 0;
while (1)
{
printf("请猜数字>:");
scanf("%d", &guess);
if (guess < r)
{
printf("猜小了\n");
}
else if (guess > r)
{
printf("猜大了\n");
}
else
{
printf("恭喜你,猜对了\n");
break;
}
}
}
void menu()
{
printf("***********************\n");
printf("****** 1. play ******\n");
printf("****** 0. exit ******\n");
printf("***********************\n");
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
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;
}
运行结果:
还可以加上猜数字的次数限制(以五次为例):
源代码:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void game()
{
int r = rand() % 100 + 1;
int guess = 0;
int count = 5;
while (count)
{
printf("\n你还有%d次机会\n", count);
printf("请猜数字>:");
scanf("%d", &guess);
if (guess < r)
{
printf("猜小了\n");
}
else if (guess > r)
{
printf("猜大了\n");
}
else
{
printf("恭喜你,猜对了\n");
break;
}
count--;
}
if (count == 0)
{
printf("你失败了,正确值是:%d\n", r);
}
}
void menu()
{
printf("***********************\n");
printf("****** 1. play ******\n");
printf("****** 0. exit ******\n");
printf("***********************\n");
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
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;
}
运行结果:
三、数组的概念
数组是⼀组相同类型元素的集合;从这个概念中我们就可以发现2个有价值的信息:
•
数组中存放的是1个或者多个数据,但是数组元素个数不能为0。
•
数组中存放的多个数据,类型是相同的。
数组分为⼀维数组和多维数组,多维数组⼀般⽐较多⻅的是⼆维数组。
四、一维数组的创建和初始化
1.数组创建
⼀维数组创建的基本语法如下:
type arr_name[常量值];
存放在数组的值被称为
数组的元素
,数组在创建的时候可以指定
数组的⼤⼩和数组的元素类型
。
•
type
指定的是数组中存放数据的类型,可以是:
char
、
short
、
int
、
float
等,也可以⾃定义的类型。
•
arr_name
指的是数组名的名字,这个名字根据实际情况,起的有意义就⾏。
•
[ ]
中的
常量值
是⽤来指定数组的⼤⼩的,这个数组的⼤⼩是根据实际的需求指定就⾏。
⽐如:我们现在想存储某个班级的20⼈的数学成绩,那我们就可以创建⼀个数组,如下:
int
math[
20
];
当然我们也可以根据需要创建其他类型和⼤⼩的数组:
char
ch[
8
];
double
score[
10
];
2.数组的初始化
有时候,数组在创建的时候,我们需要给定⼀些初始值值,这种就称为初始化的。
那数组如何初始化呢?数组的初始化⼀般使⽤大括号,将数据放在大括号中。
//完全初始化
int num1[5] = {1,2,3,4,5};
//不完全初始化
int num2[6] = {1};//第⼀个元素初始化为1,剩余的元素默认初始化为0
//错误的初始化 - 初始化项太多
int num3[3] = {1, 2, 3, 4};
3.数组的类型
数组也是有类型的,数组算是⼀种⾃定义类型,去掉数组名留下的就是数组的类型。
int num1[10];//num1数组类型是int [10]
int num2[12];//num2数组类型是int[12]
char ch[5];//ch的数组类型是char[5]
五、一堆数组的使用
1.数组下标
C语⾔规定数组是有下标的,下标是从0开始的,假设数组有n个元素,最后⼀个元素的下标是n-1,下标就相当于数组元素的编号,如下:
int
arr[
10
] = {
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
,
10
};
在C语⾔中数组的访问提供了⼀个
操作符 [ ]
,这个操作符叫:下标引⽤操作符。
有了下标访问操作符,我们就可以轻松的访问到数组的元素了,⽐如我们访问
下标为7的元素
,我们就可以
使⽤ arr[7]
,想要访问下标是3的元素,就可以使⽤
arr[3]
,如下代码:
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
printf("%d\n", arr[7]);//8
printf("%d\n", arr[3]);//4
return 0;
}
输出结果:
2.数组元素的打印
源代码:
#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;
}
输出结果:
3.数组的输入
源代码:
#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++)
{
scanf("%d", &arr[i]);
}
//输出
for (i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
输出结果:
4.⼀维数组在内存中的存储
了解⼀下数组在内存中的存储,依次打印数组元素的地址:
#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("&arr[%d] = %p\n ", i, &arr[i]);
}
return 0;
}
输出结果:
其中末尾两位是16进制表示数:0-9+abcdef组成。
从输出的结果我们分析,数组随着下标的增⻓,地址是由⼩到⼤变化的,并且我们发现每两个相邻的元素之间相差4(因为⼀个整型是4个字节)。所以我们得出结论:
数组在内存中是连续存放的。
这就为后期我们使⽤指针访问数组奠定了基础。
突然发现之前的代码不能复制,这就不太方便各位看官共同进步啦,已经更正了!!
大家可以复制代码实践啦!
内容有点多,剩下的放在明天啦!
明天一定出文章,疯狂补更ing!!
各位看管觉得还行给个三连吧!!!今天完结撒花!!!!