《C语言程序设计 第4版》笔记和代码 第十二章 数据体和数据结构基础

news2024/9/23 17:21:11

12.1从基本数据类型到抽象数据类型

1 所有的程序设计语言都不能将所有复杂数据对象作为其基本数据类型,因此需要允许用户自定义数据类型,在C语言中,就存在构造数据类型(复合数据类型)。

2 结构体是构造数据类型的一种经典代表。

3 抽象数据类型是不再单纯是一组值的集合,还包括作用在值集上操作的集合,且类型的表示细节操作的实现对外是不可见的。

4 C++中的是抽象数据的一种具体实现,也是面向对象程序设计语言中的一个重要概念,但是不能将C++看成是带类的C。

12.2 结构体的定义

1 数组的存储方式存在一些问题,如:(1)分配内存不集中,寻址效率低;(2)对数组赋初值时容易发生错位;(3)结构显得零散,不易管理。

2 数组适合对具有相同属性的数据进行批处理;而结构体将不同类型的数据成员组织到统一的名字下;共用体虽然也能表示逻辑相关的不同类型的集合,但是数据成员是情景互斥的。

3 结构体模板的格式如下:

注意,结构体模板并未声明结构体类型的变量,因此不会被分配内存。

4 C语言有两种方式定义结构体变量.

5 关键字typedef可用于为系统固有的或自定义的数据类型定义一个别名,它只是定义一个新的名字,而不是定义一种新的数据类型。

6 结构体变量的初始化格式:

结构体类型 结构体变量={值1,值2……值n};

7 结构体可以实现嵌套,即在一个结构体中包含了另一个结构体作为其成员。

8 访问结构体变量的成员必须使用成员选择运算符(也称圆点运算符),其格式为:

结构体变量名 . 成员名

9 出现结构体嵌套时,必须以级联方式访问结构体成员,也就是通过成员选择运算符逐级找到最底层的成员再引用。

例12.1见文末

10 C语言允许对具有相同结构体类型的变量进行整体赋值,如stu1=stu2;

11 并非所有的结构体成员都可以用赋值运算符来赋值,对字符数组类型的结构体成员进行赋值时,必须使用字符串处理函数strcpy()。

12 结构体类型的声明既可以放在所有函数体的外部(全局声明,可以被所有函数使用),也可以放在函数体的内部(局部声明,只能再本函数体内使用)。

13 结构体变量的地址是结构体变量所占内存空间的首地址,而结构体成员的地址值与结构体成员再结构体中所处的位置以及该成员所占内存的字节数有关。

例12.2见文末

14 系统为结构体变量分配内存的大小,或者说结构体类型所占内存的字节数,并非是所有成员所占内存字节数的总和,它不仅与所定义的结构体类型有关,还与计算机系统本身有关。

12.3 结构体数组的定义和初始化

1 结构体数组的定义格式为:

结构体类型 结构体变量[数量];

2 可以在定义时初始化结构体数组,否则其他数组元素被系统自动赋值为0

例12.3见文末

12.4 结构体指针的定义和初始化

1 如果已经声明了STUDENT的结构体类型,那么指向该结构类型的指针变量的方法为:

STUDENT *pt; //指针变量pt的值是随机值

为了使pt 指向确定的存储单元,需要对指针变量进行初始化,如:

pt=&stu1;

以上两条语句等价于:

STUDENT *pt=&stu1;

2 访问指针变量指向的结构体成员有两种方式:(一)使用成员选择符;(二)使用指向运算符(也称箭头运算符)。

3 使用箭头运算符访问结构体成员的标准形式为:

pt->studentID=1003101221;

等价于

(*pt).studentID=1002101221;//不常用

4 访问嵌套结构体指针变量下的成员,通常结合成员选择符和指向运算符,如:

pt->birthday.year=2002;

12.5 向函数传递结构体

1 向函数体传递结构体有三种方法。

2 方法一:用结构体的单个成员作为函数参数,向函数传递结构体的单个成员。这种方法与普通类型的变量作为函数实参没有区别,都是按值调用

3 方法二:用结构体变量作函数参数,向函数传递结构体的完整结构。通过这种方法,可以在函数内用成员选择运算符引用结构体其他成员,同样是按值传递,但是时空开销大,并且只能当行参和实参是同一结构体才可以使用。

4 方法三:用结构体指针结构体数组作函数参数,向函数传递结构体的地址。这种方法属于传地址调用,效率更高。

例12.4见文末

5 使用方法一和方法二,结构体变量的成员值不能在被调函数中被修改,而方法三可以被修改。

例12.5~例12.7见文末

12.6 共用体

1 共用体也称为联合,是将不同类型的数据组织在一起共同占有同一段内存的一种构造数据类型。

2 共用体与结构体的声明方法类似,只是关键字变成union

例12.8见文末

3 共用体所占的内存空间大小取决于成员中占内存空间最多的那个成员变量。

4 共用体采用与开始地址对齐的方式分配内存空间。

5 共用体通过覆盖技术来实现内存的共用,因此在每一瞬起作用的成员是最后一次被赋值的成员。

6 不能为共用体的所有成员同时初始化

7 共用体不能进行比较操作,也不能作为函数参数

12.7 枚举数据类型

1 当某些量仅由有限个数据值组成时,通常用枚举类型来表示。

2 枚举描述的是一组整型值的集合,需要使用关键字enum来定义。

3 枚举类型的声明格式为:

enum 枚举标签{枚举常量1,枚举常量2……枚举常量n};

4 枚举常量的定义格式为:

enum 枚举标签 枚举变量名;

可以将枚举常量赋值给对应的枚举标签。

5 当枚举标签和枚举变量放在一起定义时,枚举标签可以省略不写,如:

enum {no,yes,none} answer;

6 虽然枚举标签后面的花括号内的标识符代表枚举型变量的可能取值,但其值是整型常数,不是字符串,因此不能作为字符串来使用。

12.8 动态数据结构—单向链表

1 动态数据结构是利用动态内存分配,使用结构体并且配合指针来实现的一种数据结构。

2 在结构体声明时不能包含结构体类型成员,但可以包含指向本结构体类型的指针成员

3 链表实际是链式存储顺序访问的线性表,它是用一组任意的存储单元来存储线性表中的数据,存储单元不一定连续的,链表长度是不固定的。

4 链表的每一个元素称为一个节点,节点包含数据域指针域两部分。

5 节点的数据域用于存储本身的数据信息,节点的指针域是一个结构体指针,用于存储其直接后继的节点信息,当其值为空指针(NULL)时,表示链表结束。

6 链表中还需有一个指向链表的起始节点的头指针变量。

7 只包含一个指针域,由n个节点链接形成的链表就被称为线性链表或者单向链表

8 链表只能顺序访问,不能随机访问,因此最大的缺点是容易出现断链,且断链后影响大。

9 单向链表的建立考虑(1)若原链表为空表,则将新建节点置为头结点;(2)若原链表非空,则将新建节点添加到表尾.

例12.9见文末

10 单向链表的删除考虑 (1)若原链表为空表,则无须删除,直接退出程序;(2)若找到的待删除节点是头节点,则将头指针变量指向当前节点的下一个节点;(3)若找到的待删除节点不是头结点,则将前一节点的指针域指向当前节点的下一节点;(4)搜索到表尾,依旧未找到待删除节点,则提示未找到.

例12.10见文末

11 单向链表的插入考虑 (1)若原链表为空表,则将新节点作为头结点;(2)若原链表非空,则按节点值的大小确定插入新节点;(3)若在表尾插入新节点,则末节点指针域指向新节点.

例12.11见文末

代码

12.1a

演示结构体变量的赋值与用于方法,从键盘输入数据

/12.1a演示结构体变量的赋值与用于方法
#include<stdio.h>
typedef struct date
{
	int year;
	int month;
	int day;
 }DATE;//别名为DATE
 typedef struct student
 {
 	long studentID;
 	char studentName[10];
 	char studentSex;
 	DATE birthday;//嵌套结构体 
	int score[4]; 
  }STUDENT;
int main(void)
{
	STUDENT stu1={100210121,"王刚",'M',{1991,5,19},{72,83,90,82}};//初始化,赋值用花括号 
	STUDENT stu2;//定义一个相同结构体类型的结构体变量stu2
	stu2=stu1;//相同结构体类型之间进行赋值
	printf("stu2:%10ld%8s%3c%6d/%02d/%02d%4d%4d%4d%4d\n",//这里的%02d表示输出数据时若左边有多余位则补0
			stu2.studentID,stu2.studentName,stu2.studentSex,//对应学号、姓名、性别 
			stu2.birthday.year,stu2.birthday.month,stu2.birthday.day,//对应出生年月日
			stu2.score[0], stu2.score[1], stu2.score[2], stu2.score[3]); 
	return 0;
 }

12.1b

演示结构体变量的赋值与用于方法,从键盘输入数据

 //12.1b演示结构体变量的赋值与用于方法,从键盘输入数据
#include<stdio.h>
typedef struct date
{
	int year;
	int month;
	int day;
 }DATE;//别名为DATE
 typedef struct student
 {
 	long studentID;
 	char studentName[10];
 	char studentSex;
 	DATE birthday;//嵌套结构体 
	int score[4]; 
  }STUDENT;
int main(void)
{
	
	STUDENT stu1,stu2; //定义结构体变量
	int i;//用于控制成绩输入
	printf("Input a recoed:\n");
	scanf("%ld",&stu1.studentID);
	scanf("%s",&stu1.studentName);
	scanf(" %c",&stu1.studentSex);//%c前面有一个空格 
	scanf("%d",&stu1.birthday.year);
	scanf("%d",&stu1.birthday.month);
	scanf("%d",&stu1.birthday.day);
	for(i=0;i<4;i++)
	{
		scanf("%d",&stu1.score[i]);
	}
	stu2=stu1;//相同结构体类型之间进行赋值
	printf("&stu2=%p\n",&stu2);//打印stu2的地址 
	printf("stu2:%10ld%8s%3c%6d/%02d/%02d%4d%4d%4d%4d\n",//这里的%02d表示输出数据时若左边有多余位则补0
			stu2.studentID,stu2.studentName,stu2.studentSex,//对应学号、姓名、性别 
			stu2.birthday.year,stu2.birthday.month,stu2.birthday.day,//对应出生年月日
			stu2.score[0], stu2.score[1], stu2.score[2], stu2.score[3]); 
	return 0;
 } 

12.2

演示结构体所占字节数的计算方法

//12.2 演示结构体所占字节数的计算方法
#include<stdio.h>
typedef struct sample
{
	char m1;
	int m2;
	char m3;
}SAMPLE;
int main(void)
{
	SAMPLE s={'a',2,'b'};
	printf("bytes=%d\n",sizeof(s));
	return 0;
 } 

12.3

利用结构体数组计算每个学生的4门课程的平均分

//例12.3 利用结构体数组计算每个学生的4门课程的平均分
#include<stdio.h>
typedef struct date
{
	int year;
	int month;
	int day;
 }DATE;//别名为DATE
 typedef struct student
 {
 	long studentID;
 	char studentName[10];
 	char studentSex;
 	DATE birthday;//嵌套结构体 
	int score[4]; 
  }STUDENT;
int main(void)
{
	int i,j,sum[30]; 
	STUDENT stu[30]={
	{100210121,"张三",'M',{1991,5,19},{72,93,80,52}},
	{100210122,"李四",'F',{1990,3,22},{83,93,73,12}},
	{100210123,"王二",'F',{1991,11,9},{92,73,93,86}},
	{100210124,"赵五",'M',{1991,5,5},{92,84,95,86}}
	};//注意花括号的对应
	for(i=0;i<4;i++)
	{
		sum[i]=0;
		for(j=0;j<4;j++)
		{
			sum[i]=sum[i]+stu[i].score[j];
		}
		printf("%10ld%8s%3c%6d/%02d/%02d%4d%4d%4d%4d%6.1f\n",
			stu[i].studentID,stu[i].studentName,stu[i].studentSex,//对应学号、姓名、性别 
			stu[i].birthday.year,stu[i].birthday.month,stu[i].birthday.day,//对应出生年月日
			stu[i].score[0], stu[i].score[1], stu[i].score[2], stu[i].score[3],
			sum[i]/4.0); 
	 } 
	return 0;
 }

12.4

演示结构体变量作函数实参实现传值调用

//12.4 演示结构体变量作函数实参实现传值调用
#include<stdio.h>
struct date
{
	int year;
	int month;
	int day;
};//无别名,不要忘记分号
void Func(struct date p)//结构体变量作函数形参 
{
	p.year=2000;
	p.month=5;
	p.day=22;
 }
int main(void)
{
	struct date d;
	d.year=1999;
	d.month=4;
	d.day=23;
	printf("Before function call:%d/%02d/%02d\n",d.year,d.month,d.day);
	Func(d);
	printf("After function call:%d/%02d/%02d\n",d.year,d.month,d.day);
	return 0;
}

12.5

修改12.4,改用结构体指针变量作函数实参

//12.5 修改12.4,改用结构体指针变量作函数实参
#include<stdio.h>
struct date
{
	int year;
	int month;
	int day;
};//无别名,不要忘记分号
void Func(struct date *pt)//结构体zz变量作函数形参 
{
	pt->year=2000;//指针运算符 
	pt->month=5;
	pt->day=22;
 }
int main(void)
{
	struct date d;
	d.year=1999;
	d.month=4;
	d.day=23;
	printf("Before function call:%d/%02d/%02d\n",d.year,d.month,d.day);
	Func(&d);//传地址调用 
	printf("After function call:%d/%02d/%02d\n",d.year,d.month,d.day);
	return 0;
}

12.6

从函数返回结构体变量的值 

//12.6 从函数返回结构体变量的值 
#include<stdio.h>
struct date
{
	int year;
	int month;
	int day;
};
struct date Func(struct date p)//返回类型是struct date型 
{
	p.year=2000;
	p.month=5;
	p.day=22;
	return p;
 }
int main(void)
{
	struct date d;
	d.year=1999;
	d.month=4;
	d.day=23;
	printf("Before function call:%d/%02d/%02d\n",d.year,d.month,d.day);
	d=Func(d);
	printf("After function call:%d/%02d/%02d\n",d.year,d.month,d.day);
	return 0;
}

12.7

修改12.3程序,用结构体数组作函数参数编程并输出计算学生的平均分 

//例12.7 修改12.3程序,用结构体数组作函数参数编程并输出计算学生的平均分 
#include<stdio.h>
#define N 30 
typedef struct date
{
	int year;
	int month;
	int day;
 }DATE;//别名为DATE
 typedef struct student
 {
 	long studentID;
 	char studentName[10];
 	char studentSex;
 	DATE birthday;//嵌套结构体 
	int score[4]; 
  }STUDENT;
void InputScore(STUDENT stu[],int n,int m);
void AverScore(STUDENT stu[],float aver[],int n,int m);
void PrintScore(STUDENT stu[],float aver[],int n,int m);
int main(void)
{
	float aver[N];
	STUDENT stu[N];
	int n;
	printf("How many students?");
	scanf("%d",&n);
	InputScore(stu,n,4);
	AverScore(stu,aver,n,4);
	PrintScore(stu,aver,n,4);
	return 0;
 }
void InputScore(STUDENT stu[],int n,int m){
	int i,j;
	for(i=0;i<n;i++)
	{
		printf("Input recore %d:\n",i+1);
		scanf("%ld",&stu[i].studentID);
		scanf("%s",stu[i].studentName);//这里无取地址符
		scanf(" %c",&stu[i].studentSex);
		scanf("%d",&stu[i].birthday.year);
		scanf("%d",&stu[i].birthday.month);
		scanf("%d",&stu[i].birthday.day);
		for(j=0;j<m;j++){
			scanf("%d",&stu[i].score[j]);
		}
	}
}
void AverScore(STUDENT stu[],float aver[],int n,int m){
	int i,j,sum[N];
	for(i=0;i<n;i++)
	{
		sum[i]=0;
		for(j=0;j<4;j++)
		{
			sum[i]=sum[i]+stu[i].score[j]; 
		}
		aver[i]=(float)sum[i]/m;
	}
}
void PrintScore(STUDENT stu[],float aver[],int n,int m){
	int i,j;
	printf("Result:\n");
	for(i=0;i<n;i++)
	{
		printf("%10ld%8s%3c%6d/%02d/%02d",
			stu[i].studentID,stu[i].studentName,stu[i].studentSex,//对应学号、姓名、性别 
			stu[i].birthday.year,stu[i].birthday.month,stu[i].birthday.day); //对应出生年月日
		for(j=0;j<m;j++){
			printf("%4d",stu[i].score[j]);
		}
		printf("%6.1f\n",aver[i]);
	}
}

12.8

演示共用体所占内存字节数的计算方法 

//12.8 演示共用体所占内存字节数的计算方法 
#include<stdio.h>
union sample
{
	char i;
	int ch;
	char f;
};
typedef union sample SAMPLE;
int main(void)
{
	printf("bytes=%d\n",sizeof(SAMPLE));
	return 0;
 } 

12.9

单向链表的建立

//12.9 单向链表的建立
#include<stdio.h>
#include<stdlib.h>
struct link *AppendNode(struct link *head);
void DisplyNode(struct link *head);
void DeleteMemory(struct link *head);
struct link
{
	int data;
	struct link *next;
};

int main(void)
{
	int i=0;
	char c;
	struct link *head=NULL;//链表的头指针
	printf("Do you want to append a new node(Y/N)?");
	scanf(" %c",&c);
	while(c=='Y'||c=='y')
	{
		head=AppendNode(head);//向head为头指针的链表末添加节点
		DisplyNode(head);//显示当前链表中的各节点信息
		printf("Do you want to append a new node(Y/N)?");
		scanf(" %c",&c);
		i++; 
	 } 
	printf("%d new nodes have been apended!\n",i);
	DeleteMemory(head);//释放所有动态分配的内存 
	return 0;
}
//函数功能:新建一个节点并添加到链表末尾,返回添加节点后的链表的头指针
struct link *AppendNode(struct link *head)
{
	struct link *p=NULL,*pr=head;
	int data;
	p=(struct link *)malloc(sizeof(struct link));//p指向新建节点
	if(p==NULL){
		printf("No enough memory to allocate!\n");//提醒用户分配失败
		exit(0);//退出程序 
	} 
	if(head==NULL){//原链表为空表 
		head=p;//新建节点置为头结点 
	}
	else{
		while(pr->next!=NULL)//未到末尾,就移动pr,让pr指向表尾
		{
			pr=pr->next;//让pr指向下一个节点 
		 }
		pr->next=p;//末节点的指针域指向新建节点 
	}
	printf("Input node data:");
	scanf("%d",&data);
	p->data=data;
	p->next=NULL;//将新建节点置为表尾 
	return head;
 } 
 //函数功能:显示链表中所有节点的节点号和该节点中的数据项
 void DisplyNode(struct link *head)
 {
 	struct link *p=head;
 	int j=1;
 	while(p!=NULL)//不是表尾
	 {
	 	printf("%5d%10d\n",j,p->data);
	 	p=p->next;
	 	j++;
	  } 
  } 
 //函数功能:释放head指向的链表中所有节点占用的内存
 void DeleteMemory(struct link *head)
 {
 	struct link *p=head,*pr=NULL;
 	while(p!=NULL)
 	{
 		pr=p;//用pr保存当前节点 
 		p=p->next;//移动指针,使其指向下一个节点 
 		free(pr);//释放当前节点 
	 }
  } 

12.10

单向链表的删除操作函数

//12.10 单向链表的删除操作函数
//函数功能:从head 指向的链表中删除一个节点,返回删除节点后的链表的头指针
struct link *DeleteNode(struct link *head,int nodeData)
{
	struct link *p=head,*pr=head;
	if(head==NULL)//空表
	{
		printf("Linked Table is empty!\n")
		return (head);
	 } 
	while(nodeData!=p->data&&p->next!=NULL)//未找到并且 未到表尾
	{
		pr=p;//pr保存当前节点 
		p=p->next; //指向下一节点 
	 } 
	if(nodeData==p->data)//找到待删除节点
	{
		if(p==head)
		{
			head=p->next;//如果是头节点,就让头结点指向待删除节点的下一个节点 
		}
		else
		{
			pr->next=p->next;//前一节点的指针域指向待删除节点的下一个节点 
		 }
		 free(p);//释放删除节点的内存 
	 }
	 else //到来表尾依旧没有找到待删除节点
	 {
	 	printf("This Node has nor been found!\n");
	  } 
	return head;
 } 
 

12.11

单向链表的插入操作函数

//12.11单向链表的插入操作函数
//函数功能:在已按升序排序的链表中插入一个新节点,返回插入节点后的链表的头指针
struct link *InsertNode(struct link *head,int nodeData)
{
	struct link *pr=head,*p=head,*temp=NULL;
	p=(struct link *)malloc(sizeof(struct link));//p指向待插入节点 
	if(p=NULL){//内存分配失败 
		printf("No enough memory!\n");
		exit(0);
	}
	p->next=NULL;//指针域赋值为空 
	p->data=nodeData;//赋值数据 
	if(head==NULL){//空表 
		head=p;
	}
	else{
		while(pr->data<nodeData&&pr->next!=NULL)
		{
			temp=pr;//用temp保存当前节点的指针 
			pr=pr->next;//指向下一节点 
		}
		if(pr->data>=nodeData)
		{
			if(pr==head)//在头结点前插入 
			{
				p->next=head;//将新节点的指针域指向原链表的头节点 
				head=p;//让head指向新节点 
			}
			else//在链表之间插入 
			{
				pr=temp;
				p->next=pr->next;//新节点的指针域指向下一节点 
				pr->next=p;//前一节点的指针域指向新节点 
			}
		}
		else//在链表末尾插入 
		{
			pr->next=p;//末节点指向新节点 
		}
	}
	return head;
 } 
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1971896.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用Openvino部署C++的Yolov5时类别信息混乱问题记录

使用Openvino部署C的Yolov5时类别信息混乱问题记录 简单记录一下。 一、问题描述 问题描述&#xff1a;在使用Yolov5的onnx格式模型进行C的Openvino进行模型部署时&#xff0c;通过读取classes.txt获得类别信息时&#xff0c;出现模型类别混乱&#xff0c;或者说根本就不给图…

【原创】java+swing+mysql学分管理系统设计与实现

个人主页&#xff1a;程序员杨工 个人简介&#xff1a;从事软件开发多年&#xff0c;前后端均有涉猎&#xff0c;具有丰富的开发经验 博客内容&#xff1a;全栈开发&#xff0c;分享Java、Python、Php、小程序、前后端、数据库经验和实战 开发背景&#xff1a; 随着信息技术的…

嵌入式单片机中在线调试工具使用方法

大家好,相信很多小伙伴都听说过,或者用过SystemView这款工具。 它是一个可以在线调试嵌入式系统的工具,它可以分析RTOS有哪些中断、任务执行了,以及这些中断、任务执行的先后关系。 还可以查看一些内核对象持有和释放的时间点,比如信号量、互斥量、事件、消息队列等,这在…

Vue3 form表单赋值后,input输入框无法输入

1.使用reactive初始化数据: 需要用一个对象包裹数据,使其变成响应式数据 Form表单及JS中的使用都需要 “paramr.formUser” 进行调用 原因: 使用reactive生成的响应式数据&#xff0c;在直接赋值时把响应式数据给替换为了普通数据了&#xff0c;导致无法监听数据的变化。 2. …

Flutter——权威常用组件demo代码开源

背景 自学的过程中&#xff0c;并记录下来仅供大家一起学习 开源地址&#xff1a;https://github.com/z244370114/flutter_demo

软件测试经典面试题,助你面试加分

一 时间紧迫的情况下&#xff0c;如何做好测试工作&#xff1f; 对需求要明确&#xff0c;对需求的优先级也要明确&#xff0c;在项目的过程中就可以少做变更的工作。减少测试的工作量。 由资深测试工程师对测试用例进行设计&#xff0c;并进行用例评审。 用例要重点覆盖主要…

Cocos Creator2D游戏开发(10)-飞机大战(8)-计分和结束

现在游戏基本能完了, 飞机能发射子弹,打了敌机,敌机也能炸; 接下来要做计分了; 步骤: 搞出一个lable让lable显示炸了多少飞机 开搞: ①创建一个Lable标签 ② root.ts文件 添加 property(Label) player_score: Label; // 标签属性 标签绑定 ③ 代码添加 注册 然后回调 contac…

iOS弱引用

背景&#xff1a;在面试过程中被问到如果两个对象已经发生循环引用了&#xff0c;该如何将他们剪断&#xff0c;在运行态的时候。 由于这个场景比较抽象&#xff0c;我理解面试官是希望我通过运行时的方法和方式来解决循环引用。 解决方案一: 重写setter用关联对象来实现wea…

【C++11】:右值引用移动语义完美转发

目录 前言一&#xff0c;左值引用和右值引用二&#xff0c;左值引用与右值引用比较三&#xff0c;探索引用的底层四&#xff0c;右值引用使用场景和意义4.1 解决返回值问题4.2 STL容器插入接口的改变 五&#xff0c;移动语义六&#xff0c;完美转发6.1 模板中的&& 万能…

【动态路由协议】RIP

一、前导知识 动态路由协议分类&#xff1a; 1.IGP(内部网关协议&#xff0c;位于同一个自治系统内) 1.1距离矢量路由协议 RIP&#xff08;距离矢量路由&#xff09; 1.2链路状态路由协议 OSPF&#xff08;开放式最短路径优先&#xff09; IS-IS&#xff08;中间系统到中间系统…

Xinstall新玩法:Web直接打开App,用户体验再升级!

在移动互联网时代&#xff0c;App已成为我们日常生活中不可或缺的一部分。然而&#xff0c;在App推广和运营过程中&#xff0c;许多开发者面临着从Web端引流到App的难题。这时&#xff0c;Xinstall作为国内专业的App全渠道统计服务商&#xff0c;提供了一种创新的解决方案——通…

【前端 21】Vue Router路由配置

Vue Router路由配置 在Vue.js项目中&#xff0c;Vue Router是官方提供的路由管理器&#xff0c;用于构建单页面应用&#xff08;SPA&#xff09;。它允许我们通过不同的URL访问不同的页面组件&#xff0c;而无需重新加载页面。下面&#xff0c;我将详细介绍如何在Vue项目中配置…

【研发日记】Matlab/Simulink技能解锁(十二)——Stateflow中的两种状态机嵌套对比

文章目录 前言 项目背景 两级状态机 函数状态机 分析和应用 总结 参考资料 前言 见《【研发日记】Matlab/Simulink技能解锁(七)——两种复数移相算法》 见《【研发日记】Matlab/Simulink技能解锁(八)——分布式仿真》 见《【研发日记】Matlab/Simulink技能解锁(九)——基…

将 HuggingFace 模型转换为 GGUF 及使用 ollama 运行 —— 以 Qwen2-0.5B 为例

前言 最近&#xff0c;阿里发布了Qwen2的系列模型&#xff0c;包括0.5B, 1.5B, 7B, 57B-A14B 和 72B&#xff0c;中英文效果都很好。 因为模型太新&#xff0c;目前还没有 GGUF 版本可以下载&#xff0c;于是转下GGUF&#xff0c;并分享转换教程。 什么是 GGUF&#xff1f; …

[VS Code扩展]写一个代码片段管理插件(一):介绍与界面搭建

文章目录 VS Code扩展机制项目搭建创建UI元素活动栏按钮主边栏视图主边栏工具栏按钮侧边栏右键菜单编辑器右键菜单 项目地址 [VS Code扩展]写一个代码片段管理插件&#xff08;一&#xff09;&#xff1a;介绍与界面搭建[VS Code扩展]写一个代码片段管理插件&#xff08;二&…

Io.net系统概述-核心功能;Io,net自动匹配资源与任务;两种令牌:IO和IOSD;

目录 Io.net 一、系统概述 二、核心功能 三、经济系统 四、产品与服务 五、团队与融资 六、市场前景与竞争优势 Io,net自动匹配资源与任务 一、动态资源分配机制 二、高级算法自动匹配资源与任务 三、用户界面与反馈机制 两种令牌:IO和IOSD。简单举例说明 $IO令牌…

2024四大硬盘数据恢复工具推荐!

不知道你有没有遇到过这种情况&#xff0c;电脑里的重要文件突然就不见了&#xff0c;可能是不小心删了&#xff0c;或者是硬盘出了点小问题。这时候&#xff0c;下面这几个好用的硬盘数据恢复工具就能帮你解决问题&#xff01; 一、福昕数据恢复 链接&#xff1a;www.pdf365…

【从英文中重建数字】python刷题记录

R2-字符串 目录 解简单方程法 线性代数法 ps: 就是从里面找出one,two,zero,---nine 想到哈希表,key代表单词&#xff0c;value代表0---9 用t表示单词&#xff0c;那不就是t在s中的查找问题了吗 但这样显然有些麻烦&#xff0c;在于t是不确定的,t需要遍历一遍keys()&…

万物分割(Segment Anything Model)C++模型推理部署

概述 SAM 是一种先进的人工智能模型&#xff0c;已经证明了在分割复杂和多样化图像方面具有优异的表现。该模型是计算机视觉和图像分割领域的一个重大突破。 SAM 的架构旨在处理各种图像分割任务&#xff0c;包括对象检测、实例分割和全景分割。这意味着该模型可以应用于各种用…

2024年Google Play上架指南:开发者账号与上包环境防关联

移动应用市场瞬息万变&#xff0c;成功上架Google Play商店无疑是每一位开发者的重要目标。然而&#xff0c;要确保应用程序顺利通过审核并获得持久的上架资格&#xff0c;开发者需要格外重视账号注册和上包环境管理这两个关键环节。 近年来&#xff0c;Google不断加强对开发者…