一、对齐的方式:
单行对齐:
命令模式下
按两下 =
多行对齐:
shift+v 选中
按一下 =
起始行 = 结束行
全局对齐:
起始行 = 结束行
gg G(shift + g)
二、一维整形数组
1、格式
类型说明符 数组名[常量表达式];
(1).类型说明符
整型
int,short,long ,long long
浮点
字符 //基本数据类型
(2).数组名
代表着 数据集合 (内存空间的一个名字)
数据类型角度
1. a代表整个数组类型
2. a代表一个值 --数组首元素的地址
(3).[]
表示此时定义的是一个 数组
(4).常量表达式
表示数组的长度 --- 变量的个数
数组长度 与 下标
数组长度 --表示几个元素(变量)
下标 --偏移量
[0~数组长度-1]
int a[10];
[0~9]
eg:
int array[5]; //定义一个数组,这个数组放了5个 int型变量
int array[40];
2、数组本身也是一种数据类型(数组的定义)
数据类型 变量名;
int a = 10; //a int型
int a[10]; //a所代表的类型是 int[10]
int[10] a; //a所代表的类型 int[10]
//a数组名 标识符
//a ---把名字去掉 ,剩下的就是名字对应的数据类型
3、数组在内存空间上的特点
a.连续性 --一片连续空间
b.有序性 --元素依次存储
c.单一性 --单一类型的元素
4、数组的初始化
int a[10] = {1,2,3,4,5,6,7,8,9,10}; //全部初始化
int a[10] = {1,2,3,4,5}; //部分初始化--依次给到数组元素 ,没有给值的元素,默认初始化为0
将数组初始化为0
int a[10] = {}; //都初始化为0
int a[10] = {0}; //都初始化为0
数组不初始化 --- 数组中为垃圾值
5、数组的赋值
注意:
a.数组赋值不能整体赋值
b.数组赋值,需要一个元素一个元素个给到
6、变长数组
int n = 10;
scanf("%d",&n);
int a[n];
注意:
1、变长数组不能赋值
2、没赋值时,数据内部存储的是垃圾值
3、完全未初始化的普通数组a[10],此时数组中存储的值为垃圾值
4、
int a[10] = {1,2,3};
这种普通数组不完全赋值,其他位置存储的值默认为是0
a. 变长数组为初始化打印出此时数组存储的值
int n = 0,i = 0;
scanf("%d",&n);
int a[n];
for(i = 0;i < n;i++)
{
printf("%d ",a[i]);
}
return 0;
}
b. 完全未初始化的数组直接打印出数组中的结果 --> 随机值
int a[3];
int i = 0;
for(i = 0;i < 3;i++)
{
printf("%d ",a[i]);
}
return 0;
}
7、数组的越界问题(eg:a[-5])
1.不是语法问题 --- 编译器不报错,越界位置打印出来随机值
2.程序员 自己小心
三、一维字符型数组
1、字符数组的形式:
"english" //字符串 常量
//本质存储时候,是按照 字符数组的形式存储,只不过是后边多存储一个字符串结束标志'\0'
eg:
unsigned char s[10] = {'h','e','l','l','o'};//数组考虑
"hello" --> unsigned char s[10] = {'h','e','l','l','o','\0'};
unsigned char s[10] = "hello"; //占用了6个字节的内存
unsigned char s[10] = {'h','e','l','l','o','\0'}; //占用了6个字节的内存
unsigned char s[10] = {'h','e','l','l','o'}; //占用了5个字节的内存
unsigned char s[] = {'h','e','l','l','o','\0'}; //[]中可以不放数字
unsigned char s[] = {'h','e','l','l','o'};
2、字符数组的作用:
处理字符串数据
3、注意:
1.字符串 -- 更关注的是字符串整体,而不是单个字符
2.字符串的结束标志 比较重要 ,表示字符串结束
3.处理字符串时,常常使用结束标志作为判断
4、puts函数:
int puts(const char *s);
功能:
输出字符串
参数:
@s 字符串所在空间的首地址
返回值:
int 成功 >0
失败 -1
特点:
输出时,自动换行
练习:
定义一个字符数组
从键盘输入一个字符串到字符数组中
要求:
一个字符一个字符输入 ,使用scanf("%c", );
char s1[10];
int i = 0;
while ((s1[i] = getchar())!='\n')
{
i++;
}
s1[i] = '\0';
puts(s1);
5、gets()函数:
char *gets(char *s);
功能:
输入字符串
参数:
@s 存放字符串一块内存空间
返回值:
表示的是 存储字符串那块空间首地
练习1:
统计字符串的长度
用gets()获取字符串:
char s[] = {1,2,3}; //这里是代表给数组s中放入1 2 3三个数值,且开辟了3个字节的空间
int i = 0;
gets(s);//即使这里输入5个字符,也并不能认为是给s中开辟5个字节的空间,因为前边空间已经开辟好了
while(s[i] != '\0')
{
i++;
}
printf("strlen = %d\n",i);
gets函数和scanf函数的区别
gets (); //可以输入带空格的字符串
scanf(); //不能输入带空格的字符串,因为空格作为scanf的一种分割符,scanf识别到空格人数输入结束
scanf函数给arr数组中输入字符串:
键盘上输入 hello world,计算机输出 hello
gets函数给arr数组中输入字符串:
键盘上输入 hello world,计算机输出 hello world
6、strcpy函数:
char *strcpy(char *dest, const char *src);
功能:
实现字符串拷贝
参数:
@dest 目标字符串
@src 源字符串
返回值:
成功 返回的是 dest地址
失败 NULL
练习:
实现strcpy函数功能
char s1[6] = "hello";
char s2[6];
int i = 0;
for(i = 0;i < 6;i++)
{
s2[i] = s1[i];
}
puts(s2);
7、strlen函数
功能:
计算字符串长度(不包括’\0‘)
练习:
实现strlen函数功能:
char s[] = {1,2,3}; //这里是代表给数组s中放入1 2 3三个数值,且开辟了3个字节的空间
int i = 0;
gets(s);//即使这里输入5个字符,也并不能认为是给s中开辟5个字节的空间,因为前边空间已经开辟好了
while(s[i] != '\0')
{
i++;
}
printf("strlen = %d\n",i);
8、strcmp函数
格式:
int strcmp(const char *s1, const char *s2);
功能:
比较两个字符串
参数:
s1 //字符数组名
s2
返回值:
>0 s1 > s2
==0 s1 == s2
<0 s1 < s2
返回值,实际上是,结束位置上字符的差值
char s1[10] = "hello";
char s2[10] = "hellp";
printf("strcmp(s1,s2) = %d\n",strcmp(s1,s2)); //输出结果为-1
char s1[10] = "hello";
char s2[10] = "hell";
printf("strcmp(s1,s2) = %d\n",strcmp(s1,s2)); //输出结果为111('o'的ascii-'\0'的ascii)
字符串比较的规则
对两个字符串自左至右逐个字符相比(按ASCII 码值大小比较),直到出现不同的字符或遇到'\0' 为止。如全部字符相同,则认为相等;若出现不相同的字符,则以第一个不相同的字符的比较结果为准。
练习:
实现strcmp函数功能
char s1[10] = "hello";
char s2[10] = "hello";
int i = 0;
while(s1[i] != '\0' && s2[i] != '\0' && s1[i] == s2[i] )
{
i++;
}
if(s1[i] > s2[i])
printf("s1较大\n");
else if(s1[i] < s2[i])
printf("s2较大\n");
else
printf("s1 = s2\n");
9、strcat函数
char *strcat(char *dest, const char *src);
功能:
字符串拼接
参数:
@dest 目标字符串
@src 源字符串
返回值:
成功 返回的是dest
失败 NULL
练习 :
实现strcat函数功能
char s1[20]= "hello";
char s2[20]= "world"; //这里[]里边可以不写数字,让系统自己匹配数值 (这样的说法是错误的)
int i = 0,j = 0;
while(s1[i] != '\0') //找到s1数组中'\0'的位置
{
i++;
}
while(s2[j] != '\0') //拼接
{
s1[i] = s2[j];
j++;
i++;
}
s2[j] = '\0';
puts(s1);
四、二维整形数组
1、二维数组定义的一般形式为
类型说明符 数组名[常量表达式][常量表达式];
eg:int a[3][4]; //三行,四列
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}; //部分初始化
int a[3][4] = {{1,2,3,4},{5,6,7,8}}; //按行初始化
3、c语言中二维数组的本质
a. C语言中,不存在真正的二维数组,只有一维数组
b. 二维数组本质,是一维数组的一维数组
4、难点:数组类型
类型说明符 数组名[常量表达式];
int a[4]; //一维数组
//a的数据类型 int[4]
int[4] a[3]; //一维数组
//一维数组的元素类型 --> 又一个数组类型
int a[3][4]; //二维数组
//a的数据类型 int[3][4]
5、注意
int[] a[3]; //error,一维数组的类型不明确了
int[4] a[]; //true
int a[3][4]; //二维数组语法角度 ---行数可以省略 列数不能省略
6、拓展其他维数
int a[3][4]; // 3行 4列
int a[3][4][5];
int a[3][4][5][6];
.....
int[3][4] a[5];
int a[3][4][5];
7、练习
练习1:
int a[3][4];
从键盘输入值
要求求出,二维数组边上和
//四个边上的数值之和
int s1[3][4];
int i = 0,j = 0,ret = 0;
for(i = 0;i < 3;i++) //给数字中的每个元素赋值
{
for(j = 0;j < 4;j++)
{
scanf("%d",&s1[i][j]);
}
}
for(i = 0;i < 3;i++) //找四个边上的数值
{
for(j = 0;j < 4;j++)
{
if(i != 1 || j != 1 && j != 2) //法一
ret = ret + s1[i][j]; //求和
/*
if(i == 0 || i == 2 || j == 0 || j == 3) //法二
ret = ret + s1[i][j]; //求和
*/
}
}
printf("%d",ret);
练习2:
实现矩阵的转置
eg:
1 2 3
4 5 6
7 8 9
1 4 7
2 5 8
3 6 9
//转置矩阵
//思路:找出下表中行标大于列表的数值,之后进行下标互换以实现数值互换
int s[4][4] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
int i,j,t;
for(i = 0;i < 4;i++)
{
for(j = 0;j < 4;j++)
{ if(i > j) //找出下表中行标大于列表的数值
{
t = s[i][j]; //下三行代码实现下标互换
s[i][j] = s[j][i];
s[j][i] = t;
}
}
}
for(i = 0;i < 4;i++) //打印转置之后的矩阵
{
for(j = 0;j < 4;j++)
{
printf("%d ",s[i][j]);
}
printf("\n");
}
五、二维字符型数组
char s[10] = "hello"; //一维
char s[3][10] = {"aaa","bbb","ccc"}; //二维
char s[3][10] = {{a,a,a,\0},{b,b,b,\0},{c,c,c,\0}}; //二维
练习:
输入三个字符串
找出最大字符串
strcmp(s[0],s[1])
strcpy(s[0],s[1])
//字符串比较(strcmp)函数的使用
//练习:找出三个字符串中的最大的字符串
char ch1[3][10] = {"ccc","bbb","aaaa"};
int i,t1,t2;
t1 = strcmp(ch1[0],ch1[1]);
if(t1 > 0)
{
t2 = strcmp(ch1[0],ch1[2]);
if(t2 > 0)
printf("0\n");
else
printf("2\n");
}
if(t1 < 0)
{
t2 = strcmp(ch1[1],ch1[2]);
if(t2 > 0)
printf("1\n");
else
printf("2\n");
}
练习:
输入3个字符串
分别使用选择排序、冒泡排序、插入排序的方法对根据字符串的大小进行排序
排序结束后,使用二分查找的方法找出自己想查找的字符串,打印字符串所在位置的下标
//字符串选择排序 + 二分查找
char s1[3][10] = {"aaa","bbb","ccc"};
int i = 0,j = 0;
char s2[10],s3[10];
int begin,end,mid;
for(i = 0;i < 2;i++)
{
for(j = 0;j < 3 - i;j++)
{
if((strcmp(s1[i],s1[i+j])) > 0)
{
strcpy(s2,s1[i]);
strcpy(s1[i],s1[i+j]);
strcpy(s1[i+j],s2);
}
}
}
strcpy(s3,s1[2]);
begin = 0;
end = 2;
while(begin <= end)
{
mid = end + begin;
if(strcmp(s1[mid],s3) == 0)
{
break;
}
else if(strcmp(s1[mid],s3))
{
end = mid - 1;
}
else
{
begin = mid + 1;
}
}
if(begin <= end)
printf("找到了,下标是%d\n",mid);
else
printf("没找到\n");
//字符串冒泡排序 + 二分查找
char s1[6][10] = {"aaa","bbb","ccc","ddd","eee","fff"};
int i = 0,j = 0;
char s2[10],s3[10];
int begin,end,mid;
for(i = 0;i < 5;i++)
{
for(j = 0;j < 5 - 1 - i;j++)
{
if((strcmp(s1[i],s1[i+1])) > 0)
{
strcpy(s2,s1[i]);
strcpy(s1[i],s1[i+1]);
strcpy(s1[i+1],s2);
}
}
}
strcpy(s3,s1[5]);
begin = 0;
end = 5;
while(begin <= end)
{
mid = end + begin;
if(strcmp(s1[mid],s3) == 0)
{
break;
}
else if(strcmp(s1[mid],s3))
{
end = mid - 1;
}
else=
{
begin = mid + 1;
}
}
if(begin <= end)
printf("找到了,下标是%d\n",mid);
else
printf("没找到\n");
//插入排序法对字符串进行排序,后使用二分查找找出自己想要的字符串
char ch1[6][10] = {"ccc","bbb","aaa","ddd","eee","fff"};
int i = 0,j = 0,r = 0;
char s1[10];
char s2[10] = "aaa";
int begin = 0,mid = 0,end = 5;
for(i = 0;i < 3;i++)
{
strcpy(s1,ch1[i]);
j = i;
while(j > 0 && (r = strcmp(ch1[j-1],s1)) > 0)
{
strcpy(ch1[j], ch1[j - 1]);
j--;
}
strcpy(ch1[j],s1);
}
while(begin <= end)
{
mid = begin + end;
if(strcmp(ch1[mid],s2) > 0)
{
end = mid - 1;
}
else if(strcmp(ch1[mid],s2) < 0)
{
begin = mid + 1;
}
else
break;
}
if(begin <= end)
{
printf("找到了,下标是%d\n",mid);
}
else
printf("没找到\n");
六、总结:
1.数组概念
2.数组定义
一维整型
一维字符型
二维整型数组
二维字符型数组
3.重点
a.二维数组本质
b.二维整型数组操作 ---访问具体的元素 a[i][j]
c.二维字符型数组
放多个字符串
char s[3][10];
5.掌握
a.排序算法
选择
冒泡
插入
查找
b.字符串
strlen
strcpy
strcat
strcmp