1 2 Fork me on GitHub 6

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);
    通过对象的指针去访问它,首先我们要解决对象的地
址的保存问题。

image-20220523152604258

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
    *&可以约掉 抵消

image-20220523152923537

段错误:内存异常,访问内存错误。默认中止程序。致命
错误。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

posted @   JianFeng丶  阅读(28)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
点击右上角即可分享
微信分享提示