1.数组与指针
1.1 数组名 = 地址
- 数组名是数组第一个元素的地址。
#include <stdio.h>
int main()
{
int arr[] = {1,2,3,4,5,6,7,8};
for(int i=0;i<sizeof(arr)/sizeof(arr[0]);i++){
printf("&arr[%d] = %p arr+%d = %p",i,&arr[i],i,arr+i);
printf("\n");
}
printf("\n");
printf("&arr = %p\n",&arr);
printf("arr = %p\n",arr);
}
-
数组名
+下标
= 下标i
元素的地址 -
*arr[i]
=arr+i
- 数组名不可以改变
遍历数组/输入输出:
#include <stdio.h>
int main()
{
int n;
scanf("%d",&n);
int arr[n];
for(int i=0;i<n;i++){
scanf("%d",arr+i);
}
for(int i=0;i<n;i++){
printf("%d ",*(arr+i));
}
printf("\n");
}
1.2 数组名放入指针
地址存储在指针中。可以用指针操作地址。
#include <stdio.h>
int main()
{
int arr[] = {1,2,3,4,5,6,7,8};
int* p = arr;
for(int i=0;i<sizeof(arr)/sizeof(arr[0]);i++){
printf("%d %d\n",p[i],*(p+i));
}
}
2.函数与数组
2.1传递数组给函数
#include <stdio.h>
void PrintArr(int* arr,int len){
for(int i=0;i<len;i++){
printf("%d ",arr[i]);
}
printf("\n");
}
int main()
{
int arr[] = {1,2,3,4,5,6,7,8};
int len = sizeof(arr)/sizeof(arr[0]);
PrintArr(arr,len);
}
#include <stdio.h>
void Test1(int a[]){
printf("sizeof(a):%d\n",sizeof(a));
printf("a:%p\t&a:%p\n",a,&a);
}
void Test2(int* p){
printf("sizeof(p):%d\n",sizeof(p));
printf("p:%p\t&p:%p\n",p,&p);
}
int main(){
int arr[10];
printf("sizeof(arr):%d\n",sizeof(arr));
printf("arr:%p\t&arr:%p\n",arr,&arr);
Test1(arr);
Test2(arr);
}
数组作为参数时,数组退化成指针,不能利用
sizeof
获取数组大小,也就不能计算数组元素个数。练习
两个有序数组的归并
输入一个整数n(n <= 10000)和n个整数a[i],保证这n个整数已按照从小到大进行排序。然后输入一个整数m(m <= 10000),和m个整数b[j],保证这m个整数已按照从小到大进行排序。将两组数归并后输出。
2.2 从函数返回数组
C 语言不允许返回一个完整的数组作为函数的参数。通过指定不带索引的数组名来返回一个指向数组的指针。
- 语法
类型* 函数名(){
return 数组名;
}
- 练习
1.给定数组随机填充指定范围的数据。
使用stdlib.h
中的srand(time(NULL))
和rand()
.
time()
头文件:#include<time.h>
srand()
,rand()
头文件:#include<stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// 函数:打印数组 将数组传递给函数
void PrintArr(int*arr,int n){
for(int i=0;i<n;i++){
printf("%d ",arr[i]);
}
printf("\n");
}
// 函数:填充数组1 从函数返回数组 根据长度给数组赋值
int* FillArr(int*arr,int n){
for(int i=0;i<n;i++){
arr[i] = i;
}
return arr;
}
// 函数:填充数组2 产生随机数对数组进行填充
// srand(time(NULL)); // stdlib.h // time.h
// rand()
int* FillArr2(int* arr,int n){
srand(time(NULL));
for(int i=0;i<n;i++){
arr[i] = rand();
}
return arr;
}
// 函数:填充数组3 产生0-9之间的随机数对数组进行填充
// rand()%n; 随机产生 0 ~ n-1 之间的随机数
int* FillArr3(int* arr,int n){
srand(time(NULL));
for(int i=0;i<n;i++){
arr[i] = rand()%10;
}
return arr;
}
// 函数:填充数组4 产生a-b之间的随机数对数组进行填充
int* FillArr4(int* arr,int n,int a,int b){
srand(time(NULL));
for(int i=0;i<n;i++){
arr[i] = rand()%(b-a)+a;
}
return arr;
}
int main()
{
int n;
scanf("%d",&n);
int arr[n];
PrintArr(FillArr(arr,n),n);
PrintArr(FillArr2(arr,n),n);
PrintArr(FillArr3(arr,n),n);
PrintArr(FillArr4(arr,n,5,15),n);
}
- 将一维数组的查找
FindArr()
和替换RepalceArr()
封装成函数。
#include <stdio.h>
#include <stdbool.h>
// 函数:终端输入函数
void ScanfArr(int* arr,int n){
for(int i=0;i<n;i++){
scanf("%d",&arr[i]);
}
}
// 函数:查找指定数字num1
// 返回值为bool类型 找到返回true 没找到返回false
bool FindNum(int* arr,int n,int num){
for(int i=0;i<n;i++){
if(arr[i] == num){
return true;
}
}
return false;
}
// 函数:查找指定数字num2
// 返回值为int型 返回下标 不存在返回-1
int FindNum2(int* arr,int n,int num){
for(int i=0;i<n;i++){
if(arr[i] == num){
return i;
}
}
return -1;
}
// 函数:查找指定数字num3
// 返回值为int* 存在返回num的地址 不存在返回NULL
int* FindNum3(int* arr,int n,int num){
for(int i=0;i<n;i++){
if(arr[i] == num){
return arr+i;
}
}
return NULL;
}
void FindArr(int* arr,int n,int num){
bool res = FindNum(arr,n,num);
if(res){
printf("%d is in arr.\n",num);
}else{
printf("%d is not in arr.\n",num);
}
}
void FindArr2(int* arr,int n,int num){
int position = FindNum2(arr,n,num);
if(-1 != position){
printf("arr[%d] = %d.\n",position,num);
}else{
printf("%d is not in arr.\n",num);
}
}
void FindArr3(int* arr,int n,int num){
int* p = FindNum3(arr,n,num);
if(NULL != p){
printf("%d : %p\n",num,p);
}else{
printf("%d is not in arr.\n",num);
}
}
// 函数:全部查找
void FindAll(int* arr,int n,int num){
for(int i=0;i<n;i++){
if(arr[i] == num) printf("arr[%d] = %d.\n",i,num);
}
}
// 函数:替换数组元素
// 1.num1是否在数组中
// 2.替换
void Repalce(int* arr,int n,int num1,int num2){
int position = FindNum2(arr,n,num1);
if(-1 != position){
arr[position] = num2;
}else{
printf("%d is not in arr.\n",num1);
}
}
// 函数:替换数组元素2
void Repalce2(int* arr,int n,int num1,int num2){
int* p = FindNum3(arr,n,num1);
if(NULL != p){
*p = num2;
}else{
printf("%d is not in arr.\n",num1);
}
}
// 函数:全部替换
void ReplaceAll(int* arr,int n,int num1,int num2){
for(int i=0;i<n;i++){
if(arr[i] == num1){
arr[i] = num2;
}
}
}
// 函数:打印数组
void PrintArr(int* arr,int n){
for(int i=0;i<n;i++){
printf("%d ",arr[i]);
}
printf("\n");
}
int main(){
// 输入数组长度
int n;
scanf("%d",&n);
int arr[n];
ScanfArr(arr,n);
PrintArr(arr,n);
// 输入要查找的数字
int num;
scanf("%d",&num);
FindArr(arr,n,num);
FindArr2(arr,n,num);
FindArr3(arr,n,num);
// 替换数字 将num1替换成num2
PrintArr(arr,n);
int num1,num2;
scanf("%d%d",&num1,&num2);
// Repalce(arr,n,num1,num2);
Repalce2(arr,n,num1,num2);
PrintArr(arr,n);
// 替换全部
int arr1[n];
ScanfArr(arr1,n);
int a,b;
scanf("%d%d",&a,&b);
PrintArr(arr1,n);
FindAll(arr1,n,a);
ReplaceAll(arr1,n,a,b);
PrintArr(arr1,n);
}
- 通过函数返回数组下标进行查找和替换
#include <stdio.h>
// 函数:查找数组元素下标
int Find(int* arr,int n,int num){
for(int i=0;i<n;i++){
if(arr[i] == num){
return i;
}
}
return -1;
}
int FindAll(int* arr,int n,int num,int* res){
int count = 0;
for(int i=0;i<n;i++){
if(arr[i] == num){
res[count] = i;
count++;
}
}
return count;
}
void ReplaceAll(int* arr,int n,int a,int b){
int res = Find(arr,n,a);
while(res != -1){
arr[res] = b;
int ans = Find(arr+res+1,n-(res+1),a);
res = (ans != -1)?ans+res+1:-1;
}
}
void PrintArr(int* arr,int n){
for(int i=0;i<n;i++){
printf("%d ",arr[i]);
}
printf("\n");
}
int main()
{
//
printf("Enter array length:");
int n;
scanf("%d",&n);
int arr[n];
printf("Enter array:");
for(int i=0;i<n;i++){
scanf("%d",&arr[i]);
}
PrintArr(arr,n);
//
int find_res[n];
int a;
printf("Enter the number you want to find:");
scanf("%d",&a);
int count = FindAll(arr,n,a,find_res);
for(int i=0;i<count;i++){
printf("arr[%d] = %d.\n",find_res[i],a);
}
//
int b;
printf("Enter the number you want to replace:");
scanf("%d",&b);
ReplaceAll(arr,n,a,b);
PrintArr(arr,n);
}
- 通过函数返回数组指针进行查找和替换
#include <stdio.h>
// 函数:查找数组元素下标
int Find(int* arr,int n,int num){
for(int i=0;i<n;i++){
if(arr[i] == num){
return i;
}
}
return -1;
}
// 函数:查找数组元素地址
int* Find2(int* arr,int n,int num){
for(int i=0;i<n;i++){
if(arr[i] == num){
return arr+i;
}
}
return NULL;
}
int FindAll(int* arr,int n,int num,int* res){
int count = 0;
int* find_res = Find2(arr,n,num);
while(find_res != NULL){
res[count] = find_res-arr;
count++;
find_res = Find2(find_res+1,n-(find_res-arr+1),num);
}
return count;
}
// 函数:通过返回函数指针替换数组元素
// res - arr : 下标
void ReplaceAll(int* arr,int n,int a,int b){
int* res = Find2(arr,n,a);
while(res != NULL){
*res = b;
res = Find2(res+1,n-(res-arr+1),a);
}
}
void PrintArr(int* arr,int n){
for(int i=0;i<n;i++){
printf("%d ",arr[i]);
}
printf("\n");
}
int main()
{
//
printf("Enter array length:");
int n;
scanf("%d",&n);
int arr[n];
printf("Enter array:");
for(int i=0;i<n;i++){
scanf("%d",&arr[i]);
}
PrintArr(arr,n);
//
int find_res[n];
int a;
printf("Enter the number you want to find:");
scanf("%d",&a);
int count = FindAll(arr,n,a,find_res);
for(int i=0;i<count;i++){
printf("arr[%d] = %d.\n",find_res[i],a);
}
//
int b;
printf("Enter the number you want to replace:");
scanf("%d",&b);
ReplaceAll(arr,n,a,b);
PrintArr(arr,n);
}
3.多维数组
3.1 声明
- 语法
类型 数组名[元素个数1][元素个数2][元素个数3]...
- 二维数组
类型 数组名[行数][列数]
4行3列的int类型二维数组
int arr[4][3];
3.2 初始化二维数组
int arr[4][3] ={
{1,2,3},
{1,1,1},
{1,3,1},
{3,2,3}
};
3.3 访问二维数组元素
通过行列下标索引进行访问。
int n = arr[i][j];
arr[i][j] = 1;
3.4 遍历二维数组元素
通过嵌套循环进行遍历。
int arr[r][n];
for(int i=0;i<r;i++){
for(int j=0;j<c;j++){
a[i][j] = i*c+j;
}
}
3.5 输入、输出
嵌套循环输入:
int r,c;
scanf("%d%d",&r,&c);
int arr[r][c];
for(int i=0;i<r;i++){
for(int j=0;j<c;j++){
scanf("%d",&arr[i][j]);
}
}
嵌套循环输出:
for(int i=0;i<r;i++){
for(int j=0;j<c;j++){
printf("%d ",arr[i][j]);
}
printf("\n");
}
- 练习
1.输入m
个学生的n
门课程成绩,输出各门课程成绩以及总成绩和平均值。
#include <stdio.h>
// stu1 : curr1 curr2 curr3
// stu2 : curr1 curr2 curr3
int main(){
int student_num,curriculum_num;
printf("Enter the number of students:");
scanf("%d",&student_num);
printf("Enter the number of curriculum:");
scanf("%d",&curriculum_num);
int table[student_num][curriculum_num];
for(int i=0;i<student_num;i++){
printf("Enter %d curriculum scores of student %d:",curriculum_num,i);
for(int j=0;j<curriculum_num;j++){
scanf("%d",&table[i][j]);
}
}
for(int i=0;i<student_num;i++){
int sum_score = 0;
float average_score = 0;
for(int j=0;j<curriculum_num;j++){
sum_score += table[i][j];
printf("%d ",table[i][j]);
}
average_score = 1.0*sum_score/curriculum_num;
printf("%d ",sum_score);
printf("%f ",average_score);
printf("\n");
}
}
2.实现矩阵基本运算(加、减、乘、转置)。
#include <stdio.h>
// 矩阵操作
// 加法
// 减法
// 乘法
// 转置
int main(){
int r,c;
printf("Enter the rows and columns of the matrix:");
scanf("%d%d",&r,&c);
int matrix[r][c];
for(int i=0;i<r;i++){
printf("Enter the elements in %d row of the matrix:",i);
for(int j=0;j<c;j++){
scanf("%d",&matrix[i][j]);
}
}
for(int i=0;i<r;i++){
for(int j=0;j<c;j++){
printf("%d ",matrix[i][j]);
}
printf("\n");
}
// 矩阵加法、减法
int matrix2[r][c];
for(int i=0;i<r;i++){
printf("Enter the elements in %d row of the matrix:",i);
for(int j=0;j<c;j++){
scanf("%d",&matrix2[i][j]);
}
}
for(int i=0;i<r;i++){
for(int j=0;j<c;j++){
printf("%d ",matrix2[i][j]);
}
printf("\n");
}
printf("------------------------------sum----------------------------------------\n");
int sum_matrix[r][c];
int subtraction_matrix[r][c];
for(int i=0;i<r;i++){
for(int j=0;j<c;j++){
sum_matrix[i][j] = matrix[i][j] + matrix2[i][j];
subtraction_matrix[i][j] = matrix2[i][j] - matrix[i][j];
}
}
for(int i=0;i<r;i++){
for(int j=0;j<c;j++){
printf("%d ",sum_matrix[i][j]);
}
printf("\n");
}
printf("------------------------------subtraction--------------------------------\n");
for(int i=0;i<r;i++){
for(int j=0;j<c;j++){
printf("%d ",subtraction_matrix[i][j]);
}
printf("\n");
}
// 矩阵转置
printf("-------------------------------transpose---------------------------------\n");
int transpose_matrix[c][r];
for(int i=0;i<c;i++){
for(int j=0;j<r;j++){
transpose_matrix[i][j] = matrix[j][i];
}
}
for(int i=0;i<c;i++){
for(int j=0;j<r;j++){
printf("%d ",transpose_matrix[i][j]);
}
printf("\n");
}
// 矩阵乘法
printf("---------------------------multiplication1------------------------------\n");
int num;
printf("Enter num:");
scanf("%d",&num);
int multiplication_matrix[r][c];
for(int i=0;i<r;i++){
for(int j=0;j<c;j++){
multiplication_matrix[i][j] = num*matrix[i][j];
}
}
for(int i=0;i<r;i++){
for(int j=0;j<c;j++){
printf("%d ",multiplication_matrix[i][j]);
}
printf("\n");
}
printf("---------------------------multiplication2------------------------------\n");
int multiplication_matrix2[r][r];
for(int i=0;i<r;i++){
for(int j=0;j<r;j++){
multiplication_matrix2[i][j] = 0;
}
}
for(int i=0;i<r;i++){
for(int j=0;j<r;j++){
for(int k=0;k<c;k++){
multiplication_matrix2[i][j] += matrix[i][k]*transpose_matrix[k][j];
}
}
}
for(int i=0;i<r;i++){
for(int j=0;j<r;j++){
printf("%d ",multiplication_matrix2[i][j]);
}
printf("\n");
}
}
3.6 简化写法
初始化二维数组可以有如下简化写法:
1.省略内部嵌套符号:
int arr[4][3] = {1,1,1,2,2,2,3,3,3,4,4,4};
2.省略第一维大小,第二维不能省略。
int arr[][3] = {1,1,1,2,2,2,3,3,3,4,4,4};
3.部分初始化:
int arr[2][3] = {{1},{2}};
/*
{{1,0,0},
{2,0,0}
};
*/
3.7 二维数组作为函数参数
- 二维数组名是一个数组指针
二维数组作为函数参数,需要同属输入行和列的个数。
#include <stdio.h>
void PrintArr(int arr[2][3],int r,int c){
for(int i=0;i<r;i++){
for(int j=0;j<c;j++){
printf("%d ",arr[i][j]);
}
printf("\n");
}
}
int main(){
int arr[2][3] = {
{1,2,3},
{4,5,6}
};
PrintArr(arr,2,3);
}
3.8 多维数组
#include <stdio.h>
int main(){
int days[][4][3]={
{31,28,31,30,31,30,31,31,30,31,30,31}, // 平年
{31,29,31,30,31,30,31,31,30,31,30,31} // 闰年
};
printf("平年二月天数为%d\n",days[0][0][1]);// 平年第一季度第二个月
printf("闰年二月天数为%d\n",days[1][0][1]);// 闰年第一季度第二个月
}
4.const
数组
- 语法
const int arr[] = {1,2,3,4};
- 作用:用来保护数组值,数组在作为函数的参数时是以地址的形式进行传递的,函数内部可以修改数组的值,保护数组不被函数破坏。
- 2.2 2(2)修改
PrintArr()
void PrintArr(const int* arr,int n){
for(int i=0;i<n;i++){
printf("%d ",arr[i]);
}
printf("\n");
}
5.变量指针和数组指针
- 变量指针:指向单个变量的指针
- 数组指针:指向数组的指针
#include <stdio.h>
int main () {
// 变量指针
int n = 10;
int *p;
p = &n; // p指针指向变量
printf("*p = %d\n",*p);
// 数组指针
int arr[] = {1,2,3,4,5};
p = arr;// p指针指向数组
printf("*p = %d\n",*p);
printf("*(p+1) = %d\n",*(p+1));
printf("*(p+2) = %d\n",*(p+2));
printf("*(p+3) = %d\n",*(p+3));
printf("*(p+4) = %d\n",*(p+4));
}
6.二维数组的一维使用方式
6.1 二维数组转一维数组
- 按行遍历
按列遍历
#include <stdio.h>
int main()
{
int r,c;
printf("Enter the number of rows and columns:");
scanf("%d%d",&r,&c);
int arr[r][c];
for(int i=0;i<r;i++){
for(int j=0;j<c;j++){
scanf("%d",&arr[i][j]);
}
}
printf("---------------------------------Print Arr--------------------------------\n");
for(int i=0;i<r;i++){
for(int j=0;j<c;j++){
printf("%d ",arr[i][j]);
}
printf("\n");
}
printf("------------------------------Traverse by line----------------------------\n");
// 按行遍历
int arr2[r*c];
for(int i=0;i<r;i++){
for(int j=0;j<c;j++){
arr2[i*c+j] = arr[i][j];
}
}
for(int i=0;i<r*c;i++){
printf("%d ",arr2[i]);
}
printf("\n");
printf("----------------------------Traversal by column---------------------------\n");
// 按列遍历
int arr3[r*c];
for(int i=0;i<c;i++){
for(int j=0;j<r;j++){
arr3[i*r+j] = arr[j][i];
}
}
for(int i=0;i<r*c;i++){
printf("%d ",arr3[i]);
}
printf("\n");
}
6.2 三维数组转一维数组
- 按照页行列的顺序依次遍历
- 第一维度:页
- 第二维度:行
- 第三维度:列
#include <stdio.h>
int main()
{
int days[2][4][3] = {
{
{31,28,31},
{30,31,30},
{31,31,30},
{31,30,31}
},
{
{31,29,31},
{30,31,30},
{31,31,30},
{31,30,31}
}
};
printf("--------------------------------Print Arr--------------------------------\n");
for(int i=0;i<2;i++){
for(int j=0;j<4;j++){
for(int k=0;k<3;k++){
printf("%d ",days[i][j][k]);
}
printf("\n");
}
printf("\n");
}
printf("----------------------------------3 to 1----------------------------------\n");
int arr[2*4*3];
// i:页 j:行 k:列
for(int i=0;i<2;i++){
for(int j=0;j<4;j++){
for(int k=0;k<3;k++){
arr[i*4*3+j*3+k] = days[i][j][k];
}
}
}
for(int i=0;i<2*4*3;i++){
printf("%d ",arr[i]);
}
printf("\n");
}
7.一维数组的多维使用方式
7.1一维数组转二维数组
- 元素下标 = 当前行序号*列数+当前列序号
#include <stdio.h>
int main()
{
int arr[24];
for(int i=0;i<24;i++){
arr[i] = i;
}
for(int i=0;i<24;i++){
printf("%d ",arr[i]);
}
printf("\n");
// 一维数组转二维数组
// 24 = 4*6;
int r = 4;
int c = 6;
for(int i=0;i<r;i++){
for(int j=0;j<c;j++){
printf("%2d ",arr[i*c+j]);
}
printf("\n");
}
}
7.2 一维数组转三维数组
- 元素下标 = 当前页序号行数列数+当前行序号*列数+当前列序号
#include <stdio.h>
int main()
{
int arr[24];
for(int i=0;i<24;i++){
arr[i] = i;
}
for(int i=0;i<24;i++){
printf("%d ",arr[i]);
}
printf("\n");
// 一维数组转三维数组
// 24 = 2*4*3;
int p = 2;
int r = 4;
int c = 3;
for(int i=0;i<p;i++){
for(int j=0;j<r;j++){
for(int k=0;k<c;k++){
printf("%2d ",arr[i*r*c+j*c+k]);
}
printf("\n");
}
printf("\n");
}
}
8.二维数组指针用法
- 一维数组指针用法
No | 操作 | 下标 | 指针 |
---|---|---|---|
1 | 第i个元素值 | arr[i] | *(arr+i) |
2 | 第i个元素地址 | &arr[i] | arr+i |
- 二维数组指针用法
二维数组中arr[i]
是一个一维数组
No | 操作 | 下标 | 指针 |
---|---|---|---|
1 | 第i行第j列元素值 | arr[i][j] | *(*(arr+i)+j) |
2 | 第i行第j列元素地址 | &arr[i][j] | *(arr+i)+j |