数组
数组是由多个相同类型的数据组成的集合
数组的内存地址是连续的
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main() {
int a[5] = { 1,2,3,4,5 };
for (int i = 0; i < 5; ++i)
{
printf("%p
", &a[i]);
}
return 0;
}
运行结果:
000000043FAFF818
000000043FAFF81C
000000043FAFF820
000000043FAFF824
000000043FAFF828
内存地址是十六进制的,可以看到,每个地址都是前一个地址加4(int占4字节)
改成字符数组:
0000003360DEFC14
0000003360DEFC15
0000003360DEFC16
0000003360DEFC17
0000003360DEFC18
数组的数组名代表了数组第一个元素的地址
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main() {
char a[5] = { 'a','v',' ','d','s' };
printf("%p
", a);
printf("%c
", *a);
return 0;
}
运行结果:
000000532697F9B4
a
数组的大小等于数组元素个数乘以每个元素的大小
因此有:
数组元素的个数 = sizeof(数组名) / sizeof(数组名[0]);
例:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>}
int main() {
int a[5] = { 1,2,3 };
int n = sizeof(a) / sizeof(a[0]);
printf("数组元素个数:%d", n);
for (int i = 0; i < n; ++i)
{
printf("%d ", a[i]);
}
return 0;
}
运行结果:
数组元素个数:5
1 2 3 0 0
一维数组
语法:
数据类型 数组名[元素个数];
字符数组(字符串)
// 方法一
char s[4] = {'a','b','c',' '};
// 也可以不写元素个数,编译器会自己统计
char s[] = {'a','b','c',' '};
最后的' '是结束符,系统读取到' '就会停止
如果不加结束符,会变成这样:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main() {
char a[5] = { 'a','v','c','d','s' };
puts(a);
return 0;
}
运行结果:
avcds烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫 烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫??,a
这是乱码
另一个例子:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main() {
char a[5] = { 'a','v',' ','d','s' };
puts(a);
return 0;
}
运行结果:
av
可以验证读取字符串是读取到' '结束
// 方法二
char s[] = "Hello world";
直接把字符串赋值给字符数组,和把字符拆开赋值效果一样,注意此时字符串末尾自带' '
获取长度
导入库
#include <string.h>
使用:
strlen(字符串);
例:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main() {
char s[] = "Hello world";
printf("%d
", strlen(s));
return 0;
}
运行结果:
11
数值数组
一般常用的是int数组
语法:
int 数组名[元素个数];
元素个数在初始化时可以不写,自动统计,在C99中元素个数可以是变量
访问:
数组名[下标];
注意!数组下标是从0开始的
打印数组:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main() {
int a[] = { 1,2,3,7,3 };
for (int i = 0; i < 5; ++i)
{
printf("%d ", a[i]);
}
return 0;
}
运行结果:
1 2 3 7 3
注意!要注意防止数组下标越界!!!
例:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main() {
int a[] = { 1,2,3,7,3 };
for (int i = 0; i < 5; ++i)
{
printf("%d ", a[i+1]);
}
return 0;
}
运行结果:
2 3 7 3 -858993460
数组越界是非常危险的行为
数组的总大小 = 元素个数 * 每个元素大小
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main() {
int a[] = { 1,2,3,7,3 };
printf("%d", sizeof(a));
return 0;
}
运行结果:
20
部分初始化和全部初始化
// 全部初始化
int a[] = { 1,2,3,7,3 };
// 部分初始化
int a[4] = {1,2};
如果全部初始化,可以省略元素个数
部分初始化中未被初始化的元素默认为0
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>}
int main() {
int a[5] = { 1,2,3 };
for (int i = 0; i < 5; ++i)
{
printf("%d ", a[i]);
}
return 0;
}
运行结果:
1 2 3 0 0
二维数组
定义
数据类型 数组名[行数][列数];
例:
int a[3][4];
注意!二维数组可以省略行数,但不能省略列数
初始化
例:
int a[3][4] = {{1,4},{5,6,7,8},{9}}; // 方法一
int a[2][3] = {1,2,3,4,5,6}; // 方法二
打印
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main() {
int a[3][4] = { {1,2,3,4},{5,6,7,8},{3}};
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 4; j++)
{
printf("%d ", a[i][j]);
}
printf("
");
}
return 0;
}
运行结果:
1 2 3 4
5 6 7 8
3 0 0 0
数组案例
一维数组
案例1:求数组最大值
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int max(int a[],int n) {
int max = a[0];
for (int i = 0; i < n; ++i)
{
if ((i + 1) <= n) {
if (max < a[i + 1]) {
max = a[i + 1];
}
else
{
continue;
}
}
else
{
if (max < a[i]) {
max = a[i];
}
else
{
continue;
}
}
}
return max;
}
int main() {
int a[5] = { 1,3,4444,2,253 };
printf("max of a is %d
", max(a,5));
return 0;
}
运行结果:
max of a is 4444
案例2:求数组最小值
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int min(int a[], int n) {
int min = a[0];
for (int i = 0; i < n; ++i)
{
if ((i + 1) <= n) {
if (min > a[i + 1]) {
min = a[i + 1];
}
else
{
continue;
}
}
else
{
if (min > a[i]) {
min = a[i];
}
else
{
continue;
}
}
}
return min;
}
int main() {
int a[5] = { 1,3,4444,2,253 };
printf("min of a is %d
", min(a, 5));
return 0;
}
运行结果:
min of a is 1
案例3:求数组平均值
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
double average(int a[], int n) {
int sum = 0;
for (int i = 0; i < n; i++)
{
sum += a[i];
}
return ((double)sum) / ((double)n);
}
int main() {
int a[5] = { 1,2,3,4,6 };
printf("Average of a is %g
", average(a, 5));
return 0;
}
运行结果:
Average of a is 1.5
案例4:逆置数组
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
void inversion(int a[],int n) {
for (int i = 0,j = n - 1; i < j; ++i, --j)
{
int tmp = 0;
tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
}
int main() {
int a[5] = { 1,2,3,4,5 };
inversion(a,5);
for (int i = 0; i < 5; ++i) {
printf("%d ", a[i]);
}
return 0;
}
运行结果:
5 4 3 2 1
案例5:冒泡排序
算法思想
- 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
- 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
- 针对所有的元素重复以上的步骤,除了最后一个。
- 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较
代码
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
void bubbleSort(int a[], int n) {
for (int i = 0; i < n - 1; ++i) {
for (int j = 0; j < n - i - 1; ++j) {
if (a[j] > a[j + 1]) {
int tmp = 0;
tmp = a[j];
a[j] = a[j + 1];
a[j + 1] = tmp;
}
}
}
}
int main() {
int a[5] = {1,4,2,3,6};
bubbleSort(a, 5);
for (int i = 0; i < 5; ++i) {
printf("%d ", a[i]);
}
return 0;
}
运行结果:
1 2 3 4 6