当前位置: 首页 > news >正文

C与指针。

目录

1_指针理解

1.1变量的值

1.2变量的地址

1.3指针

1.4取变量的地址

2_分析指针

2.1分析指针变量的要素

2.2根据需求定义指针变量

3_指针的使用

3.1指针对变量的读操作

3.2指针对变量的写操作

4_指针占用空间的大小与位移

4.1指针占用空间的大小

4.2指针的位移

5_指针用于传递参数

5.1值传递与地址传递

6_函数与指针

6.1函数指针

6.2指针函数

6.3区分

7_数组与指针

7.1数组的地址

7.2数组元素的指针使用

7.3一道小题目练习一下

7.4传入数组到子函数

7.5字符串与指针

7.6数组指针的使用

8_结构体与指针

8.1结构体指针

9_链表

9.1空间分配的方式

9.2空间动态分配管理函数

9.3链表理解

9.4创建链表

9.5表尾添加节点

9.6表头添加节点

9.7表中添加节点


1_指针理解

1.1变量的值

 根据需要的数据类型定义变量,内存会给定义的变量分配空间,就可以这个空间写入值了。

int a = 5;    //5就是变量的值

1.2变量的地址

定义变量时,内存会分配对应的空间,且该空间会有地址编号,变量的地址编号值为分配的空间的首字节地址编号值 。

1.3指针

指针是 一种数据类型,用指针类型定义的变量称为指针类型变量(或称指针变量、指针)

指针变量是用来存储变量地址编号值的。

1.4取变量的地址

在C中可用 ’&‘来取变量的地址,格式如下:

&变量名

int a = 5;    //5就是变量的值

int *p = &a; //定义一个指针变量p来存储a的地址

2_分析指针

2.1分析指针变量的要素

指针变量本质是一个变量,只不过这种变量存储的内容是变量的地址编号值。

分析指针变量的三要素:

  1. 变量名
  2. 指针的类型
  3. 指向的对象类型

(这些例子简单一眼就能看出来,但后面的数组指针,函数指针,结构体指针就不一定了,不过方法都是一样的)

int *p

变量名           :p

指针类型       :int *        (除了变量名以外的内容都是)

指向对象类型:int         (除了 *变量名以外的内容就是)

float *q

变量名           :q

指针类型       :float *

指向对象类型:float

 int (*p)[20]

变量名           :p

指针类型       :int(*) [20]

指向对象类型:int [20]

int **p

 变量名           :p

指针类型       :int **

指向对象类型:int *

2.2根据需求定义指针变量

格式:
指向对象类型 *变量名

先确定指针指向的变量的类型,然后再定义。

int a;      int *p;      p = &a;   //把a的地址存储到变量p中(指针变量p指向了变量a)     

float b;    float *p;     p = &b;   //把b的地址存储到变量p中(指针变量p指向了变量b)   

char c;    char *p;     p = &c;

int *m;    int **p;     p = &m;

指针变量p 存储了变量a的地址;== 也可以说指针变量p指向了变量a;

3_指针的使用

3.1指针对变量的读操作

#include<stdio.h>int main()
{int *p;                     //定义一个可以储存int类型的指针变量pint a = 10;                 //定义一个整型变量a,并给a负值10p = &a;                     //将a的地址储存到变量p中(指针变量p指向了变量a)printf("p  :%d\n",p);       //p储存了a的地址值printf("&a :%d\n",&a);      //可以看到直接打印出a的地址值与打印指针变量p的值是一样的printf("*p :%d\n",*p);      //打印出指针变量p指向的变量a的值printf("a  :%d\n",a);       //可以看到打印指针变量p指向的变量a的值与直接打印出a的值相同return 0;
}

注意:

int *p;                                在定义语句中,* 可以理解为指针变量的标志

printf("*p :%d\n",*p);         中的* 是取内容符号

3.2指针对变量的写操作

#include<stdio.h>int main()
{int *p;                         //定义一个可以储存int类型的指针变量pint a = 10;                     //定义一个整型变量a,并给a负值10p = &a;                         //将a的地址储存到变量p中(指针变量p指向了变量a)printf("赋值前\na: %d\n*p: %d\n",a,*p); //未赋值前a和*p都为10*p = 20;                        //将20赋值给*p.也就是将20赋值给aprintf("赋值后\na: %d\n*p: %d\n",a,*p); //可以看到a和*p都变成了20return 0;
}

4_指针占用空间的大小与位移

4.1指针占用空间的大小

关键字:sizeof

                功能:计算对应类型的变量占用空间的大小(字节)

                格式:sizeof(变量类型或变量名)

指针变量占用空间的大小与指向对象类型没有关系

#include<stdio.h>int main()
{printf("%d\n",sizeof(int*));printf("%d\n",sizeof(int*[20]));  //(指针数组)相当与20个int*占用的空间大小printf("%d\n",sizeof(int(*)[20]));//(数组指针)return 0;
}

指针变量占用的空间大小:

指针变量占用空间4byte(32位平台)

指针变量占用空间8byte(64位平台)

4.2指针的位移

指针位移就是指针变量增减

指针变量的位移与指向对象类型有关

!!!此段代码仅供举例,在实际操作中最好不要将不同类型的指针变量相互赋值!!!

!!!在这里因为指针变量的大小都一样,所以强制赋值没有问题!!!

#include<stdio.h>int main()
{int a = 0x12345678;          // 定义一个整数变量 a,并初始化为 0x12345678int *p;              // 定义一个 int 类型的指针 pchar *q;             // 定义一个 char 类型的指针 qp = &a;              // 将指针 p 指向变量 a 的地址q = p;               // 将指针 q 指向指针 p 所指向的地址(即 a 的地址)printf("位移前\n");printf("p: %d   q: %d\n", p, q); // 输出指针 p 和 q 的值printf("*p: 0x%x   *q: 0x%x\n", *p, *q);p += 1;              // 将指针 p 向后移动 1 个 int 类型的大小q += 1;              // 将指针 q 向后移动 1 个 char 类型的大小printf("位移后\n");printf("p: %d   q: %d\n", p, q); // 输出指针 p 和 q 的位移后的值printf("*p: 0x%x   *q: 0x%x\n", *p, *q);return 0;
}

通过结果可以看出

 

p的地址编号偏移了4,q的地址编号偏移了1。看图:

总结:指针的移位跟指向对象的数据类型有关

int *p

指针跳动一步,指针变量里存储的 地址编号就偏移4   地址编号+4

char *p

指针跳动一步,指针变量里存储的 地址编号就偏移1   地址编号+1  

short *p

指针跳动一步,指针变量里存储的 地址编号就偏移2   地址编号+2

double *p

指针跳动一步,指针变量里存储的 地址编号就偏移8   地址编号+8


补充:(指针位移的数组应用的很广泛,因为数组元素的地址是连续的,在其他变量的用处实际不大)

p+1; //p储存的地址不变(p = p + 1;//这样p储存的地址才会改变)

p++;//p储存的地址改变


5_指针用于传递参数

5.1值传递与地址传递

值传递是将实参的值传递给函数的参数,在调用函数时,会对实参的值拷贝一份副本,程序只会在函数内部对形参进行操作,不会对原始变量(实参)进行修改。

#include<stdio.h>// 声明函数 mm,接受两个参数:一个 int 类型和一个 char 类型
void mm(int a, char c);int main(void)
{int x = 10; char y = 'A'; mm(x, y); // 调用 mm 函数,传递 x 和 y 的值(值传递)// 打印 x 的值,由于值传递,x 的值在 mm 函数中没有变化,仍然是 10printf("x:%d\n", x); // 打印 y 的值,由于值传递,y 的值在 mm 函数中没有变化,仍然是 'A'printf("y:%c\n", y);return 0;  // 返回 0,表示程序正常结束
}// 定义 mm 函数,接受两个参数:一个 int 类型的 a 和一个 char 类型的 c
void mm(int a, char c)
{// 在函数内部,a 被修改为原来 a 的值加 1,即 10 + 1 = 11a = a + 1;  // 在函数内部,c 被修改为原来 c 的值加 1,即 'A' 的 ASCII 值为 65,加 1 后变为 66,对应字符 'B'c = c + 1;// 打印修改后的 a 和 c 的值printf("a:%d\n", a);  // 输出 11,因为 a 被修改为 11printf("c:%c\n", c);  // 输出 'B',因为 c 被修改为 'B'
}

地址传递是将实参的地址(指针)传递给参数。在这种方式,函数的参数实际上指向了实参的地址,在调用函数时,会对原始变量(实参)进行操作。

#include<stdio.h>
void mm(int *a, char *c);int main(void)
{int x = 10;char y = 'A';mm(&x, &y);  // 传递变量的地址printf("x: %d\n", x);  // 这里的 x 会被修改为 11printf("y: %c\n", y);  // 这里的 y 会被修改为 'B'return 0;
}void mm(int *a, char *c)
{*a = *a + 1;  // 修改 a 指针指向的值*c = *c + 1;  // 修改 c 指针指向的值printf("a: %d\n", *a);  // 11printf("c: %c\n", *c);  // 'B'
}

地址传递使用场景:

  1. 想要在函数中改变实参的值。
  2. 想要获取子函数中的数据(特别是想要多个数据的时候)。ex:

    子函数中寻找100~999中的所有水仙花数打印

    主函数要水仙花数的个数和总和

    /*********************************************************************
    水仙花数(Narcissistic Number) 是指一个 n 位数,其每个数字的 n 次方和
    等于它本身。
    例如,三位数的水仙花数是指,某个三位数的每个数字的立方和等于这个数本身。
    **********************************************************************/
    #include<stdio.h>
    int sxh(int *s, int *c);int main(void)
    {int sum = 0,cont = 0;sxh(&sum,&cont);printf("水仙花数的和为:%d\n",sum);printf("水仙花数的个数:%d\n",cont);return 0;
    }int sxh(int *s, int *c)
    {int i,ge,shi,bai;printf("水仙花数有:\n");for(i = 100;i <= 999;i++){ge  = (i / 1)   % 10;shi = (i / 10)  % 10;bai = (i / 100) % 10;if(ge*ge*ge + shi*shi*shi + bai*bai*bai == i){printf("%d\n",i);*s += i;(*c)++;}}return 0;
    }
    

  3. 需要传递一个数组到子函数中。(看数组与指针部分)

6_函数与指针

6.1函数指针

指向对象类型是函数的指针叫函数指针,本质是指针。

作用:储存函数的地址变化值(函数的地址编号可以用函数名表示)

int (*f)(char a);   

中间(*f)的括号必须加,不加就变成了指针函数,指针函数本质是函数。(后面会区分)

变量名           :f

指针类型       :int (*) (char a)       (除了变量名以外的内容都是)

指向对象类型:int (char a)       (除了 *变量名以外的内容就是)

作用: 存一个函数的地址,该函数的返回值为int类型且有一个char类型参数。

#include<stdio.h>int mm(char a);
int main(void)
{printf("int(*)(char a)类型的指针占用空间的大小为%dbyte\n",sizeof(int(*)(char a)));int(*f)(char a);  //定义一个函数指针f = mm;           //将函数的地址赋值给指针变量f//通过函数名调用函数int a = mm('A');printf("'A'的ASCII值为:%d\n",a);//当通过函数指针调用int b = f('B');printf("'B'的ASCII值为:%d\n",b);//通过解引用函数指针调用int c = (*f)('C');printf("'C'的ASCII值为:%d\n",c);return 0;
}int mm(char a)
{printf("进入int (char a)类型的函数\n");printf("函数的功能为打印字符%c并返回其ASCII值\n",a);return a;
}

多举2个例子:

int (*p)(void);

变量名           :p

指针类型       :int (*) (void)       (除了变量名以外的内容都是)

指向对象类型:int (void)       (除了 *变量名以外的内容就是)

作用: 存一个函数的地址,该函数的返回值为int类型且没有参数。

void (*q)(int a,char *b);

变量名           :q

指针类型       :void (*) (int a,char *b)       (除了变量名以外的内容都是)

指向对象类型:void (int a,char *b)         (除了 *变量名以外的内容就是)

作用: 存一个函数的地址,该函数无返回值为且有一个int类型和char *类型参数。

函数指针的使用场景:
将一个函数作为另一个函数的参数。

ex:通过接口函数启动功能函数。

#include<stdio.h>void fun(void(*q)(void)); // 声明接口函数
void f1(void); // 声明功能函数1
void f2(void); // 声明功能函数2
void f3(void); // 声明功能函数3
void f4(void); // 声明功能函数4
void f5(void); // 声明功能函数5int main(void)
{fun(f1); // 通过接口函数调用功能函数fun(f2);fun(f3);fun(f4);fun(f5);return 0;
}// 接口函数:接收一个函数指针并调用对应的功能函数
void fun(void(*q)(void))
{(*q)(); // 调用传入的函数
}// 功能函数1
void f1(void)
{printf("进入功能块1\n");
}// 功能函数2
void f2(void)
{printf("进入功能块2\n");
}// 功能函数3
void f3(void)
{printf("进入功能块3\n");
}// 功能函数4
void f4(void)
{printf("进入功能块4\n");
}// 功能函数5
void f5(void)
{printf("进入功能块5\n");
}

 更多接口函数例子==》C语言_接口函数

6.2指针函数

指针函数本质是一个函数,一个可以返回地址编号的函数。

int *f(void);

函数名     : f

参数         :无

返回值     :int *

作用        :  该函数的返回值是地址编号,需要定义一个指针变量接收。

指针函数的使用场景:

用于动态分配。

int *malloc(int n);

具体看后面的链表章节

6.3区分

有括号的就是函数指针,没有括号的就是指针函数(类似数组指针和指针数组)。

分析

int  (*mm)(void (*f)(float b), int a, char *m);

int  *mm(void (*f)(float b), int a, char *m);

int  *(*mm)(void (*f)(float b), int a, char *m);

int  (*mm)(void (*f)(float b), int a, char *m);

函数指针:

变量名           :mm

指针类型       :int (*)(void(*f)(float b),int a,char *m)      

指向对象类型:int (void(*f)(float b),int a,char *m)          

这是一个指针变量,指针存储函数的地址,函数的要求如下:

返回值类型        :   int   
参数                   :  int a                    //传入一个整型值

                                char * m            //传入一个字符型变量的地址

                                void(*f)(float b)  //传入一个函数的地址,函数要求如下:

                                                        返回值:        无

                                                        参数    :        float b       //传入一个浮点值

              

#include <stdio.h>// 定义一个简单的函数,接受一个 float 类型的参数
void example_function(float b) {printf("接收到的 float 值: %f\n", b);
}// 定义一个函数,符合 mm 的签名,接收一个函数指针、一个整数和一个字符串
int my_function(void (*f)(float b), int a, char *m) {printf("整数: %d, 字符串: %s\n", a, m);f(3.14);  // 调用传入的函数 freturn a * 2;
}int main() {// 定义函数指针 mm,指向 my_functionint (*mm)(void (*f)(float b), int a, char *m) = my_function;// 通过 mm 调用 my_function,并传入 example_function、整数 5 和字符串 "Hello, World!"int result = mm(example_function, 5, "Hello, World!");printf("结果: %d\n", result);return 0;
}

                               

int  *mm(void (*f)(float b), int a, char *m);

指针函数:

函数名     : mm

返回值     : int *

参数                   :  int a                    //传入一个整型值

                                char * m            //传入一个字符型变量的地址

                                void(*f)(float b)  //传入一个函数的地址,函数要求如下:

                                                        返回值:        无

                                                        参数    :        float b       //传入一个浮点值

#include <stdio.h>
#include <stdlib.h>// 这是一个符合要求的函数,接收一个 float 类型的参数,并返回 void
void example_function(float b) {printf("函数 example_function 被调用,参数为: %f\n", b);
}// mm 函数,返回一个 int* 指针
int* mm(void (*f)(float b), int a, char *m) {// 打印传入的整数和字符串printf("传入的整数 a: %d\n", a);printf("传入的字符串 m: %s\n", m);// 调用传入的函数 f,传入一个 float 参数f(3.14);// 使用 malloc 分配内存int *result = (int*)malloc(sizeof(int));if (result != NULL) {*result = a * 2;  // 计算并存储结果}return result;  // 返回指向结果的指针
}int main() {// 定义一个函数指针 f,指向 example_functionvoid (*f_ptr)(float) = example_function;// 调用 mm 函数,传入函数指针 f_ptr,整数 5 和字符串 "Hello"int *result = mm(f_ptr, 5, "Hello");// 打印 mm 函数返回的 int* 指针值和指针解引用后的值if (result != NULL) {printf("计算结果的指针地址: %p\n", (void*)result);printf("解引用后的结果: %d\n", *result);// 使用完 malloc 分配的内存后,记得释放它free(result);}return 0;
}

int  *(*mm)(void (*f)(float b), int a, char *m);

函数指针:

变量名           :mm

指针类型       :int *(*)(void(*f)(float b),int a,char *m)      

指向对象类型:int * (void(*f)(float b),int a,char *m)    

这是一个指针变量,指针存储函数的地址,函数的要求如下:

返回值类型        :   int *   
参数                   :  int a                    //传入一个整型值

                                char * m            //传入一个字符型变量的地址

                                void(*f)(float b)  //传入一个函数的地址,函数要求如下:

                                                        返回值:        无

                                                        参数    :        float b       //传入一个浮点值

#include <stdio.h>
#include <stdlib.h>// 这是一个符合要求的函数,接收一个 float 类型的参数,并返回 void
void example_function(float b) {printf("函数 example_function 被调用,参数为: %f\n", b);
}// mm 函数的实现,符合声明
int *mm(void (*f)(float b), int a, char *m) {// 打印传入的整数和字符串printf("传入的整数 a: %d\n", a);printf("传入的字符串 m: %s\n", m);// 调用传入的函数 f,传入一个 float 参数f(3.14);// 计算 a * 2,并返回其地址int *result = (int *)malloc(sizeof(int));  // 动态分配内存if (result != NULL) {*result = a * 2;}return result;
}int main() {// 定义一个函数指针 f,指向 example_functionvoid (*f_ptr)(float) = example_function;// 定义一个函数指针 mm,指向 mm 函数int *(*mm_ptr)(void (*f)(float b), int a, char *m) = mm;// 调用 mm 函数,传入函数指针 f_ptr,整数 5 和字符串 "Hello"int *result = mm_ptr(f_ptr, 5, "Hello");// 打印 mm 函数返回的 int* 指针值和指针解引用后的值if (result != NULL) {printf("计算结果的指针地址: %p\n", (void*)result);printf("解引用后的结果: %d\n", *result);// 使用完 malloc 分配的内存后,记得释放它free(result);}return 0;
}

7_数组与指针

7.1数组的地址

!!!数组的首元素地址属性和数组的地址属性不一样!!!

数组的首元素地址:
        0号元素的地址属性表示首个元素的地址

        数组名代表数组首元素地址(或  &a[0])

        偏移:a+1;偏移一个数组元素的长度地址

数组的地址:

        数组的地址的属性表示整个数组的地址:&a

        数组的首元素地址编号值和数组的地址编号值一样,但偏移量不一样

        偏移:&a+1;偏移一个数组的长度地址,即 偏移量 == 元素个数 * 元素类型大小

7.2数组元素的指针使用

由于数组名可以代码数组首元素地址,所以通过:

        (数组名+i)的形式表示数组的i号元素的地址

      *(数组名+i)的形式来获取数组的i号元素的值

注意:

数组名只能代表数组首元素的地址,不能代表其他元素的地址

所以用数组名访问的时候,不能用 数组名++ 的形式

也可以通过指针变量来访问数组的元素:

通过指针操作数组中的元素,要先定义一个可以指向数组元素的指针,

然后,

通过p++的形式访问某个元素的地址      //指针变量p存储的地址是变化的

通过*p的形式访问某个元素的内容       //要注意指针某一时刻存了谁的地址

也可以

通过p+i的形式访问某个元素的地址     //指针变量p存的地址不变,一直是首元素地址

通过*(p+i)的形式访问某个元素的内容  

7.3一道小题目练习一下

如果定义:

char a,b,c,d,e,f,x,y;
    char niu[6];
    niu[0] = 3;
    niu[1] = 6;
    niu[2] = 10;
    niu[3] = 21;
    niu[4] = 40;
    niu[5] = 50;
    char *sp = niu;

求:

a=*sp;

b=*sp+1;

c=*sp++;

d=*sp;

e=*(sp+1);

f=*sp;

x = sizeof(niu[6]);
y = sizeof(niu);
z = sizeof(char[6]);
k = sizeof(sp);

的结果(注意假设程序从上往下执行):

a=          b=            c=          d=  

e=         f=            x=          y=  

z=        k=

#include<stdio.h>int main(void)
{char a,b,c,d,e,f,x,y,z,k;char niu[6];niu[0] = 3;niu[1] = 6;niu[2] = 10;niu[3] = 21;niu[4] = 40;niu[5] = 50;char *sp = niu;a = *sp;            //sp指向niu[0]    a = niu[0] = 3b = *sp+1;          //sp指向niu[0]    b = niu[0]+1 = 4c = *sp++;          //sp指向niu[0]    c = niu[0] = 3  (*sp++ == *(sp++)    sp++运算符是先赋值后自增,所以本次赋值在自增前)d = *sp;            //sp指向niu[1]    d = niu[1] = 6  (上一行代码进行了自增)e = *(sp+1);        //sp指向niu[1],但(sp+1)的地址为niu[2]  e = niu[2] = 10f = *sp;            //sp指向niu[1]    f = niu[1] = 6x = sizeof(niu[6]);y = sizeof(niu);z = sizeof(char[6]);k = sizeof(sp);printf("a = %d\n",a);printf("b = %d\n",b);printf("c = %d\n",c);printf("d = %d\n",d);printf("e = %d\n",e);printf("f = %d\n",f);printf("x = %d\n",x);printf("y = %d\n",y);printf("z = %d\n",z);printf("k = %d\n",k);return 0;
}

思考:如果把代码中所以char改为int,指针的偏移有什么变换?(看4.2指针的位移

7.4传入数组到子函数

数组的空间特点:元素空间分配连续

基于数组的空间特点,我们可以吧数组的首元素地址传给子函数(子函数定义一个指针变量的形参来接收数组首元素地址),子函数就可以通过地址偏移的方式访问所以数组元素。

1.        用户在主函数中定义一个数组,往数组中输入10个数据

           写一个子函数,统计用户输入的数据非负数的个数打印

           并且求非负数的和返回给主函数在主函数中打印。

#include <stdio.h>int Sub(int *p, int n);int main()
{int a[10];  // 存储用户输入的 10 个数int value;  // 存储非负数的和printf("请输入10个数:\n");// 输入 10 个整数for (int i = 0; i < 10; i++){scanf("%d", &a[i]);}// 计算并返回非负数的和value = Sub(a, 10);// 输出非负数的和printf("非负数的和为:%d", value);return 0;
}// 计算非负数的和
int Sub(int *p, int n)
{int sum = 0;  // 初始化和为 0// 输出非负数printf("非负数有:\n");// 遍历数组中的所有元素for (int i = 0; i < n; i++)  // 使用传入的数组大小 n{if (*(p + i) >= 0)  // 判断当前元素是否为非负数{printf("%d\n", *(p + i));  // 打印当前的非负数sum += *(p + i);  // 将非负数累加到 sum}}return sum;  // 返回非负数的和
}

 2.      用户在主函数中输入数组后

          在子函数中去掉最大最小求平均值

          返回平均值在主函数中打印

插个知识点:

冒泡排序

作用:将数组中的数据进行从大到小或者从小到大排序

原理:

int a[6] = { 68 , 100 , 90 , 34 , 200 , 60};

说明:轮数循环从1开始,每轮比较的次数 j == 数据个数 n - 轮数 i

           每轮比较的次数从0开始,因为要用这个循环变量当数组的下标。

#include <stdio.h>float Average(int *p, int n);int main()
{int a[10];  float average;  printf("请输入10个数:\n");for (int i = 0; i < 10; i++){scanf("%d", &a[i]);  /}average = Average(a, 10);printf("去掉最大最小后的平均值为%.2f\n", average);return 0;  
}// 计算去掉最大最小数后的平均值的函数定义
float Average(int *p, int n)
{int temp, sum = 0;  // 临时变量 temp 用于交换,sum 初始化为 0,用来累加去掉最大最小数后的和float aver;  // 存储计算出的平均值// 冒泡排序,按升序排列数组for (int i = 1; i < n; i++)  // 外层循环:每次将最大的数移动到末尾{for (int j = 0; j < n - i; j++)  // 内层循环:比较相邻的两个数,较大的数交换到后面{if (p[j] > p[j + 1])  // 如果当前数比下一个数大,则交换{temp = p[j];  // 保存当前数p[j] = p[j + 1];  // 将下一个数赋值给当前数p[j + 1] = temp;  // 将保存的当前数赋值给下一个数}}}// 去掉最大值和最小值后,计算剩余部分的和for (int k = 1; k < n - 1; k++)  // 从第二个元素开始,到倒数第二个元素{sum += p[k];  // 累加每个元素到 sum}// 计算去掉最大最小数后的平均值aver = (float)sum / (n - 2);  // 计算平均值,确保进行浮点数运算return aver;  // 返回计算出的平均值
}

在上面2段代码中,关于在子函数调用数组我用了2中不同的形式:

用指针的形式:*(p+i)

用数组的形式:p[i]

虽然形式参数的类型是指针,但这两种方式是等价的,*(p + i) 等价于 p[i],

想想在用数组的时候是不是也用过指针的形式调用数组。


7.5字符串与指针

字符串其实是数组,用指针操作字符串其实就是用指针操作数组,在这不讲太多,可以看下这C_字符串其实就是字符数组

也可以看看下一节关于数组指针操作字符的二维数组的部分。

7.6数组指针的使用

区分:

数组指针:      char (*p)[10];        这是一个指针,可以存一个char [10]类型的数组的地址编号

指针数组:      int *p[10];           这是一个数组,可以存10个int * 类型的指针变量

有括号为指针,无括号为数组(跟函数指针和指针函数类似)

数组指针存了数组的地址编号,意味着整体操作数组,这多很多类型的数组没有操作价值,但可以操作字符数组,也就是操作字符串,一般用在字符的二维数组。

接下来讲讲数组指针操作字符的二维数组

①定义一个数组指针

char (*p)[10];

变量名           :p

指针类型       :char *[10]

指向对象类型:char [10]

②明确指向

假如有一个字符的二维数组:

char a[10][10];

p = a;

③使用

p++;        //指针指向改变

p+1;        //指针指向不变

练习:

主函数有一个指令包,指令包里有10个字符串指令,

用户再输入一个字符串指令,

写一个子函数,判断用户输入的字符串指令是否在指令包中,

如果在指令包中返回1,不在指令包中返回0。

分析:

                10个指令存在一个二维数组中

        主函数:

                指令包二维数组

                用户输入指令字符串

        子函数:

                参数:char (*p)[10], char *m

                返回值: int

        说明:

                和二维数组中的每个字符串进行对比,对比成功返回1,失败返回0

#include <stdio.h>
#include <string.h>int Judge(char (*p)[10],char *i);int main()
{int judge;char package[10][10] = {"123456","abcd","98765","55555","4444","333","22","liao","jia","tong"};char ins[10];printf("请输入指令:");scanf("%s",ins);judge = Judge(package,ins);if(judge == 1){printf("输入正确\n");}else if(judge == 0){printf("输入错误\n");}return 0;
}/*******************************************************
函数名     : Judge
函数功能   : 判断指令是否在指令包中
函数参数   : char (*p)[10], char *i
函数返回值 : int
函数描述   : 如果字符串i在字符串数组p中,则返回1,不在则返回0
*******************************************************/int Judge(char (*p)[10], char *i)
{for (int j = 0; j < 10; j++) {if (strcmp(p[j], i) == 0) {  // 如果匹配return 1;  // 返回 1 表示输入正确}}return 0;  // 如果没有匹配,返回 0
}//int Judge(char (*p)[10],char *i)
//{
//    int j = 0;
//    while(*(p+j) != NULL)
//    {
//        if(strcmp((char *)(p+j),i)) == 0)
//        {
//            return 1;
//        }
//        j++;
//    }
//    return 0;
//}

8_结构体与指针

关于结构体的基础知识在这里不讲,有需要可以看这==》C_结构体

8.1结构体指针

假如已经声明了一个结构体:

typedef struct book
{
    char title[50];     // 书名
    char author[50];    // 作者
    char id[50];        // 书籍编号
    float pop;          // 热度
    int stock;          // 库存
    float price;        // 价格
} BOK;  // 结构体类型的别名 BOK

 定义一个结构体指针:

BOK *f;

变量名           :f

指针类型       :BOK *

指向对象类型:BOK

使用:

        明确指向:

BOK bk1;

f = bk1;

        格式:

这个符号:              ->                是结构体指针特有的,是结构体元素到结构体具体成员的指向。

        结构体指针变量名->成员变量名;

f->title        f->price

#include <stdio.h>
#include <string.h>
typedef struct book
{char title[50];     // 书名char author[50];    // 作者char id[50];        // 书籍编号float pop;          // 热度int stock;          // 库存float price;        // 价格
} BOK;  // 结构体类型的别名 BOKint main()
{BOK bk1 ={"C Programming",    // title"Dennis Ritchie",   // author"001",              // id4.5,                // pop10,                 // stock39.99               // price};BOK *f;f = &bk1;f -> price = 29.99;strcpy(f -> title , "C语言");printf("Book 1: %s by %s\n ID: %s\n Popularity: %.2f\n Stock: %d\n Price: %.2f\n",f->title, f->author, f->id, f->pop, f->stock, f->price);return 0;
}

9_链表

9.1空间分配的方式

自动分配:

        系统根据用户定义的变量来分配空间,分配的位置为栈区。

        访问可以通过变量访问,也可以通过地址访问。

动态分配:

        用户通过动态分配函数人为申请空间,人为释放空间申请到的空间在堆区。

        分配到的空间没有名字,只能通过地址访问。

9.2空间动态分配管理函数

malloc函数:

函数原型:

#include <stdlib.h>        //头文件

void *malloc(unsigned int size);        //函数

函数名             : malloc

函数参数          :unsigned int size

函数返回值      :void *

说明                 :此函数有1个整型参数size,这个参数是用来请求分配的内存块大小的,

                            单位是字节(byte),此函数会返回一个地址编号,所在地址中存的数据类型                                  不确定。

功能                  : 在堆区申请一块size字节的空间

                           会把申请到的空间的地址的首字节编号返回,如果分配失败则返回NULL

                           此空间没有类型(可以强转成任何地址类型)

注意                  :申请空间是为了存数据

                             申请到的空间要类型转换

                              返回的是申请到的空间的首字节地址

#include <stdio.h>
#include <stdlib.h>int main() {// 请求分配一个整数大小的内存int* ptr = (int*)malloc(sizeof(int));if (ptr == NULL) {printf("内存分配失败\n");return 1;}// 使用分配的内存*ptr = 10;printf("存储的值是: %d\n", *ptr);// 释放分配的内存free(ptr);return 0;
}

free函数:

函数原型:

#include <stdlib.h>        //头文件

void free(void *prt);        //函数

函数名             :free

函数参数          :void *prt

函数返回值      :无

功能                  : 释放指针指向的堆区空间的内容

                           权限自由

注意                  :释放的是空间里的内容,不是空间

                             调用后,*prt的值发生了变化,因为这块空间里的内容已经释放掉了,但prt还是

                              指向这块空间的首地址,不太好,所以最好:

                              prt = NULL;    //避免”野指针“

                              

#include <stdio.h>
#include <stdlib.h>int main() {// 动态分配内存int* ptr = (int*)malloc(sizeof(int));if (ptr == NULL) {printf("内存分配失败\n");return 1;}// 使用分配的内存*ptr = 42;printf("存储的值是: %d\n", *ptr);// 释放分配的内存free(ptr);// 注意:释放后,不要再使用该指针ptr = NULL;  // 设为NULL,避免悬空指针问题return 0;
}

calloc函数:

#include <stdlib.h>        //头文件

void *calloc(unsigned int num,unsigned int size);        //函数

函数名             : calloc

函数参数          :unsigned int num,unsigned int size

函数返回值      :void *

说明                 :此函数有2个整型参数 num和size,num是要申请的内存块数,size是用来请求分                                配的每块内存块大小的,单位是字节(byte)。

功能                  : 在堆区申请num块size字节的空间

                           会把申请到的空间的地址的首字节编号返回,如果分配失败则返回NULL

                           此空间没有类型(可以强转成任何地址类型)

#include <stdio.h>
#include <stdlib.h>int main() {// 分配并初始化 10 个整数大小的内存块int* ptr = (int*)calloc(10, sizeof(int));if (ptr == NULL) {printf("内存分配失败\n");return 1;}// 打印每个元素的值(应为 0,因为 calloc 初始化了内存)for (int i = 0; i < 10; i++) {printf("ptr[%d] = %d\n", i, ptr[i]);}// 释放分配的内存free(ptr);return 0;
}

     callocmalloc的区别主要是以下两点:         

1.calloc是申请num块字节数为size的内存空间。

   malloc是申请1块字节数为size的内存空间

   calloc(6,4); 等价于malloc(24);        //在堆区申请24字节的空间

2.malloc不会初始化申请到的空间,而calloc会初始化申请到的空间。

9.3链表理解

还没写b( ̄▽ ̄)d 

9.4创建链表

9.5表尾添加节点

9.6表头添加节点

9.7表中添加节点

相关文章:

C与指针。

目录 1_指针理解 1.1变量的值 1.2变量的地址 1.3指针 1.4取变量的地址 2_分析指针 2.1分析指针变量的要素 2.2根据需求定义指针变量 3_指针的使用 3.1指针对变量的读操作 3.2指针对变量的写操作 4_指针占用空间的大小与位移 4.1指针占用空间的大小 4.2指针的位移…...

使用 Selenium 和 Python 爬取腾讯新闻:从基础到实践

使用 Selenium 和 Python 爬取腾讯新闻&#xff1a;从基础到实践 在这篇博客中&#xff0c;我们将介绍如何利用 Selenium 和 Python 爬取腾讯新闻的内容&#xff0c;并将结果保存到 CSV 文件中。本教程包含以下内容&#xff1a; 项目简介依赖安装实现功能的代码实现中的关键技…...

ElasticSearch的下载和基本使用(通过apifox)

1.概述 一个开源的高扩展的分布式全文检索引擎&#xff0c;近乎实时的存储&#xff0c;检索数据 2.安装路径 Elasticsearch 7.8.0 | Elastic 安装后启动elasticsearch-7.8.0\bin里的elasticsearch.bat文件&#xff0c; 启动后就可以访问本地的es库http://localhost:9200/ …...

处理HTTP请求的两种常见方式:多个处理器(Handler)、多个处理函数(HandleFunc),两者有什么区别

一、多个处理器(Handler)、多个处理函数(HandleFunc)&#xff0c;两者的区别&#xff1a; 在Go语言中&#xff0c;处理HTTP请求的两种常见方式是使用http.Handler接口和http.HandleFunc函数。它们都用于定义如何处理HTTP请求&#xff0c;但它们之间有一些关键的区别&#xff1…...

在oracle下载jdk显示400 Bad Request Request Header Or Cookie Too Large

下载JDK17&#xff0c;官网地址&#xff1a;【https://www.oracle.com/cn/java/technologies/downloads/#jdk17-windows】 问题&#xff1a; 出现 400 Bad Request: Request Header Or Cookie Too Large 错误&#xff0c;通常是由于浏览器存储的 Cookies 或请求头过大所导致的…...

机器学习与深度学习-2-Softmax回归从零开始实现

机器学习与深度学习-2-Softmax回归从零开始实现 1 前言 内容来源于沐神的《动手学习深度学习》课程&#xff0c;本篇博客对于Softmax回归从零开始实现进行重述&#xff0c;依旧是根据Python编程的PEP8规范&#xff0c;将沐神的template代码进行简单的修改。近期有点懒散哈哈哈…...

Vue3之弹窗

文章目录 第一步、引入JS第二步、弹框 在前端开发语言Vue3&#xff0c;在管理端如何进行弹窗&#xff1f;下面根据API实现效果。 Element API文档&#xff1a; Element-plus文档 搭建环境可参考博客【 初探Vue3环境搭建与nvm使用】 第一步、引入JS <script lang"ts&…...

计算机的错误计算(一百七十一)

摘要 探讨 MATLAB 中秦九韶&#xff08;Horner&#xff09;多项式的错误计算。 例1. 用秦九韶&#xff08;Horner&#xff09;算法计算&#xff08;一百零七&#xff09;例1中多项式 直接贴图吧&#xff1a; 这样&#xff0c;MATLAB 给出的仍然是错误结果&#xff0c;因为准…...

利用Python爬虫精准获取淘宝商品详情的深度解析

在数字化时代&#xff0c;数据的价值日益凸显&#xff0c;尤其是在电子商务领域。淘宝作为中国最大的电商平台之一&#xff0c;拥有海量的商品数据&#xff0c;对于研究市场趋势、分析消费者行为等具有重要意义。本文将详细介绍如何使用Python编写爬虫程序&#xff0c;精准获取…...

_C#_串口助手_字符串拼接缺失问题(未知原理)

最近使用WPF开发串口助手时&#xff0c;遇到一个很奇怪的问题&#xff0c;无论是主线程、异步还是多线程&#xff0c;当串口接收速度达到0.016s一次以上&#xff0c;就会发生字符串缺失问题并且很卡。而0.016s就一切如常&#xff0c;仿佛0.015s与0.016s是天堑之隔。 同一份代码…...

volcano k8s 部署

下载volcano-development文件 官网 https://volcano.sh/zh/docs/installation/volcano-development.yaml wget https://raw.githubusercontent.com/volcano-sh/volcano/master/installer/volcano-development.yaml部署volcano 查下需要下载的镜像 grep vc- volcano-develo…...

Linux---对时/定时服务

文章目录 目录 文章目录 前言 一.对时服务 服务端配置 客户端配置 二.定时服务 单次定时任务 循环定时任务 前言 在当今信息化高速发展的时代&#xff0c;时间的准确性和任务的定时执行对于各种系统和服务来说至关重要。Linux操作系统&#xff0c;凭借其强大的功能和灵活的…...

13 设计模式之外观模式(家庭影院案例)

一、什么是外观模式&#xff1f; 1.定义 在日常生活中&#xff0c;许多人喜欢通过遥控器来控制家中的电视、音响、DVD 播放器等设备。虽然这些设备各自独立工作&#xff0c;但遥控器提供了一个简洁的界面&#xff0c;让用户可以轻松地操作多个设备。而这一设计理念正是 外观模…...

spring boot整合ArtemisMQ进行手动消息确认

1、SpringBoot整合ArtemisMQ进行手动消息确认使用的是&#xff1a; factory.setSessionTransacted(false); factory.setSessionAcknowledgeMode(ActiveMQJMSConstants.INDIVIDUAL_ACKNOWLEDGE); 2、SpringBoot整合ActiveMQ进行手动消息确认使用的是&#xff1a; factory.setSe…...

dpwwn02靶场

靶机下载地址&#xff1a;https://download.vulnhub.com/dpwwn/dpwwn-02.zip 信息收集 ip add 查看kali Linux虚拟机的IP为&#xff1a;10.10.10.128 https://vulnhub.com/entry/dpwwn-2,343/中查看靶机的信息&#xff0c;IP固定为10.10.10.10 所以kali Linux添加仅主机网卡…...

展示和添加篮球队信息--laravel与elementplus

之前使用laravel与inertia来做过一样的功能,感觉不满意,因此再结合elementplus重做一遍,先展示下重做后的效果。重写后的代码相比之下比较优雅。 球队首页 球队添加页 球员首页 很明显的改变,我新增了侧栏菜单来控制局部模块(这里是指NBABasketba…...

K8S疑难概念理解——Pod,应该以哪种Kind来部署应用,为什么不直接Pod这种kind?

文章目录 一、Pod概念深度理解&#xff0c;为什么一般不直接以kindPod资源类型来部署应用?二、究竟应该以哪种资源类型来部署应用 一、Pod概念深度理解&#xff0c;为什么一般不直接以kindPod资源类型来部署应用? Pod是Kubernetes中的最小部署单元&#xff0c;可以包含一个或…...

centos7怎么安装keepalive+nginx

在CentOS 7上安装Keepalived和Nginx&#xff0c;可以按照以下步骤进行&#xff1a; 安装Nginx 添加Nginx到Yum源&#xff1a; rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm安装Nginx&#xff1a; yum install -y ng…...

DevOps工程技术价值流:Jenkins驱动的持续集成与交付实践

一、Jenkins系统概述 Jenkins&#xff1a;开源CI/CD引擎的佼佼者 Jenkins&#xff0c;作为一款基于Java的开源持续集成&#xff08;CI&#xff09;与持续交付&#xff08;CD&#xff09;系统&#xff0c;凭借其强大的插件生态系统&#xff0c;成为DevOps实践中不可或缺的核心…...

el-select 修改样式

这样漂亮的页面&#xff0c;搭配的却是一个白色风格的下拉框 &#xff0c;这也过于刺眼。。。 调整后样式为&#xff1a; 灯红酒绿总有人看着眼杂&#xff0c;但将风格统一终究是上上选择。下面来处理这个问题。 分为两部分。 第一部分&#xff1a;是修改触发框的样式 第二部…...

文本内容处理命令和正则表达式

文本内容处理命令 grep 用来过滤文本内容&#xff0c;以匹配要查询的结果。 -m 数字 匹配几次后停止&#xff1a; grep -m 1 /root/etc/passwd #查找包含root的行 -v 取反 -i 忽略字符的大小写&#xff0c;默认的&#xff0c;可以不加 -n 显示匹配的行号 -c 统计匹配的…...

【PlantUML系列】类图(一)

目录 一、类 二、接口 三、抽象类 四、泛型类 五、类之间的关系 六、添加注释 七、包图 八、皮肤参数 一、类 使用class关键字定义类&#xff0c;类名后跟大括号&#xff0c;声明类的属性和方法。 属性&#xff1a;格式为{visibility} attributeName : AttributeType…...

【Leetcode Top 100】21. 合并两个有序链表

问题背景 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 数据约束 两个链表的节点数目范围是 [ 0 , 50 ] [0, 50] [0,50] − 100 ≤ N o d e . v a l ≤ 100 -100 \le Node.val \le 100 −100≤Node.val≤100 l 1 l_1 …...

【真正离线安装】Adobe Flash Player 32.0.0.156 插件离线安装包下载(无需联网安装)

网上很多人声称并提供的flash离线安装包是需要联网才能安装成功的&#xff0c;其实就是在线安装包&#xff0c;而这里提供的是真正的离线安装包&#xff0c;无需联网即可安装成功。 点击下面地址下载离线安装包&#xff1a; Adobe Flash Player 32.0.0.156 for IE Adobe Fla…...

UG NX二次开发(C#)-如何进行NX多版本的编译

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 1、前言2、以删除对象为例3、解决方案1、前言 由于UG NX的版本不同,新版本与旧版本开发过程中,如果是在一个工程中,其会出现低版本不能编译高版本NX的问题,这是因为高版本会引入新的函数,或者…...

Spark优化--开发调优、资源调优、数据倾斜调优和shuffle调优等

针对Spark优化&#xff0c;我们可以从多个角度进行&#xff0c;包括开发调优、资源调优、数据倾斜调优和shuffle调优等。以下是一些具体的优化方法&#xff1a; 1. 开发调优 避免创建重复的RDD&#xff1a;对于同一份数据&#xff0c;只应该创建一个RDD&#xff0c;避免创建多…...

911事件反思:灾难通信和ddos之间的取舍

流量分析与监控 建立基线流量模型&#xff1a;在正常情况下监控和记录网络流量&#xff0c;建立正常流量的基线。这样&#xff0c;当突发请求发生时&#xff0c;可以更容易地识别出流量的异常变化。 实时流量监控&#xff1a;使用流量分析工具实时监控网络流量&#xff0c;快速…...

网络安全之IP伪造

眼下非常多站点的涉及存在一些安全漏洞&#xff0c;黑客easy使用ip伪造、session劫持、xss攻击、session注入等手段危害站点安全。在纪录片《互联网之子》&#xff08;建议搞IT的都要看下&#xff09;中。亚伦斯沃茨&#xff08;真实人物&#xff0c;神一般的存在&#xff09;涉…...

算法笔记:力扣24. 两两交换链表中的节点

思路&#xff1a; 本题最简单的就是通过递归的形式去实现 class Solution {public ListNode swapPairs(ListNode head) {if(head null || head.next null){return head;}ListNode next head.next;head.next swapPairs(next.next);next.next head;return next;} } 对于链…...

Shell脚本小练习

学习了这么长时间Shell脚本&#xff0c;总得来一次小小的练习吧&#xff0c;那么请看下文&#xff01; 1.用Shell写一个小计算器。 通过read命令获取用户输入的表达式&#xff0c;表达式的格式设定为操作数1 运算符 操作数2&#xff0c;例如53&#xff0c;然后利用设计的脚本…...

Fastify装饰器:增强你的路由处理功能加入日志

Fastify以其出色的性能和扩展性脱颖而出。装饰器是Fastify提供的一个强大功能&#xff0c;它允许开发者在不修改核心代码的情况下&#xff0c;向请求&#xff08;Request&#xff09;和响应&#xff08;Response&#xff09;对象添加自定义属性和方法。本文将通过一个简单的示例…...

node.js基础学习-url模块-url地址处理(二)

前言 前面我们创建了一个HTTP服务器&#xff0c;如果只是简单的http://localhost:3000/about这种链接我们是可以处理的&#xff0c;但是实际运用中一般链接都会带参数&#xff0c;这样的话如果我们只是简单的判断链接来分配数据&#xff0c;就会报404找不到链接。为了解决这个问…...

Vue如何加载十万条数据

加载十万条数据到 Vue 应用中是一个相对复杂的问题&#xff0c;主要因为渲染大量数据可能会导致性能瓶颈&#xff0c;尤其是在前端性能较低的设备上。为了确保加载大量数据时&#xff0c;页面不会卡顿或崩溃&#xff0c;我们通常采取一些优化手段&#xff0c;以下是几种常用的方…...

重生之我在异世界学编程之C语言:二维数组篇

大家好&#xff0c;这里是小编的博客频道 小编的博客&#xff1a;就爱学编程 很高兴在CSDN这个大家庭与大家相识&#xff0c;希望能在这里与大家共同进步&#xff0c;共同收获更好的自己&#xff01;&#xff01;&#xff01; 本文目录 引言正文一 二维数组的创建1. 二维数组的…...

linux——进程间通信及管道的应用场景

linux进程的控制-CSDN博客 liunx——进程间通信&#xff08;管道通信&#xff09;-CSDN博客 文章目录 文章目录 前言 二、管道的应用 1.创建子进程 1、描述&#xff1a; 2.创建进程及管理 3、子进程接受任务 4、控制子进程 总结 前言 上篇博客我们学习了进程间通信&…...

深度学习基础3

目录 1.过拟合与欠拟合 1.1 过拟合 1.2 欠拟合 1.2 解决欠拟合 1.2.1 L2正则化 1.2.2 L1正则化 1.2.3 Dropout 1.2.4 简化模型 1.2.5 数据增强 1.2.6 早停 1.2.7 模型集成 1.2.8 交叉验证 2.批量标准化 2.1 实现过程 2.1.1 计算均值和方差 2.1.2 标准化 2.1.3…...

靶机dpwwn-01

靶机下载地址&#xff1a;https://download.vulnhub.com/dpwwn/dpwwn-01.zip 信息收集 扫描靶机的IP地址 arp-scan -l 获得靶机的IP地址&#xff1a;192.168.200.130 查看靶机的服务类型&#xff0c;端口信息 nmap -sS -sV -T4 -A -p- 192.168.200.130 开启了22&#xf…...

Python毕业设计选题:基于django+vue的智慧社区可视化平台的设计与实现+spider

开发语言&#xff1a;Python框架&#xff1a;djangoPython版本&#xff1a;python3.7.7数据库&#xff1a;mysql 5.7数据库工具&#xff1a;Navicat11开发软件&#xff1a;PyCharm 系统展示 管理员登录 管理员功能界面 养老机构管理 业主管理 社区安防管理 社区设施管理 车位…...

大语言模型微调与 XTuner 微调实战

1 大语言模型微调 1.1 什么是微调 大语言模型微调&#xff08;Fine-tuning of Large Language Models&#xff09;是指在预训练的大型语言模型基础上&#xff0c;使用特定任务的数据进一步训练模型&#xff0c;以使其更好地适应和执行特定任务的过程&#xff0c;用于使LLM&am…...

数据结构-查找(四)总结与对比

查找算法总结 文章目录 查找算法总结一、查找的基本概念二、顺序查找法适用场景 三、分块查找法适用场景 四、折半查找法&#xff08;Binary Search&#xff09;适用场景 五、树型查找1. 二叉搜索树&#xff08;BST&#xff09;2. 平衡二叉树&#xff08;AVL&#xff09;3. 红黑…...

c++总复习

一、什么是 C 中的函数对象&#xff1f;它有什么特点&#xff1f; 在 C 中&#xff0c;函数对象&#xff08;Function Object&#xff09;也称为仿函数&#xff08;Functor&#xff09;&#xff0c;它是一个类的实例&#xff0c;该类重载了函数调用运算符()&#xff0c;使得这个…...

AJAX一、axios使用,url组成(协议,域名,资源路径)查询参数和化简,错误处理,请求/响应报文,状态码,接口文档,

一、AJAX是什么 概念 &#xff1a; AJAX是一种与服务器&#xff08;后端&#xff09;通信的技术 二、请求库axios的基本用法 1导包 2使用 // 1. 发请求 axios({ url: 请求地址 }).then(res > { // 2.接收并使用数据 }) <body><p class"province"…...

Python学习笔记

MJ大神的Python课&#xff0c;课堂笔记 int 和float运算结果是 float除法&#xff08;/&#xff09;的结果是float整除&#xff08;//&#xff09;&#xff0c;向下取整(floor)int 和 int 进行整除&#xff08;//&#xff09;,得到的结果是int 绘制一个填充色边框色 import …...

开源 - Ideal库 - Excel帮助类,TableHelper实现(三)

书接上回&#xff0c;我们今天继续讲解实现对象集合与DataTable的相互转换。 01、把表格转换为对象集合 该方法是将表格的列名称作为类的属性名&#xff0c;将表格的行数据转为类的对象。从而实现表格转换为对象集合。同时我们约定如果类的属性设置了DescriptionAttribute特性…...

ceph手动部署

ceph手动部署 一、 节点规划 主机名IP地址角色ceph01.example.com172.18.0.10/24mon、mgr、osd、mds、rgwceph02.example.com172.18.0.20/24mon、mgr、osd、mds、rgwceph03.example.com172.18.0.30/24mon、mgr、osd、mds、rgw 操作系统版本&#xff1a; Rocky Linux release …...

macOS 开发环境配置与应用开发指南

macOS 开发环境配置与应用开发指南 macOS作为苹果公司推出的操作系统&#xff0c;因其稳定性、优雅的用户界面和强大的开发支持&#xff0c;已成为开发者和创意专业人士的首选平台之一。无论是开发iOS、macOS桌面应用&#xff0c;还是Web应用、跨平台程序&#xff0c;macOS都提…...

自动化是语法,智能化是语义与语用

自动化与智能化可以从语言学的角度来进行类比和探讨。 1. 自动化是语法 自动化可以类比为“语法”的部分&#xff0c;因为它关注的是操作过程的规则、结构和执行方式。语法是语言中关于词汇、句子结构和规则的系统&#xff0c;它提供了语言运作的框架和规范。类似地&#xff0c…...

基于DHCP,ACL的通信

该问题为华为的学习资料 1.首先把所有的PC机全部设置为DHCP 2.配置地址 3.ospf 4.dhcp 5.acl AR1 dhcp en interface GigabitEthernet0/0/0ip address 192.168.1.254 255.255.255.0 dhcp select global interface GigabitEthernet0/0/1ip address 10.1.12.1 255.255.255.…...

Unity跨平台基本原理

Unity跨平台基本原理 Unity跨平台基本原理微软的.Net是什么微软做 .Net平台的目的如何实现的.Net跨语言&#xff1f;总结 .Net Framework.Net Framework的体系结构CLR总结 如何实现的跨平台&#xff1f;.Net Core.Net FrameWork 到 .Net CoreMonoMono如何实现跨平台总结如何实现…...

基于 Python、OpenCV 和 PyQt5 的人脸识别上课打卡系统

大家好&#xff0c;我是Java徐师兄&#xff0c;今天为大家带来的是基于 Python、OpenCV 和 PyQt5 的人脸识别上课签到系统。该系统采用 Python 语言开发&#xff0c;开发过程中采用了OpenCV框架&#xff0c;Sqlite db 作为数据库&#xff0c;系统功能完善 &#xff0c;实用性强…...