c_lesson11
1.数组定义
1.遍历数组
2.char[]作为字符输出和字符串输出,输入的区别
3.数组内存空间:数组的空间是在对应函数的栈帧内部空间开辟的。也就是所谓的栈上开辟空间。
1.1 遍历数组
#if 1
#include <stdio.h>
#include <windows.h>
int main()
{
int arr1[] = {1,2,3};
int arr[10] = {1,2,3};
//求数组元素的个数
int num = sizeof(arr1)/sizeof(arr1[0]);
int i = 0;
for(;i<num;i++){
printf("%d ",arr1[i]);
}
printf("\n");
for(i=0;i<10;i++){
printf("%d ",arr[i]);
}
printf("\n");
system("pause");
return 0;
}
#endif
1.2 char[]:被当做普通的char数组,就跟int[]数组类似,需要遍历数组,下标访问的方式才能获取每一个元素。
#if 1
#include <stdio.h>
#include <windows.h>
int main()
{
char arr[] = {'a','b','c'};
int num = sizeof(arr)/sizeof(arr[0]);
int i = 0;
for(;i<num;i++){
printf("%c = %d ",arr[i],arr[i]);
}
printf("\n");
system("pause");
return 0;
}
#endif
1.3 char[]:被整体当做字符串使用
#if 1
#include <stdio.h>
#include <windows.h>
int main()
{
char arr[] = {'a','b','c','\0'};//如果有\0,就当做字符串处理。
char arr1[] = "asdfg";
//打印方式:1.直接%s输出;2.遍历打印
printf("%s\n",arr);
printf("%s\n",arr1);
/*int num = sizeof(arr)/sizeof(arr[0]);
int i = 0;
for(;i<num;i++){
printf("%c ",arr[i]);
}
printf("\n");*/
system("pause");
return 0;
}
#endif
1.4 char[]:输入的区别
#if 1
#include <stdio.h>
#include <windows.h>
int main()
{
char arr[] = {'a','b','c','\0'};//如果有\0,就当做字符串处理。
char arr1[] = "asdfg";
//打印方式:1.直接%s输出;2.遍历打印
printf("%s\n",arr);
printf("%s\n",arr1);
/*int num = sizeof(arr)/sizeof(arr[0]);
int i = 0;
for(;i<num;i++){
printf("%c ",arr[i]);
}
printf("\n");*/
system("pause");
return 0;
}
#endif
2.一维数组
1.操作符: [] ,下标引用操作符,数组访问的操作符.
2.初始化一维数组,计算一维数组的元素个数,遍历输入和打印一维数组。
int size = sizeof(arr)/sizeof(arr[0])
3.数组下表元素对应的空间、内容的理解--数组任意一个元素满足左值和右值问题
4.一维数组在内存中的存储
(1)输出的是最小的地址
(2)遍历数组元素时,打印的都是数组元素第一个字节的地址,物理空间是连续的。
(3)数组名+1,就是下一个元素的第一个字节的地址。
eg:int arr[10];arr是数组首元素的地址,arr+1就是第二个数组元素的第一个字节的地址。
(4)数组只能整体初始化,不能整体赋值
(5)数组是整体空间分布的,局部地址是依次增大的,但是把数组不要看成一个个独立个体去开辟空间,数组是整体开辟空间,
所以在栈上把空间一次性开辟了。然后把最低地址作为零号下标a[0].
(6)定义一个全局变量数组,其不是在栈上开辟空间,而是在已初始化全局变量区。
(7)不管是栈上还是已初始化全局变量区,数组开辟空间都是整体开辟空间,局部地址是依次增大的。
总结:
1.一维数组:a[0]...a[9]
地址依次增大,a[0]的地址最小;
一个变量中,第一个字节的地址,代表该变量的地址;
2.地址是跨字节连续的;int--》4;char---》1;double---》8
3.对地址加1,其实就是加所选类型的大小;int arr[10];arr+1;
4.数组只能对整体初始化,不能对整体赋值;
5.数组整体空间分布,数组局部地址依次增大,栈上地址依次减小。
2.1 初始化一维数组,计算一维数组的元素个数,遍历输入和打印一维数组。
#if 1
#include <stdio.h>
#include <windows.h>
int main()
{
//数组的不完全初始化
int arr[10] = {0};
//计算数组的元素个数
int sz = sizeof(arr)/sizeof(arr[0]);
//对数组内容赋值,数组是使用下标来访问的,下标从0开始。
int i = 0;//做下标
//输入数组的内容
for(i=0; i<sz; i++)
{
arr[i] = i;
}
//输出数组的内容
for(i=0; i<sz; ++i)
{
printf("%d ", arr[i]);
}
system("pause");
return 0;
}
#endif
2.2 数组下表元素对应的空间、内容的理解–数组任意一个元素满足左值和右值问题
#if 1
#include <stdio.h>
#include <windows.h>
int main()
{
//code1:
//int arr[] = {11,22,33,44,55};
//arr[1] = 1;//arr[1]:1号下标元素对应的空间
//int a = arr[2];//arr[2]:2号下标元素对应的内容
//printf("%d %d\n",arr[1],arr[2]);
//code2:
int arr[] = {11,22,33,44,55};
scanf("%d",&arr[2]);//arr[2]的空间
printf("%d",arr[2]);//arr[2]的内容
system("pause");
return 0;
}
#endif
2.3 一维数组在内存中的存储
#if 1
#include <stdio.h>
#include <windows.h>
int arr[10] = {1,2,3,4,5,6,7,8,9,0};
int main()
{
//code1:
/*int a = 0x11223344;
printf("%p ",&a);*/
//code2:地址是跨字节连续的
/*//int arr[10];
//char arr[10];
double arr[10];
int sz = sizeof(arr)/sizeof(arr[0]);
int i = 0;
for(; i<sz; ++i)
{
printf("a[%d]:%p \n", i,&arr[i]);
}*/
//code3:
/*int arr[10];
printf("%p ",arr);//arr[0]
printf("%p ",arr+1);//arr[1];类似于指针,int *p = a; p++;对地址加1,其实就是加所选类型的大小;
printf("%p ",int(arr)+1);//这个是首元素第二个字节的地址*/
//code4:数组只能整体初始化,不能整体赋值
//int arr[10];
//arr+1;//初始化
//arr = arr+1;//报错,赋值a++
//code5:
//int arr[] = {1,2,3,4};
//printf("%p \n",arr);//数组首元素的地址
//printf("%p \n",arr + 1);//数组第二个元素的地址
//printf("%p \n",&arr[1]);//数组第二个元素的地址
//printf("%p \n",int(arr) + 1);//数组第二个字节的地址
//printf("%d \n",*(arr+1));//数组第二个元素的内容
//printf("%d \n",arr[1]);//数组第二个元素的内容
//printf("%d \n",*&arr[1]);//数组第二个元素的内容
//code6:栈上的地址是依次减小的,先进后出
/*int a = 10;
int b = 20;
int c = 30;
printf("%p \n",&a);
printf("%p \n",&b);
printf("%p \n",&c);*/
//code7:数组是整体空间分布的,局部地址是依次增大的,
//但是把数组不要看成一个个独立个体去开辟空间,数组是整体开辟空间,所以在栈上把空间一次性开辟了。
//然后把最低地址作为零号下标a[0].
/*int a = 10;
int b = 20;
int c = 30;
printf("%p \n",&a);
printf("%p \n",&b);
printf("%p \n",&c);
int arr[10];
int sz = sizeof(arr)/sizeof(arr[0]);
int i = 0;
for(; i<10; ++i)
{
printf("a[%d]:%p \n", i,&arr[i]);
}*/
//code8:数组在全局区,地址也是依次增大的。
int i = 0;
for(; i<10; ++i)
{
printf("a[%d]:%p \n", i,&arr[i]);
}
system("pause");
return 0;
}
#endif
code1:
code2:
code3:
code4:
code5:
code6:
code7:
code8:
3.二维数组
1.二维数组的创建、初始化
(1)arr[3][4]--->三个元素的一维数组,一维数组里有4个int类型的整数
(2)二维数组第一个维度可以省略,有几行由花括号决定;但第二个维度不能省略
(3)数组不初始化时为随机值
(4)二维数组依旧只能初始化,不能赋值
2.遍历二维数组:二维数组在内存中也是连续存储的,且递增的。
3.冒泡排序
3.1 二维数组的创建、初始化
#if 1
#include <stdio.h>
#include <windows.h>
int main()
{
//1.二维数组的创建、初始化
//arr[3][4]--->三个元素的一维数组,一维数组里有4个int类型的整数
int arr[3][4]={{1,2},{3,4},{5,6}};
int arr1[][4] = {{1,2},{3,4}};//第一个维度可以省略,有几行由花括号决定;但第二个维度不能省略
int arr2[3][4];//数组不初始化时为随机值
//arr2+1;
//arr2++;//二维数组依旧只能初始化,不能赋值
system("pause");
return 0;
}
#endif
3.2 遍历二维数组:二维数组在内存中也是连续存储的,且递增的。
#if 1
#include <stdio.h>
#include <windows.h>
int main()
{ //code1:遍历输出二维数组
/*int arr[4][5] = {{1,2},{3,4},{5,6},{7,8}};
int i = 0;
for(;i<4;i++){
int j = 0;
for(;j<5;j++){
printf("arr[%d][%d] = %d : %p\n",i,j,arr[i][j],&arr[i][j]);
}
}*/
//code2:遍历输入二维数组并输出
int arr[4][5];
int i = 0;
for(;i<4;i++){
int j = 0;
for(;j<5;j++){
//scanf("%d",&arr[i][j]);
arr[i][j] = i*5+j;
}
}
for(i=0;i<4;i++){
int j = 0;
for(;j<5;j++){
printf("arr[%d][%d] = %d : %p\n",i,j,arr[i][j],&arr[i][j]);
}
}
system("pause");
return 0;
}
#endif
3.3 数组传参
1.数组作为函数参数,发生了降维问题,降维成了数组首元素的地址。
在32平台下是4字节,因此数组传参时,一定要传参数组元素的个数,不能再函数中求。
2.冒泡排序
3.3.1 降维处理
#if 1
#include <stdio.h>
#include <windows.h>
void PrintArr(int *arr,int num)
{
//参数:int *arr,其实是首元素的地址;
//size=1;因为sizeof(arr)是四字节,数组首元素的地址,
//在32平台下是4字节,因此数组传承时,一定要传参数组元素的个数,不能再函数中求。
int size = sizeof(arr)/sizeof(arr[0]);
printf("%d\n",size);
int i = 0;
for(;i<num;i++){
printf("%d ",arr[i]);
}
printf("\n");
}
int main()
{
int arr[] = {9,5,3,8,0,4,6,22,2,6};
int num = sizeof(arr)/sizeof(arr[0]);
PrintArr(arr,num);
system("pause");
return 0;
}
#endif
3.3.2 冒泡排序
原理:
(1)每一趟只能确定将一个数归位。
即第一趟只能确定将末位上的数归位,第二趟只能将倒数第 2 位上的数归位,依次类推下去。
如果有 n 个数进行排序,只需将 n-1 个数归位,也就是要进行 n-1 趟操作。
(2)而 “每一趟 ” 都需要从第一位开始进行相邻的两个数的比较,
将较大的数放后面,比较完毕之后向后挪一位继续比较下面两个相邻的两个数大小关系,
重复此步骤,直到最后一个还没归位的数。
思路:(1)数组传参需要传参数组名和数组元素的个数
(2)i控制趟数,每次将最后一个数归为,需要num-1次;
(3)j控制每趟交换的次数,次数由i控制,num-1-i次
(4)为了将有序数组快速排序,提高排序效率,用flag==1的方式来判断;
如果进行过一轮后,没有比较,flag依旧是1,那么这个数组就是有序的,
直接输出就ok,这样效率会更高。
如果有进行交换,flag=0,则不是有序数组。
#if 1
#include <stdio.h>
#include <windows.h>
void ShowArr(int *arr,int num)
{
int i = 0;
for(;i<num;i++){
printf("%d ",arr[i]);
}
printf("\n");
}
void BubbleSort(int *arr,int num)
{
int i = 0;
//控制躺数
for(;i<num-1;i++){
//控制每趟的次数
int j = 0;
int flag = 1;
for(;j<num-1-i;j++){
//判断相邻两个元素是不的大小,进行排序。
if(arr[j+1]<arr[j]){
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
flag = 0;
}
}
//判断是否有序,如果进行过一轮后,发现flag==1,那么这个数组就是有序的,
//直接输出就ok,这样效率会更高。
if(flag == 1){
break;
}
}
}
int main()
{
int arr[] = {9,5,3,8,0,4,6,22,2,6};
int num = sizeof(arr)/sizeof(arr[0]);
ShowArr(arr,num);
BubbleSort(arr,num);
ShowArr(arr,num);
system("pause");
return 0;
}
#endif
4.数组名
1.数组名是数组首元素的地址。
2.sizeof(数组名),计算整个数组的大小,sizeof内部单独放一个数组名,数组名表示整个数组;
&数组名,取出的是数组的地址。&数组名,数组名表示整个数组。
#if 1
#include <stdio.h>
#include <windows.h>
int main()
{
//code1:
int arr[] = {1,2,3,4,5,6};
printf("%p \n",arr);//首元素的地址
printf("%p \n",&arr[0]);//第一个元素的地址
printf("%d \n",*arr);//数组第一个元素
//code2:
printf("%p \n",arr);//首元素的地址
printf("%p \n",arr+1);//第二个元素的地址
printf("%p \n",arr+2);//第三个元素的地址
printf("%d \n",*(arr+1));//第二个元素
printf("%d \n",arr[1]);//第二个元素
//code3:
printf("%p \n",arr);//首元素的地址
printf("%p \n",&arr);//数组的地址
printf("%p \n",arr+1);//下一个元素的地址
printf("%p \n",&arr+1);//下一个数组的地址
//code4:
int size = sizeof(arr)/sizeof(arr[0]);
printf("%d \n",size);//数组元素的个数
printf("%d \n",sizeof(arr));//整个数组的大小
printf("%d \n",sizeof(arr+1));//第二个元素的大小
//code5:
char arr1[] = "asdfghj";
printf("%d %d\n",strlen(arr1),sizeof(arr1));//strlen字符串内容大小,sizeof字符串包含\0的空间大小
//code6:
int arr2[] = {1,2,3,(0,4),5};//逗号表达式按照最后一个元素输出
int num = sizeof(arr)/sizeof(arr[0]);//元素个数5个
int i = 0;
for(;i<num;i++){
printf("%d ",arr2[i]);
}
printf("\n");
printf("%d \n",num);
system("pause");
return 0;
}
#endif
code1:
code2:
code3:
code4:
code5:
code6: