1.循环输入二维数组,计算所有元素的和
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
int n,m;
printf("需要几行几列:\n");
scanf("%d %d",&n,&m);
int arr[n][m];
int i,j,sum=0;
printf("请输入:\n");
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
scanf("%d",&arr[i][j]);
sum+=arr[i][j];
}
}
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
printf("%d ",arr[i][j]);
}
printf("\n");
}
printf("和为:%d\n",sum);
return 0;
}
结果为:
一、数组
int num;只能存储一个数字,存储多个数据,则引出数组
数组:使用任意一段连续的存储空间,存储类型相同的构造数据类型
构造类型:可以分割【数组、结构体、共用体】
1.1 一维数组
一维数组:只有一个下标表示的数组称为一维数组
1) 一维数组的定义
格式:
存储类型 数据类型 数组名[常量表达式]
解析:
1>存储类型:auto\static\const\extern\register\volatile
2> 数据类型:基本类型{int float double...},构造类型,指针类型、空类型
3> 数组名:满足命名规范
4> []:数组的标志
5> 常量表达式:定义时,不为0,不为空,不为小数,初始化时不为变量
int arr[10];//√ 存储10个整数类型
int arr[0];//×
int arr[];//×
int arr[5.5];//×
int n=10;
int arr[n];//定义 √
int n=10;
int arr[n]={1,2,3,4};//×
#define N 10
int arr[N];
2) 一维数组的初始化
1> 全局数组未初始化,默认结果为0
全局:在主函数外定义数组
2> 局部数组未初始化,默认结果是随机值
局部:在主函数内定义数组,一般使用局部
3> 全部初始化
int arr[5]={11,22,33,44,55};
4> 部分初始化
int arr[5]={11,22};//部分初始化,剩余元素默认以0填充
5> 特殊初始化【常用】
int arr[]={11,22,33,44}; -->int arr[4]={11,22,33,44}
默认数组长度是实际元素的个数
6> 错误初始化
int arr[5]; 错误
arr={11,22,33,44,55};//arr表示数组的首地址,arr本质上是一个指针,不可以赋值
int arr[5];
arr[5]={1,2,3,4,5};//首先arr[5]越界,其次arr[5]表示一个值
7> 一维数组的循环输入和输出
int main(int argc, const char *argv[])
{
int arr[4];
for(int i=0;i<4;i++)
{
scanf("%d",&arr[i]);
}
for(int i=0;i<4;i++)
{
printf("%d ",arr[i]);
}
}
3) 一维数组引用
1> 数组下标从0开始,n个元素,下标范围【0--- n-1】
2> arr[0]: 第一个元素 arr[n-1]:最后一个元素
3> 越界访问:int arr[4]; printf("arr[4]=%d\n",arr[4]);
1.如果越界访问的空间没有被占用,越界访问的结果是垃圾值
2.如果越界访问的空间被占用,但是存储不重要的数据,访问的是垃圾值
3.如果越界访问的空间被占用,但是存储重要的数据,则段错误
段错误:访问了不该访问的内存空间
4)一维数组的地址
数组名表示数组的首地址,也就是第一个元素的地址arr=&arr[0]
数组名是常量不可以进行自增或自减 arr++/arr--/++arr/--arr,错误
1> 数组的地址是连续的
2> 地址加1,表示向后移动一个元素大小字节,打印地址的格式控制符%p
arr=0x10
arr+1=0x14
int main(int argc, const char *argv[])
{
int arr[4]={11,22,33,44};
printf("arr=%p",arr);
printf("&arr[0]=%p\n",&arr[0]);
for(int i=0;i<4;i++)
{
printf("&arr[%d]=%p\n",i,&arr[i]);
printf("arr+%d=%p\n",i,arr+i); arr+i 等价于&arr[i]
}
1.2 二维数组
二维数组有两个下标表示
1.二维数组的定义
格式:
存储类型 数据类型 数组名[常量表达式1][常量表达式2]
解析:
1>存储类型:auto\static\const\extern\register\volatile
2> 数据类型:基本类型{int float double...},构造类型,指针类型、空类型
3> 数组名:满足命名规范
4>常量表达式1: 第一维表示行数
5> 常量表达式2:第二维表示列数
2.二维数组定义以及初始化
1> 按行初始化
int arr[2][3]={{1,2,3},{4,5,6}};//全部初始化
int arr[2][3]={{1},{4,5}};//部分初始化,剩余元素默认以0填充
int arr[][3]={{1,2,3},{4,5,6}};//二维数组初始化时可以省略第一维
2> 按列初始化【常用】
int arr[2][3]={1,2,3,4,5,6};//全部初始化
int arr[2][3]={1,4,5,0,0,0};//部分初始化,剩余元素默认以0填充
int arr[][3]={1,2,3,4};//二维数组初始化时可以省略第一维
3> 错误初始化
int arr[2][]={1,2,3,4,5,6};//错误,不可以省略列数
int arr[2][3];
arr[2][3]={1,2,3,4,5,6};//错误 越界访问,arr[2][3]表示值
int arr[2][3];
arr={1,2,3,4,5,6};//错误:arr是指针、不可以赋值
2.二维数组的引用
1> 行列起始下标从0开始,m行n列的下标范围是【0--m-1】 [0--n-1]
2> 表示第3行第5列: arr[2][4]
3>越界访问:int arr[2][3] printf("arr[2][3]=%d",arr[2][3]);
1.如果越界访问的空间没有被占用,越界访问的结果是垃圾值
2.如果越界访问的空间被占用,但是存储不重要的数据,访问的是垃圾值
3.如果越界访问的空间被占用,但是存储重要的数据,则段错误
段错误:访问了不该访问的内存空间
4> 正确的引用
i)按列循环引用
for(int i=0;i<2;i++)//外层循环控制行
{
for(int j=0;j<3;j++)//内层循环控制列
{
scanf("%d",&arr[i][j]);
}
}
for(int i=0;i<2;i++)//外层循环控制行
{
for(int j=0;j<3;j++)//内层循环控制列
{
printf("%d ",arr[i][j]);//i=1
}
printf("\n");
}
ii)二维数组按行遍历,二维数组看似是二维实际存储是一维
int arr[2][3]={1,2,3,4,5,6};
printf("arr[1][0]=%d\n",arr[1][0]);//4
printf("arr[0][3]=%d\n",arr[0][3]);//等价于arr[1][0]
printf("arr[0][4]=%d\n",arr[0][4]);
//等价于arr[1][1]
printf("arr[0][5]=%d\n",arr[0][5]);
//等价于arr[1][2]
for(int i=0;i<2*3;i++)
{
printf("%d ",arr[0][i]);
}
冒泡排序
思路:
左边大于右边交换一趟排下来最大的在右边
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
int arr[]={5,1,3,9,7,1,5,9};
int len=sizeof(arr)/sizeof(int);
int i,j,t;
int flag;
for(i=1;i<len;i++)
{
flag=0;
for(j=0;j<len-i;j++)
{
if(arr[j]>arr[j+1])
{
t=arr[j];
arr[j]=arr[j+1];
arr[j+1]=t;
flag++;
}
}
if(flag==0)
break;
}
for(i=0;i<len;i++)
{
printf("%d ",arr[i]);
}
printf("\n");
return 0;
}
时间复杂度:最坏情况:O(N^2)
最好情况:O(N)
空间复杂度:O(1)