二、随机函数
随机函数能够产生随机的整数。
计算机的随机都是假随机。是使用一套算法计算出来的一系列让人看不出规律的数。
#include <stdlib.h>
std stdandard标准 lib library库 标准库头文件,头文件中声明了很多不同功能函数。
#include <time.h>
srand(); //设置随机种子的函数,后面生成的一系列随机数,都是根据种子数计算出来的。
//seed random set random
rand(); //random 产生一个随机数,每调用一次rand()会产生一个随机数
time(); //获得当前时间,单位是秒
示例:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i;
srand(0);//使用0作为随机的种子数,后面生成的所有的随机数都是根据0计算出来的
for(i = 0;i < 10;i++)//循环10次生成10个随机数
{
printf("%d ", rand());//rand()通过返回值给我们提供随机数
}
printf("\n");
return 0;
}
所有人得到的随机数都是一样的,证明计算机的随机数是假随机,是根据种子数使用一套算法计算出来的。
所以我们只需要让种子不一样,得到的随机数也就不一样
示例:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
srand(time(0));//为了让随机看上去更加的真实,我们使用当前的时间作为种子数,time(0)是固定用法获得当前时间的功函数,时间从1970年..到现在的秒数,只要程序不是在同一秒内运行,那么生成的随机数就不一样
int i;
for(i = 0;i < 10;i++)
{
int r = rand()%100;//rand生成的随机数,是无符号int全范围的数,范围太大,所以我们会使用%限制范围,%100将随机数范围限制在0~99
printf("%d ", r);
}
printf("\n");
return 0;
}
思考:
-10~10闭区间
N表示随机数范围内数的数量 -10~10闭区间之间有21个数
rand()%N+范围内最小值
rand()%21+(-10)
随机数编程示例:
随机出一个数,一个 0~10 以内的数字。然后请你猜 3 次。
如果猜对了,结束程序,并且输出"Congratulations!"。
如果没有猜对,那么提示一下,你的输入是偏大了,还是偏小。如果3次没猜对,GAMEOVER
1.随机一个数,作为答案
2.循环3次,for
3.用户输入
4.比较大小(输入和答案比)
5.如果猜对,输出"Congratulations!",结束循环
6.如果猜错,输出大或者小,回到步骤3
7.循环结束i==3说明3次都猜错了。输出GAMEOVER
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
int i, num, result;
srand(time(0));
result = rand()%10;
//printf("result = %d\n", result);
for(i = 0;i < 3;i++)
{
scanf("%d", &num);
if(num > result)
{
printf("偏大了\n");
}
else if(num < result)
{
printf("偏小了\n");
}
else
{
printf("恭喜猜对了%d\n",result);
break;
}
}
if(i == 3)//说明没有执行猜对了,因为猜对了结束循环,此时i一定小于3
{
printf("GAME OVER %d\n", result);
}
return 0;
}
阶段练习:
编写程序,实现:彩票35选7.
要求:
- 用户输入7个数(模拟买彩票选数),保证不能有重复。
- 系统随机出 1~35 之间不重复的7个数。
- 开奖时,统计猜中数值的个数。(不按顺序)
- 打印中奖金额。
思路:
用户输入的数组 int user[7]
系统开奖的数组 int sys[7]
查重思路
int a[5] = {1,2,3,4,5};
int b[5] = {2,3,4,5,6};
int i, j;
//使用a中的每个元素,和b中的所有元素进行比较
for(i = 0;i < 5;i++)//遍历a
{
//当i=0时,a[0]会和b数组所有元素比较一遍
//当i=1时,a[1]会和b数组所有元素比较一遍
for(j = 0;j < 5;j++)//遍历b
{
if(a[i] == b[j])//这个if一共会比较多少次?25次
{
}
}
}
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
srand(time(0));
int user[7];
int sys[7];
//用户输入
int i, j;
for(i = 0;i < 7;i++)
{
scanf("%d", &user[i]);
//判断输入在1~35之间
if(user[i]<1 || user[i]>35)
{
i--;//i元素重新输入
printf("输入超出范围1~35\n");
continue;
}
//查重
//判断i元素之前是否有重复
for(j = 0;j < i;j++)
{
if(user[i] == user[j])//判断重复
{
i--;//i元素重新输入
printf("出现输入的重复\n");
break;
}
}
}
//生成开奖数字
for(i = 0;i < 7;i++)
{
sys[i] = rand()%35+1;//1~35
//查重 判断i元素之前是否有重复
for(j = 0;j < i;j++)
{
if(sys[i] == sys[j])
{
i--;
break;//停止for(j = 0;j < i;j++)
}
}
}
//输出开奖数字
for(i = 0;i < 7;i++)
{
printf("%d ", sys[i]);
}
printf("\n");
//判断中奖信息
int count = 0;//计数,初始化为0
for(i = 0;i < 7;i++)//sys
{
for(j = 0;j < 7;j++)//user
{
if(sys[i] == user[j])
{
count++;
}
}
}
//显示中奖信息
switch(count)
{
case 7:
printf("1000000\n");
break;
case 6:
printf("100000\n");
break;
case 5:
printf("10000\n");
break;
case 4:
printf("1000\n");
break;
case 3:
printf("10\n");
break;
case 2:
case 1:
case 0:
printf("tk\n");
}
return 0;
}
三、冒泡排序
为了方便数据处理,我们经常需要排序。
排序的方法不止冒泡排序。为什么学习冒泡?因为它好写。
冒泡排序是排序效率最低的排序方法之一。
当排序的数据量很小的时候,是很难感觉到高效的排序算法的效率提升的。但是高效的排序算法代码一般都挺难写,所以当数据量很小的时候,冒泡排序好写的优势就体现出来了。
1.冒泡的原理
分析: int a[7] = {85, 72, 65 ,79, 53, 95, 87};
冒泡的原理(升序):比较数组中相邻的两个元素,前者大于后者,交换两个元素的值。
有N个数,需要比较N-1次。
2.冒一个泡
#include <stdio.h>
int main()
{
int a[] = {85, 72, 65, 79, 53, 95, 87};
int i;
//循环遍历整个数组,因为数组有7个数,所以我们需要比较7-1次
for(i = 0;i < 7-1;i++)
{
if(a[i] > a[i+1])//比较相邻两个元素
{
//前者大于后者,就交换两个元素的值
int temp = a[i];
a[i] = a[i+1];
a[i+1] = temp;
}
}
//此时完成冒泡,输出查看结果
for(i = 0;i < 7;i++)
{
printf("%d ", a[i]);//72 65 79 53 85 87 95
}
printf("\n");
return 0;
}
3.冒泡排序
我们只需要反复的执行冒泡过程,最终数组就会有序。需要进行的冒泡次数是N-1次,7个数需要冒泡6次。
#include <stdio.h>
int main()
{
int a[] = {85, 72, 65, 79, 53, 95, 87};
int i,j;
//反复进行冒泡,需要进行N-1次冒泡,数组有序
for(j = 0;j < 7-1;j++)
{
//内层循环用来冒一个泡,-j的目的是因为每一轮冒泡都比上一轮少比较一次
for(i = 0;i < 7-1-j;i++)
{
if(a[i] > a[i+1])
{
int temp = a[i];
a[i] = a[i+1];
a[i+1] = temp;
}
}
}
//输出结果
for(i = 0;i < 7;i++)
{
printf("%d ", a[i]);
}
printf("\n");
return 0;
}
思考:
如果在某一轮冒泡的时候,没有发生交换,说明数组已经有序了,那么后面的冒泡轮次就没有比较进行了。
比如上图中是在第4轮冒泡中完成的数组排序,然后我们在第5轮冒泡的时候发现没有发生交换,于是第5轮之后的冒泡轮次就没有必要执行了。
#include <stdio.h>
int main()
{
int a[] = {85, 72, 65, 79, 53, 95, 87};
int i,j;
//反复进行冒泡,需要进行N-1次冒泡,数组有序
for(j = 0;j < 7-1;j++)
{
int flag = 0;//用作标记本轮冒泡中是否发生交换
//内层循环用来冒一个泡,-j的目的是因为每一轮冒泡都比上一轮少比较一次
for(i = 0;i < 7-1-j;i++)
{
if(a[i] > a[i+1])
{
int temp = a[i];
a[i] = a[i+1];
a[i+1] = temp;
flag = 1;//如果发生交换,改变flag的值
}
}
if(flag == 0)
{
break;//如果flag值没有发生改变,那么说明数组已经有序,结束冒泡轮次
}
}
//输出结果
for(i = 0;i < 7;i++)
{
printf("%d ", a[i]);
}
printf("\n");
return 0;
}
四、二维数组
1. 二维数组的本质
2. 如何定义
int a[2][3];
[2]说明a是有2个元素组成的数组。
[3]说明a的每个元素,是一个3个元素组成的一维数组。
int 说明作为a的子数组元素类型是int。
这样的数组a我们简称为二维数组。
换句话说,数组元素是一维数组的数组,我们叫做二维数组。
为了方便表达叫作为a元素的数组为 子数组。注意,C语言中没有子数组的概念
3.如何赋值
a[0][0] = 10;//a[0]数组的0元素赋值 10 是int变量
a[1][2] = 20;//a[1]数组的2元素赋值 20 是int变量
能不能给 a[0]赋值?不能,数组不能被整体赋值,只能对元素赋值,如果元素还是数组,那么就得对元素的元素赋值。
4. 遍历
遍历二维数组就是在遍历N个一维数组
遍历二维数组,一般使用双重for循环,外层循环遍历第一个角标,内层循环遍历第二个角标。
#include <stdio.h>
int main()
{
int a[2][3];
int i, j;
for(i = 0;i < 2;i++)//遍历数组a,数组a有2个元素 分别是a[0]和a[1]
{
//遍历子数组
/*
i = 0时,遍历a[0]数组 a[0]数组有3个元素
i = 1使,遍历a[1]数组 a[1]数组有3个元素
*/
for(j = 0;j < 3;j++)
{
a[i][j] = i*j;//a[i][j]是一个整型变量
printf("%d\n", a[i][j]);
}
}
return 0;
}
5. 初始化
三种初始化的概念和一维数组是一样的。
完全初始化:
int a[2][3] = {{1,2,3},{4,5,6}};
//a[0]:1,2,3 a[1]:4,5,6
int a[2][3] = {1,2,3,4,5,6};
//a[0]:1,2,3 a[1]:4,5,6
//在完全初始化中,里面的{}写不写无所谓
部分初始化:
int a[2][3] = {1,2,3};
//a[0]:1,2,3 a[1]:0 0 0 a[1]默认补0
int a[2][3] = {{1},{2,3}};
//a[0]:1,0,0 a[1]:2,3,0
默认初始化:
在二维数组中,第一个角标表示数组的元素个数,所以默认初始化的时候,只有第一个角标可以省略。
第二个角标表示数组的元素类型,所以第二个角标一定不能省略。
int a[][3] = {{1,2,3},{4,5,6}};
//a[0]:1,2,3 a[1]:4,5,6
int a[][3] = {1,2,3,4};
//a[0]:1,2,3 a[1]:4,0,0
6. 类型
二维数组的类型是二维数组的子数组的元素类型,可以是任何类型。
五、二维数组编程示例
编程示例1:
定义一个二维数组。初始化。并输出
#include <stdio.h>
int main()
{
int a[3][5] = {{1,2,3,4,5},{5,4,3,2,1},{1,3,5,7,9}};
int i, j;
for(i = 0;i < 3;i++)
{
for(j = 0;j < 5;j++)
{
printf("%d ", a[i][j]);//打印a[i]数组的j元素
}
printf("\n");//每打印完一个数组换行
}
return 0;
}
编程示例2:
对二维数组中每个元素相加,求和
先初始化一个二维数组。使用示例1数组。
#include <stdio.h>
int main()
{
int a[3][5] = {{1,2,3,4,5},{5,4,3,2,1},{1,3,5,7,9}};
int i, j;
int sum = 0;
for(i = 0;i < 3;i++)
{
for(j = 0;j < 5;j++)
{
sum += a[i][j];
}
}
printf("%d\n", sum);
return 0;
}
编程示例3:
已知,有两个二维数组,初始化的。请将这个两个二维数组中对应位置的元素相加,将结果放在第三个二维数组中
#include <stdio.h>
int main()
{
int a[2][3] = {1,2,3,4,5,6};
int b[2][3] = {3,4,5,6,7,8};
int c[2][3];
int i, j;
for(i = 0;i < 2;i++)
{
for(j = 0;j < 3;j++)
{
c[i][j] = a[i][j]+b[i][j];
printf("%d ", c[i][j]);
}
printf("\n");
}
return 0;
}
编程示例4:
用二维数组表示一个6*8的平面直角坐标系,默认显示*,输入对应的位置和一个字符,给二维数组中相应的位置赋值,以行列的形式打印二维数组。
这道题的根本目的是使用二维数组表示直角坐标系中显示的数据。是二维数组的常见用法之一。
- 第一个角标表示Y轴,第二个角标表示X轴。
- X轴向右递增,Y轴向下递增。
- 坐标原点(0,0)在左上角。
2 3 &
char a[8][6];
* * * * * * a[0]
* * * * * * a[1]
* * * * * * a[2]
* * & * * * a[3]
* * * * * * a[4]
* * * * * * a[5]
* * * * * * a[6]
* * * * * * a[7]
#include <stdio.h>
int main()
{
char a[8][6];
printf("初始化坐标系:\n");
for (int i = 0; i < 8; ++i) {
for (int j = 0; j < 6; ++j) {
a[i][j]='*';
printf("%c ",a[i][j]);
}
printf("\n");
}
int x,y;
char signal;
printf("请输入坐标和符号 :\n");
scanf("%d %d %c",&x,&y,&signal);
a[y][x]=signal;
printf("输入的符号在坐标轴中的位置为:\n");
for (int i = 0; i < 8; ++i) {
for (int j = 0; j < 6; ++j) {
printf("%c ",a[i][j]);
}
printf("\n");
}
return 0;
}
编程示例5:
鞍点。 判断数组中是否存在鞍点,在该行最大,并且在该列最小
int a[3][4];
1 2 6 4 a[0]
5 6 7 8 a[1]
9 10 11 12 a[2]
6是鞍点
#include <stdio.h>
int main()
{
int a[3][4]={1,2,6,4,
5,6,7,8,
9,10,11,12};
int i,j,k,x,y;
printf("二维数组为:\n");
for ( i = 0; i < 3; ++i) {
for ( j = 0; j < 4; ++j) {
printf("%d ",a[i][j]);
}
printf("\n");
}
int max=a[0][0];
for ( i = 0; i < 3; ++i) {
for ( j = 0; j < 4; ++j) {
if (a[i][j] > max)
{
x=j;
y=i;
max=a[i][j];
}
}
int count=0;
for ( k = 0; k < 3; ++k) {
if(a[k][x]<max)
{
count++;
}
}
if(count==0)
{
printf("数组的鞍点为%d,坐标为(%d,%d)\n",
max,y,x);
break;
}
}
return 0;
}
编程示例6:
请将杨辉三角形(7阶)保存在二维数组中,并输出。
1 0 0 0 0
1 1 0 11=00+01
1 2 1 0 21=10+11
1 3 3 1 32=21+22
1 4 6 4 1
1 5 10 10 5 1
#include <stdio.h>
#define YH 7
int main()
{
int yh[YH][YH]={1};
for (int i = 1; i < YH ; ++i) {
yh[i][0]=1;
for (int j = 1; j < i+1; ++j) {
yh[i][j]=yh[i-1][j-1]+yh[i-1][j];
}
}
for (int i = 0; i < YH ; ++i) {
for (int j = 0; j < YH - i; ++j) {
printf(" ");
}
for (int j = 0; j < i+1; ++j) {
printf("%4d ",yh[i][j]);
}
printf("\n");
}
return 0;
}
编程示例6:
请将杨辉三角形(7阶)保存在二维数组中,并输出。
1 0 0 0 0
1 1 0 11=00+01
1 2 1 0 21=10+11
1 3 3 1 32=21+22
1 4 6 4 1
1 5 10 10 5 1
#include <stdio.h>
#define YH 7
int main()
{
int yh[YH][YH]={1};
for (int i = 1; i < YH ; ++i) {
yh[i][0]=1;
for (int j = 1; j < i+1; ++j) {
yh[i][j]=yh[i-1][j-1]+yh[i-1][j];
}
}
for (int i = 0; i < YH ; ++i) {
for (int j = 0; j < YH - i; ++j) {
printf(" ");
}
for (int j = 0; j < i+1; ++j) {
printf("%4d ",yh[i][j]);
}
printf("\n");
}
return 0;
}