Day2_Array_Pointer
DAY2
主题:数组与指针
数组
练习一:
求一个一维数组的第二大元素,要求仅遍历一次数组。
数组元素默认不重复。
/**********************************************************************
练习1:
求一个一维数组的第二大元素,要求仅遍历一次数组。
**********************************************************************/
#if 1
#include<stdio.h>
int main()
{
int arr[10] = { 102,233,435,253,12399,
45,2353,65,434,8877 };
int max = arr[0];
int max2 = arr[0];
for (int i = 0; i < 10; i++)
{
if (arr[i] > max)
{
max2 = max;
max = arr[i];
}
else if (arr[i] > max2)max2 = arr[i];
printf("max:%d\n", max);
printf(" max2:%d\n", max2);
}
//printf("%d dierda",max2);
return 0;
}
#endif
数组是一组相同数据类型的有序的元素。
数组的定义
数组元素的类型 数组名[元素的个数]{=初始化};
int a[0];//定义了一个数组 里面有0个元素。空数组
struct Node
{
char Data[0];
struct Node* prev;
struct Node* next;
};
int a[10];
typeof(a) = ?
a是一个数组,是一个有10个int类型元素的数组
typeof(a) ==> int[10] //构造类型:由用户定义的类型
定义一个变量:类型 变量名;
定义一个像a的类型的变量b;
typeof(a) b;
int [10] b; ===>int b[10];
数组元素全部都是一维数组
typeof(a) c[5];//定义了一个数组,有5个类型为一维数组(有10个int类型的一维数字)的一维数组。
int[10] c[5];===>int c[5][10];
c这个数组有5个元素,分别为c[0] c[1] c[2] c[3] c[4]
c[0]是一个数组,数组名,所以我们访问c[0]里面的第一个元素,c[0][0]
数组与函数
数组怎么传入函数?数组作为函数的参数
数组元素的类型 [],数组元素的个数
int a[10]
sum(int b[],int n)
{
}
调用:sum(a,10);
typeof(a) =>int[10]
sum(int[10] b) ==>sum(int b[10])
{
}
练习
封装一个函数,对任意长度的整型(int)一维数组进行输入
array_input()
封装一个函数,对任意长度的整型(int)一维数组进行输出
array_output()
/**********************************************************************
练习2:
封装一个函数,对任意长度的整型(int)一维数组进行输入
array_input()
封装一个函数,对任意长度的整型(int)一维数组进行输出
array_output()
**********************************************************************/
#if 1
#include<stdio.h>
int array_intput(int array[], int n)
{
for (int i = 0; i < n; i++)scanf("%d", &array[i]);
}
int array_output(int array[], int n)
{
for (int i = 0; i < n; i++)printf("%d\n", array[i]);
}
int main()
{
int a[3] = { 1,2,3 };
int b[3];
array_intput(b, 3);
array_output(a, 3);
array_output(b, 3);
return 0;
}
#endif
指针
请封装一个函数来交换两个数(正整数)的值,要求不要百
度。
time:20分钟 14.45分讲解
main
a = 3,b = 4;
swap();//形参自己定义
printf("%d %d",a,b);//4 3
进阶:请使用三种方法可以不完成
1.指针的概念
存储单元的地址:
分配给每个变量的内存单元都有一各编号,这个编号
就是我们所说的存储单元的地址。
在C语言中,指针和地址的概念差不多,你可以认为
指针就是一个地址。
地址:
一个变量的地址。也称之为变量的“指针"
& 取地址符
eg: &a
int a;
scanf("%d",&a);
通过对象的指针去访问它,首先我们要解决对象的地
址的保存问题。
2.指针变量
是一个变量,能读能写。指针变量保存地址的。
变量的定义:
变量的类型 变量名; eg:int a
指针变量不是一般的变量,所以我们一般在变量的前面加
一个"*",表示它是一个指针变量。
指针变量的定义:
指向对象的类型 *指针变量名;
指向对象的类型而不是指针的类型。
指向
你的名字是你的,你的名字指向你。你的名字有没有
包含你的"地址"
你的名片是你的,名片是不是想你。那么我可以不可
以根据你的名片上门打你一顿。
间接的方式,间接访问。
指针变量保存了谁的地址,指向谁。
名片上保存了谁的地址,那就指向谁。
eg:
int a;
int *p;//p指向的对象类型是int
p=&a;//p保存的是a的地址 所以p指向a
3.指针相关的运算符
*:指向运算符
动词,根据地址找上门
int a;
int *p=&a;//p指向a
*p ==>根据p的值(是a的地址) 根据a的地址去找a
所以*p <===> a
*p = 1024 <==> a = 1024
*(&a) = 1024 <==> a=1024
*&可以约掉 抵消
段错误:内存异常,访问内存错误。默认中止程序。致命
错误。segment default
eg:修改了只读的。比如:5 = 10;
int swap4(int *a,int *b)
{
int *temp = NULL;
*temp = *a;
*a = *b;
*b = *temp;
}
int *temp;//temp指向谁? 野指针
访问野指针一定会段错误吗?不一定,可能指向的那个内
存单元可以访问的。
一般让它指向为空
int *temp=NULL;//NULL 的ASCII是0 '\0' temp指
向内存编号为0的地方
//但是内存编号为0的储存空间是不存在的 能访问吗?不
能
所以访问这个为0编号的内存 一定会段错误
*temp 就一定段错误。
int a = 4;
4.指针做加减法
int *p = &a;//p->a
typeof(p)的类型?类型 变量名;
int * typeof(&a) ==> typeof(a) *==>int *
数组作为函数的参数
数组名?int a[10];
1.代表整个数组
sizeof(a) ==>整个数组的大小
typeof(a) ==>数组的类型 int[10]
2.数组的首地址 等价于 &a[0] 当作指针
typeof(&a[0]) =>int *
int a[],int n <==> int *a,int n
int a[10]
4.指针做加减法
数火车,一节一节车厢 单位是车厢
数人头 单位是人
int *p = 0x300400;//p指向的对象是一节车厢 车厢
占4个字节
p+1 下一节车厢 所以p+1的值为多少 0x300404
char *p1 = 0x300400;
p1+1 0x300401;
int a[10];
|————|----|----|....
&a[0] = 0x300400
a当指针来用
5.字符串
&a[0] = a + 0 a[0] <==>*(a+0)
&a[1] = a + 1 a[1] <==>*(a+1)
....
请问 a[10] 存在吗?a[-1] <==>*(a-1)
5.字符串
C语言是没有字符串这种类型的
把字符一个挨着一个存储,读的话从头读到尾。
|___|___|....|___| '\0' 结束的标志
知道头 知道尾
首地址 char*
+1 +1 +1
char *str = "hello world";//str是指针 ""字符
串 ''字符 str保存是h的首地址
str指向一段内存 “hello world" 这个字符串储存
在.rodata 只读数据段
"hello world"长度为?12
*(str+3)='W';//这个代码会段错误
char str[]={"hello world"};//str 字符数组 数
组元素可读 可写的
char str[]={'h','e','l','l'....};
请问该数组的长度
str[4]='W';//可以
char s[64]={0},c;//<==>char *s;char c
int i=0;
for(;i<5;i++)
练习
{
scanf("%c",&c);
*(s+i)=c;
}
//段错误 为什么
char s[64] ={0};里面的元素都是0
printf("%c",s[1]);//'\0'
char整型 存储的是整数 ascii码
s[1] ->char 字符串ascii为0 为0 '\0'
s[1] = '0';
动态内存分配 ---> 申请一段可用的内存(权限 可读可
写 归你所有)
/**********************************************************************
* 练习3:
封装交换两个数的函数:swap();
**********************************************************************/
#if 0
#include<stdio.h>
//法1:
//普通的变量代替不会改变变量正真的值;
//在执行该函数时,存储空间生成形参,形参接收的只是实参的值的拷贝。
//即a=c只是数值上的相等,a并不是c
void swap1(int a, int b) {
int mid = 0;
mid = a;
a = b;
b = mid;
printf("a= %d,b= %d\n", a, b);
//printf("a= %d,b= %d\n", &a, &b);//运行后可以看出来显然与c,d的地址不一样,因为输出的是形参的地址。
}
//法2:
//该法交换了实参c和d的地址,所以在main()函数中仍然交换
void swap2(int *a, int *b) {
int mid;
mid = *a;
*a = *b;
*b = mid;
printf("a= %d,b= %d\n", *a, *b);
//printf("a= %d,b= %d\n", a, b);//输出的是实参的地址
}
//法3
//该法交换了实参的指针,所以在main()函数中仍交换
void swap3(int *a, int *b) {
int* c;
c = a;
a = b;
b = c;
printf("a= %d,b= %d\n", *a, *b);
//printf("a= %d,b= %d\n", a, b);//输出的是实参的地址
}
int main()
{
int c = 3, d = 4;
swap1(c, d);
printf("a= %d,b= %d\n", c, d);
swap2(&c, &d);
printf("a= %d,b= %d\n", c, d);
swap3(&c, &d);
printf("a= %d,b= %d\n", c, d);
}
#endif
/**********************************************************************
* 练习4:
1.有一个一维数组int a[10]
请封装以下函数:
(1)求最大值;Max_array()
(2)求和Sum_array()
2.封装一个函数,实现如下功能:
判断一个三位数是否满足:各个位的数字的阶乘的和等于它的本身
**********************************************************************/
#if 0
#include<stdio.h>
void Max_array(int array[], int n)
{
int max = 0;
for (int i = 0; i < n; i++)max = array[i] > max ? array[i] : max;
printf("这个数组的最大值是%d\n", max);
}
void Sum_array(int array[], int n)
{
int sum = 0;
for (int i=0; i < n; i++)sum += array[i];
printf("这个数组的和是%d\n", sum);
}
void PDJiec(int num)
{
int sum = 0;
int chengji = 1;
int single = num % 10;
int ten = (num / 10) % 10;
int hundred = num / 100;
if (num / 100 == 0 || num / 1000 != 0)
printf("输入错误,");
else
{
for (int i = 0; i < single; i++)chengji *= (i + 1);
//printf("%d\n", chengji);
sum += chengji;
chengji = 1;
for (int i = 0; i < ten; i++)chengji *= (i + 1);
sum += chengji;
//printf("%d\n", chengji);
chengji = 1;
for (int i = 0; i < hundred; i++)chengji *= (i + 1);
sum += chengji;
//printf("%d\n", chengji);
chengji = 1;
}
if (num == sum)printf("%d这个数符合要求\n",num);
if (num != sum)printf("%d这个数不符合要求\n",num);
}
int main() {
int a[10] = { 123,321,32,44,543,2,55,888,554,357 };
Max_array(a, 10);
Sum_array(a, 10);
PDJiec(145);
PDJiec(135);
PDJiec(45);
return 0;
}
#endif
homework
/******************************************************************************
1.《算经》中提出一个著名的“百钱买百鸡”
鸡翁一,值钱五,鸡母一,值钱三,鸡雏三,值钱一;
百钱买百鸡,问翁,母,雏各几?
提示:请不要太残忍,不要把小鸡切开。
******************************************************************************
分析:公=5元,母=三元,雏=1/3元 --->5x+3y+(1/3)z=100<=>15x+9y+z=300
且x+Y+z=100,
******************************************************************************/
#if 0
#include<stdio.h>
int main()
{
for (int i = 0; i < 20; i++)
{
for (int j = 0; j < 34; j++)
{
for (int k = 0; k < 300; k++)
{
if (i * 15 + j * 9 + k == 300 && i + j + k == 100)printf("%d,%d,%d\n", i,j,k);
}
}
}
return 0;
}
#endif
/******************************************************************************
2.春哥给你发喜糖,每个同学的糖果数目成等差数列,前4各同学得到的糖果数目之和是26,积是880。
编程求前20名学生每人得到的糖果数目。
分析:设第一个是a,第二个就是a+d,第三个就是a+2d,第四个就是a+3d;和为4a+6d.
---> a最大6.5<7;d最大8.7<9
******************************************************************************/
#if 0
#include<stdio.h>
int main()
{
int product;//前四个数的乘积
for (int a = 0; a < 7; a++)
{
for (int d = 0; d < 9; d++)
{
if (4 * a + 6 * d == 26)
{
product = a * (a + d) * (a + d + d) * (a + d + d + d);
if(880==product)printf("%d,%d\n", a, d);
}
}
}
return 0;
}
#endif
/******************************************************************************
3.哥德巴赫猜想
验证100以内的正偶数都可以分解为两个素数(质数)之和。
即验证哥德巴赫猜想对100以内(大于2)的正偶数成立的。
请使用函数封装的思想。
******************************************************************************/
#if 0
#include<stdio.h>
//判断是否为素数
int Whether_prime(int n)
{
int flag = 1;//假设是素数
for (int i = 2; i < n; i++)
if (n % i == 0)
{
flag = 0;//如果存在余数为0的就不是素数
}
return flag;
}
//哥德巴赫猜想的拆分/证明
void Goldbach_conjecture(int n)
{
for (int i = 2; i < (n/2)+1; i++)
{
if (Whether_prime(i))
{
for (int j = 2; j < n; j++)
{
if (Whether_prime(j))
{
if(i+j==n)
printf("%d是满足条件:可以分解为:%d+%d\n", n, i, j);
}
}
}
}
}
int main()
{
int n;
//scanf_s("%d", &n);
for(n=0;n<100;n+=2)
Goldbach_conjecture(n);
}
#endif
/******************************************************************************
4.在你爷爷小时候的时候,如果要将挣钱换成零钱,那么一元可以兑换成一角,两角或五角。
请问有多少种兑换方式?
******************************************************************************/
#if 0
#include<stdio.h>
int main()
{
int counter = 0;
for (int i = 0; i <= 10; i++)
for (int j = 0; j <=5; j++)
for (int k = 0; k <= 2; k++)
if (10 == i + 2 * j + 5 * k)
{
printf("可以有:%d+%d+%d\n", i, j, k);
counter++;
}
printf("共有%d种兑换方式", counter);
}
#endif
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」