制作网站的公司注册资本要多少,欧美做受网站视频播放,语音识别程序代做网站,最近发生的国内热点事件数组的概念
什么是数组
数组是相同类型#xff0c;有序数据的集合。
数组的特征 数组中的数据被称为数组的元素#xff0c;是同构的 数组中的元素存放在内存空间里 (char player_name[6]#xff1a;申请在内存中开辟6块连续的基于char类型的变量空间)
衍生概念#x…数组的概念
什么是数组
数组是相同类型有序数据的集合。
数组的特征 数组中的数据被称为数组的元素是同构的 数组中的元素存放在内存空间里 (char player_name[6]申请在内存中开辟6块连续的基于char类型的变量空间)
衍生概念下标索引 下标或索引代表了数组中元素距离第一个元素的偏移位置。 数组中元素的地址值下标越大地址值越大。每一块内存空间都有一个独有的内存地址。 数组的下标是从0开始的。
一维数组
数组的定义 类型说明符 数组名[数组容量]
说明 数组的类型说明符由数组中的元素来决定也就是元素是什么类型数组就是什么类型 数组名也是标识符 我们所说的数组(名)大家可以理解为数据类型是数组的变量(名)。 数组容量也可以叫做常量表达式举例 int ages[10]、int lcd[1024*768]
类型代表了数组中元素的类型
容量数组中能存储多少个元素数组容量可以是一个常量、常量表达式还可以是符号常量但必须是整型。
深入理解定义一个数组相当于申请了一个可以容纳所指定元素数量的内存单元。所申请的内存单元是连续的。
定义一个数组相当于定义了多个匿名变量这些变量可以通过 数组名[下标] 来标识。
举例
// 定义一个数组
int arr[10];
// 问题上面数组中最小下标0最大下标9
经过上面的案例分析得到 数组的最大下标 数组元素个数数组容量 - 1
数组元素的访问
原则数组中的元素不能一次性访问所有元素只能一个一个的访问。
访问方式
数组名[下标];
举例
// 定义一个容纳10个元素的int数组
int arr[10];
// 给数组的第一个元素进行赋值
arr[0] 89;
// 访问数组的第一个元素
int a arr[0];
// 问题以下访问是否正确
int b arr[10]; // error下标越界异常
注意数组元素的访问一定不能越界。
案例
/*
需求一维数组案例-引用数组元素。利用循环给数组元素a[0]~a[9]赋值0~9并且逆序输出
*/
#include stdio.h
int main()
{// 创建一个数组int arr[10];// 使用for循环给数组赋值for(int i 0;i 10;i){arr[i] i;}// 逆序输出// 我们通过循环将数组中的元素一个个取出来称之为遍历for(int j 9;j 0;j--){printf(%d ,arr[j]);}printf(\n); // 纯粹换行return 0;
}
数组的初始化
定义数组的同时用指定数据来给对应元素赋值。
简化数组定义后需要对元素一一赋值操作。
语法规则 类型 数组名[容量] {常量1常量2常量3...};
注意事项 数组可以部分初始化也就是可以给数组中前几个元素初始化未被初始化的元素系统将自动初始化如0如果定义数组时未指定数据容量则系统会根据初始化元素的个数来决定数组容量。
// 1. 如果定义数组时只给数组前几个初始化后续剩余元素会自动完成初始化比如赋值0
int arr[10] {1,2,3,4,5} // 推荐写法等价于以下写法
int arr[10] {1,2,3,4,5,0,0,0,0,0}
// 2. 如果定义数组时未指定数据容量根据初始化元素个数来决定容量
int arr[] {1,2,3,4,5} // 推荐写法等价于以下写法
int arr[5] {1,2,3,4,5}
衍生概念 柔性数组柔性数组的概念是在C99标准针对结构体的最后一个成员可以是一个未指定大小的数组
广义简单理解数组容量待定或者待确定的数组举例 int arr[] {1,2,3,4,5}
面试题 在不知道数组类型的情况下如何确定数组元素的个数
int length sizeof(arr) / sizeof(arr[0])
说明
1. arr就是我们计算的数组本身sizeof(arr)用来计算该数组中总的字节大小。
2. sizeof(arr[0])用来计算数组中一个元素所占的字节大小因为数组中的元素类型相同所以计算哪一个都行。
3. sizeof(arr)/sizeof(arr[0])就是用数组中总的字节数除以每一个元素所占的字节数从而得到元素的个数。 一维数组案例
案例1
/*
需求一维数组案例-非波拉契数列
*/
#include stdio.h
int main()
{int i;// 循环变量int f[20] {1,1}; // 定义一个数组用来存储数列默认存储第1位和第2位int length sizeof(f)/sizeof(f[0]);// 计算数组的元素个数// 生出数列存入数组for(i 2;i length;i){// 给数组元素赋值从数组的第3个元素开始f[i] f[i - 2] f[i - 1];}// 遍历数组// 通过循环将数组中的每一个元素取出来称之为遍历for(i 0;i length;i){// 遍历的时候要求一行显示5个数if(i % 5 0){printf(\n);}printf(%6d,f[i]);}printf(\n);return 0;
}
数组的典型应用数据排序
冒泡排序 向后冒泡 思想 一次只排好一个数针对n个数最差情况需要 n-1次就可以排好 每次排序将相邻数据两两比较将较大或较小的数据向后交换等所有数据都比较完成将较大/较小的数就会出现在最后这也是该数应该有的位置。 在余下的数中再次应用第2步的操作直到只剩下一个数。 向前冒泡 思想 一次只排好一个数针对n个数最差情况需要n-1次就可以排好 每次排序假定第一个元素是最大/最小的用第一个元素的后面的元素一一与第一个元素比较遇到较大/较小的和第一个元素交换访问完数组的最后一个元素就排好了一个数 在余下的数中再次应用第2步的操作直到只剩下一个数。
一维数组案例
案例2
/*
需求一维数组案例-冒泡排序
*/
#include stdio.h
int main()
{// 创建一个数组用来存储排序的数列int arr[11];int i,j,temp;// i:比较的轮数j:每一轮比较的次数temp:临时变量用来比较时交换数据printf(请输入11个测试整数\n);// 计算数组的大小int length sizeof(arr) / sizeof(int); // 这里 sizeof(int) 等价于 sizeof(arr[0]);// 通过循环录入数据for(i 0;i length; i){scanf(%d,arr[i]);}printf(\n);// 对数组arr使用冒泡进行排序注意我们使用标准冒泡大家也可以自行补充优化版的冒泡如鸡尾酒排序法等等// 外层循环控制比较的轮数因为有11个数所以我们需要比较 length -1 轮也就是比较10轮for(i 0;i length -1;i){// 内层循环每一轮比较的次数每一轮比较的次数为 length - 1 - i 3-1-02,3-1-11,3-1-20for(j 0;j length-1-i;j){// 相邻的两个数进行比较满足条件交换位置if(arr[j] arr[j1]){temp arr[j];arr[j] arr[j1];arr[j1] temp;}}}printf(冒泡排序后遍历数组\n);for(i 0; i length; i){printf(%4d,arr[i]);}printf(\n);return 0;
}
案例3
/*
需求一维数组案例-从键盘输入年、月、日计算并输出该日是该年的第几天。
*/
#include stdio.h
int main()
{// 定义变量年月日,统计总天数循环变量用来遍历当前月前面的月份int year,month,day,sum,k;// 定义一个数组用来存放112月每月的天数int t[] {31,0,31,30,31,30,31,31,30,31,30,31};// 柔性数组printf(请输入年份、月份、天\n);scanf(%d,%d,%d,year,month,day);// 因为二月比较特殊存在平年和润年这样的因素所以需要进行平年和润年的判断if((year % 4 0 year % 100 ! 0) || year % 400 0){t[1] 29; // 润年 2月 29天}else{t[1] 28; // 平年 2月 28天}sum day; // 默认记录最后一个月的天数// 这是该年的第几天for(k 0; k month -1;k){sum t[k]; // 叠加前几个月的天数}printf(%d月%d日是%d年的第%d天。\n,month,day,year,sum);return 0;
}
二维数组
定义 二维数组本质上是一个行列式的组合也就是说二维数组是有行和列两部分构成。二维数组数据是通过行列进行解读。 二维数组可被视为一个特殊的一维数组相当于二维数组又是一个一维数组只不过它的元素是一维数组。
语法
类型 数组名[行数][列数]
举例
int arr[3][3] {{1,2,3},{4,5,6},{7,8,9}}; // 等价于以下写法
int arr[][3] {{1,2,3},{4,5,6},{7,8,9}}; // 柔性数组
int arr[3][] {{1,2},{4,5,6},{7}} // 等价于 {{1,2,0},{4,5,6},{7,0,0}}
应用场合
主要应用于数据有行列要求的情况。
特殊写法
下标可以是整型表达式如 a[2-1] [2*2-1]
下标可以是已经有值的变量或数组元素, 如 a[2*x-1] [b[3] [1]]
数组元素可以出现在表达式中 如 b[1] [2]a[2] [3]/2
初始化 分行给二维数组赋初值
int a[3][4] {{1,2,3,4},{5,6,7,8},{9,10,11,12}}; 可将所有数据写在一个花括号内按照排列顺序对元素赋值。
int a[3][4] {1,2,3,4,5,6,7,8,9,10,11,12}; // 等价于上面的写法 可对部分元素赋初值其余未赋值部分自动填充 0 | \0 | 0.0...
int a[3][4] {{1},{5,6},{9}}; // 等价于 int a[3][4] {{1,0,0,0},{5,6,0,0},{9,0,0,0}} 若对全部元素赋初值自定义数组时可以省略第1为数组的长度第2维数组的长度必须指明。
int a[][4] {1,2,3,4,5,6,7,8,9,10,11,12}; 在分行赋初值是也可以省略第1维的长度。
int a[][4] {{1,2,3},{0},{0,10}}; // 等价于 int a[][4] {{1,2,3,0},{0,0,0,0},{0,10,0,0}}
案例
案例1
/**
* 案例二维数组的遍历
*/
#include stdio.h
int main()
{int arr[][3] {{1},{2,4},{5,6,7}};// 经过论证二维数组我们必须指明第2维的数组的长度// 获取行元素的大小int length sizeof(arr) / sizeof(arr[0]); // 如果是二维数组第1维的长度应该是如左侧这样获取printf(length:%d\n,length);// 遍历二维数组需要使用双层for循环外层遍历行内层遍历每一行的列for(int row 0;row length;row){// 获取列元素的总大小int len sizeof(arr[row]) / sizeof(int);for(int col 0; col len; col){// 获取列元素printf(%3d,arr[row][col]);// 意思是获取数组arr 第row行第col列}printf(\n);}return 0;
}
// 数据类型分支结构循环结构数组
案例2
/**
* 需求二维数组案例-矩阵的转置就是将一个2行3列的数组转换为3行2列的数组
*/
#include stdio.h
int main()
{// 准备2个数组存放转前和转后的数据int arr_before[2][3] {1,2,3,4,5,6};int arr_after[3][2] {0};// 初始化每一列上都是0// 遍历arr_beforefor(int i 0;i sizeof(arr_before)/sizeof(arr_before[0]);i){for(int j 0;j sizeof(arr_before[i])/sizeof(int);j){// 转置arr_after[j][i] arr_before[i][j];}}// 遍历arr_afterfor(int i 0;i sizeof(arr_after)/sizeof(arr_after[0]);i){for(int j 0;j sizeof(arr_after[i])/sizeof(int);j){// 输出printf(%4d,arr_after[i][j]);}printf(\n);}return 0;
}
案例3
/**
* 需求二维数组案例-准备一个int类型的二维数组求该数组中大的最大值以及对应的行号列号
*/
#include stdio.h
int main()
{// 准备一个二维数组int arr[3][4] {{1,2,3,4},{9,8,7,6},{-10,10,-5,2}};// 创建变量用保存最大值、行号、列号int max arr[0][0],row0,col0;// 遍历集合for(int i 0;i sizeof(arr) / sizeof(arr[0]);i){for(int j 0;j sizeof(arr[i]) / sizeof(arr[i][0]);j){// 判断最大值if(arr[i][j] max){max arr[i][j];row i;col j;}}}printf(max%d,row%d,col%d\n,max,row,col);return 0;
}
字符数组
概念 元素类型为char字符型的数组字符数组往往是用来存储字符串数据的。需要注意的一点是我们C语言中的字符是字节字符。 字节字符也就是一个字符占1个字节
测试题
char a A // 正确
char b 1 // 正确
char c 65 // 正确 这是ASCII码编号对应的值是 A
char d A // 错误这是字符串的写法也是char数组的写法char d[1] A
char e 马 // 错误中文一个字符超过1一个字节
语法
char 数组名[容量];
char 数组名[行容量][列容量];
字符数组的语法就是之前所学一维数组和二维数组的语法只不过数据类型是char而已。
注意: 如果我们的char数组初始化的时候没有完全赋完值的时候空出来的地方使用 \0 进行填充。
字符案例
案例1
/**
* 需求字符数组案例-输出一个字符串I LOVE YOU!
*/
#include stdio.h
int main()
{// 准备一个测试字符串 I LOVE YOUchar arr[11] {I, ,L,O,V,E, ,Y,O,U,!};// 通过一个for循环进行遍历输出for(int i 0;i sizeof(arr)/sizeof(char);i){printf(%c,arr[i]);}printf(\n);return 0;
}
案例2
/**
* 需求字符数组案例-输出一个用字符组成的菱形图案
*/
#include stdio.h
int main()
{// 准备数据char arr[5][5] {{ , ,*, , },{ ,*, ,*, },{*, , , ,*},{,*, ,*, },{ , ,*, , }};// 遍历数组for(int i 0;i sizeof(arr)/sizeof(arr[0]);i){for(int j 0;j sizeof(arr[i])/sizeof(char);j){// 打印菱形printf(%c,arr[i][j]);}// 内层循环每结束一轮就是一行printf(\n);}printf(\n);return 0;
}
字符串和字符串结束标志
说明 字符数组的多样表示 我们的char数组可以以数组的方式一个个输出每个字符我们的char数组也可以以字符串的方式整体
进行输出所有字符。具体如下面案例
/*
需求字符数组-字符串
*/
#include stdio.h
int main()
{// 字符串第1种表示char s1[] {h,e,l,l,o, ,w,o,r,l,d};// 字符串第2种表示char s2[] {hello world};// 字符串第3种表示char s3[] hello world;// 测试使用字符串方式打印这样就不用一一遍历printf(%s\n,s1);printf(%s\n,s2);printf(%s\n,s3);return 0;
}
注意 字符串的长度与字符数组的长度不一定相同。 利用字符串常量可以对字符数组进行初始化但不能用字符串常量为字符数组赋值。
// 正确写法利用字符串常量给字符数组初始化
char b[15] China;
// 错误写法利用字符串常量给字符数组赋值
char b[15];
b[15] China;
字符串的基础操作
字符串输入
案例
/*
* 需求字符数组-字符串的输入输出
*/
#include stdio.h
int main()
{// 创建一个变量用来存放人的名字char name[20];printf(请输入您的姓名\n);scanf(%s,name);// 如果是字符串这里不是变量地址是变量名printf(您的姓名是%s\n,name);return 0;
}
注意采用scanf进行字符串输入要求字符串中不能存在空格否则字符串遇到空格会结束。 fgets(数组名,数组容量stdin);
说明采用fgets进行字符串输入可获取所有输入的字符串包含 \n 在实际的字符串处理时我们
可能需要处理 \n
案例
/*
* 需求字符数组-字符串的输入输出
*/
#include stdio.h
int main()
{// 创建一个变量用来存放人的名字char name[20];printf(请输入您的姓名\n);fgets(name,sizeof(name)/sizeof(char),stdin);// 输入返回地址puts(name);// 输出return 0;
}
注意 如果输入的字符串不包含 空格 和 换行 可以使用scanf() | fgets(); 如果输入的字符串需要包含 空格 和 换行 只能使用fgets(); 经过对比我们发现在字符串的输入中fgets()更好
字符串输出
puts(数组名)
案例
/*
* 需求字符数组-字符串的输入输出
*/
#include stdio.h
int main()
{// 创建一个变量用来存放人的名字char name[20];printf(请输入您的姓名\n);scanf(%s,name);puts(name);// 输出 问题字符串如何拼接printf(您的姓名是%s\n,name);return 0;
} printf(%s,数组名);
案例
/*
* 需求字符数组-字符串的输入输出
*/
#include stdio.h
int main()
{// 创建一个变量用来存放人的名字char name[20];printf(请输入您的姓名\n);scanf(%s,name);printf(您的姓名是%s\n,name);return 0;
}
字符串拼接 strcat(数组名,需要拼接的字符串) 注意需要引入 #include string.h
案例
/*
* 需求字符数组-字符串的输入输出
*/
#include stdio.h
#include string.h
int main()
{// 创建一个变量用来存放人的名字char name[20];printf(请输入您的姓名\n);fgets(name,sizeof(name)/sizeof(char),stdin);// 输入返回地址puts(strcat(name, 跑着));// 拼接return 0;
}
字符串拷贝 strcpy(数组名,字符串) 注意需要引入 string.h库 说明这个方法适合给字符串赋值用。
char str[16] 马杰克 // 初始化正确
char str[16]; str[16] 马杰克 // 赋值错误
char str[16]; strcpy(str,马杰克) // 赋值正确结果马杰克
案例
/*
* 需求字符数组-字符串的输入输出
*/
#include stdio.h
#include string.h
int main()
{// 创建一个变量用来存放人的名字char name[20];printf(请输入您的姓名\n);scanf(%s,name);strcpy(name,你好);printf(%s\n,name);// 输出return 0;
}
字符串比较 strcmp(字符串1,字符串2); 注意 需要引入 string.h 返回的结果是boolean
案例
/*
* 需求字符数组-字符串的输入输出
*/
#include stdio.h
#include string.h
int main()
{// 创建一个变量用来存放人的名字char username[20];printf(请输入您的账户\n);scanf(%s,username);if(strcmp(username,admin)){printf(账户输入错误\n);}else{printf(账户输入正确\n);}return 0;
}
获取字符串长度 strlen(字符串)
注意 需要 string.h 返回字符串长度
案例
/*
* 需求字符数组-字符串的输入输出
*/
#include stdio.h
#include string.h
int main()
{// 创建一个变量用来存放人的名字char username[20];printf(请输入您的账户\n);scanf(%s,username);// 获取字符串长度unsigned long len strlen(username);if(strcmp(username,admin)){printf(账户输入错误%lu\n,len);}else{printf(账户输入正确%lu\n,len);}return 0;
}