数组
一、一维数组
1、作用
需要保存大量的类型相同的数据
例:保存全班同学的成绩
2、定义数组
类型名 数组名[数组元素个数];
任何合法的C语言类型,都可以定义成数组
char buf[10];//最多可以存放10个字符
int buf1[10];//最多可以存放10个整型数
float buf2[10];//最多可以存在10个浮点型数
3、数组的初始化及赋值
写法一:int a[5]={1,2,3,4,5};//列表初始化
char b[10] = "hello"
写法二:int a[5] = {45,25};//部分初始化,其它没有初始化的都为0
char b[10] = {'h','e','l','l','o'};
写法三:int a[ ] = {85,96}; //[ ]里不写元素个数,只有在定义的时候立马进行初始化才可以
char b[ ] = "world";
写法四:int a[ ] ;
a[0] = 78;//错误写法
写法五:int a[3];//定义了数组,但没进行初始化
a[3] = 88;//数组越界了,这里数组a的下标为0、1、2
写法六:把数组前面50个元素初始化为100,后面50个初始化为200
int b[100] = {[0 ... 49] = 100, [50 ... 99] = 200};
注意:...的左右两边必须要有空格
4、元素数组的下标
从0开始,使用的时候不要越界
数组越界的危害(容易出现段错误)
int a[10];//下标范围0~9
第一种:往前越界
a[-2];//访问a[0]前面8个字节的地址里面的数据
第二种:往后越界
a[11];//访问a[9]后面8个字节的地址里面的数据
段错误:segment fault
由于程序员在代码中访问了非法地址导致的(经常见于指针没有初始化,数组越界)
5、数组的存储
数组在计算机中是连续存储(数组元素的地址是紧挨着的)
6、数组的大小
/*
sizeof();//求任何类型数据的大小
strlen();//专门用来求字符串的实际长度
*/
#include <string.h> //使用到的头文件
size_t strlen(const char *s);
返回值:字符串的实际长度
参数:s --》你要计算长度的字符串
原理:计算字符串实际长度,遇到/0认为字符串结束了
总结:
第一:sizeof是运算符,strlen是个函数
第二:sizeof适用范围广 strlen只能求字符串的长度
第三:sizeof求字符串的长度会把\0算上
strlen求字符串的长度不计算\0.
字符串在计算机中的存储方式
字符串默认有一个结束标记\0(ASCII值就是0)
char buf[10] = "hello";//编译器会自动给字符串的末尾添加\0,无需程序员担心
char buf1[5]="hello"; //本来编译器想自动添加\0,可惜你不给它机会
要注意的特例(没有道理可讲,记住就行)
char buf[]={'h','e','l','l','o'}; sizeof求出是5,没有加\0
char buf[]="hello" sizeof求出是6(加上了\0)
7、空字符串,'A'和"A"的区别
char buf[10] = " ";//空字符串
'A'; //字符A 单个字符
"A"; //字符串A A和\0
8、char类型数组重复使用,清空数组
1)char类型数组重复使用
char buf[10];
while(1)
{
scanf("%s",buf); /*假如第一次输入的字符串长一点,下一次输入的字符串短一点,scanf都会自动帮
你在字符串后面添加\0保存到数组中,短一点的字符串重复长字符串的前面部分,
并且有个\0在后面(容易忽略)*/
}
2)清空数组
数组先清空后使用(数组不清空里面存的是随机数)
//写法一:
#include<strings.h>//包含的头文件
void bzero(void *s,size_t n);//把数组全部填充为0
参数:s --》数组名
n --》数组大小
//例:
int buf[10];
bzero(buf,10);
//写法二:
int buf[10] = {0};//部分初始化原理,其他没有初始化的默认都是0,把数组清零
char buf[5] = {0};//部分初始化原理,其他没有初始化的默认都是0,把数组清零
9、数组怪异的写法(了解即可)
int buf[10];
buf[0] =11;//等价于0[buf] = 11;
二、二维数组
1、作用
int a[5][6]; //行列存放整数,有5行,每一行最多可以存放6个整数,总共可以存放30个整数。
char b[5][10]; //可以存放5个字符串,每个字符串的最大长度不能超过10个字节,用来保存多 个字符串
2、定义二维数组
类型名 数组名[行数][列数];
任何合法的C语言类型,都可以定义成二维数组
char buf[10][20]; //最多存放10个字符串,每个字符串的长度不能超过20个字符
"hello" "world"
int buf1[50][50]; //50行整数,每一行最多50个整数
3、二维数组的初始化以及赋值
//写法一:
int a[5][6]={45,78,96}; //部分初始化,正确
char b[3][10]={"hello","world","gec"};
[0][0] [0][1] [0][2] ....[0][5]
[1][0] [1][1] [1][2] ....[1][5]
....
[4][0] [4][1] [4][2] ....[4][5]
//写法二:
int a[][6]={89,9}; //正确
char b[][10]={"hello","world","gec"};
//写法三:
int a[][]={89,9}; //错误
//写法四:
int a[5][]={89,9}; //错误
//写法五:
int a[5][6]={{5},{8,9},{89,63}}; //正确,分组初始化
//分组初始化必须从左到右连续(花括号不要跳跃)
int a[5][6]={{5},8,9,{89,63}}; //错误的写法,不满足从左到右连续(花括号中间跳跃了)
char b[3][10]={{'h','e','l','l','o'},{'g','e','c'}}
//写法六:
int a[5][6]={{5},{8,9},89,63}; //正确
//写法七:
int a[5][6]; //分别赋值
a[0][0]=99;
a[1][2]=67;
char b[3][10];
b[0][1]='h';
4、数组元素的下标
行和列都是从0开始,使用的时候不要越界
5、二维数组的存储
二维数组在计算机中是连续存储(数组元素的地址是紧挨着的)
二维数组:可以看作是特殊的“一维数组”
可以把二维数组拆分成多个一维数组
6、二维数组的大小
情况一:两个下标都有
int a[5][6]; //公式 行*列*sizeof(类型)
情况二:少了行下标
int a[ ][6] = {78,76}; //依据初始化列表中值的个数,确定有几行
7、字符串在一维数组和二位数组中如何存储,如何比较
1)复制、拷贝字符串
#include <string.h>
char *strcpy(char *dest, const char *src);
//参数:把src中的字符串拷贝一份到dest里面
char *strncpy(char *dest, const char *src, size_t n);
//参数:把src中的字符串拷贝一份到dest里面,拷贝n个字节
/* 注意:strcpy拷贝字符串会自动在后面加上\0(特别是src比dest要短的情况下)
strncpy拷贝字符串的时候不会自动添加\0 */
2)字符串的比较
比较标准:按照两个字符串中字符的ASCII码排列顺序来比较
int strcmp(const char *s1, const char *s2);
返回值:s1>s2 返回值>0
s1<s2 返回值<0
s1=s2 返回0
参数s1 s2为要比较的两个字符串
注意:strcmp判断字符串大小,是根据字符串字母的排列先后顺序来判断(不是根据长度)
int strncmp(const char *s1,const char *s2,size_t n);
参数:比较s1和s2前n个字符是否相同
3)字符串合并,拼接
char *strcat(char *dest,const chatr *src);
参数:把src合并到dest中,合并的结果存放在dest.
char *strncat(chat *dest,const char *src,size_t n);
参数:把src最前面n个字节合并到dest中,合并结果存放在dest.
注意 :dest的大小要能够容纳合并后的结果,不要出现越界的情况
4)字符串的切割strtok
底层原理:strtok会改变原始字符串,strtok会把原始字符串中遇到的切割符号替换成\0
#include <string.h>
char *strtok(char *str,const char *delim);
返回值:切割的结果
参数:str 你要切割的字符串
delim 你要切割的标准
5)判断子串strstr
#include <string.h>
char *strstr(const char *haystack, const char *needle);
//返回值:出现过 --》返回needle首次出现的位置
// 没有出现过--》返回NULL
//参数:判断needle在haystack中有没有出现过