C语言 | 第十六章 | 共用体 家庭收支软件-1

news2024/10/27 17:23:12

P 151 结构体定义三种形式 2023/3/15

一、创建结构体和结构体变量

  1. 方式1-先定义结构体,然后再创建结构体变量
struct Stu{
char *name; //姓名
int num; //学号
int age; //年龄
char group; //所在学习小组
float score; //成绩
};
struct Stu stu1, stu2;
//定义了两个变量 stu1 和 stu2,它们都是 Stu 类型,都由 5 个成员组成
//注意关键字struct不能少
  1. 方式2-在定义结构体的同时定义结构体变量
struct Stu{
char *name; //姓名
int num; //学号
int age; //年龄
char group; //所在学习小组
float score; //成绩
} stu1, stu2;
//在定义结构体Stu 的同时,创建了两个结构体变量 stu1 和 stu2
  1. 方式3-如果只需要 stu1、stu2 两个变量,后面不需要再使用结构体数据类型,定义其他变量,在定义时也可以不给出结构体名
struct { //没有写 Stu
char *name; //姓名
int num; //学号
int age; //年龄
char group; //所在学习小组
float score; //成绩
} stu1, stu2;
stu1.name = "tom"; stu1.num = 100;....   // 使用直接赋值
//1. 该结构体数据类型,没有名, 匿名结构体
//2. stu1 和 stu2 就是 该结构体的两个变量

二、成员的获取和赋值

基本说明:结构体和数组类似,也是一组数据的集合,整体使用没有太大的意义。数组使用下标[ ]获取单个元素,结构体使用点号.获取单个成员。获取结构体成员的一般格式为结构体变量名.成员名;

案例一:赋值1

struct{
	char *name; //姓名
	int num; //学号
	int age; //年龄
	char group; //所在小组
	float score; //成绩
} stu1;
stu1.name = "jack";   // 上面使用的方法
printf("%s", stu1.name)  

案例二:赋值2

#include<stdio.h>
void main(){
	struct Student{
		char *name; //姓名
		int num; //学号
		int age; //年龄
		char group; //所在小组
		float score; //成绩
	} stu1 = {"贾宝玉", 11, 18, 'B', 90.50}, stu2 = { "林黛玉", 12, 16, 'A', 100 };
	// 也可以在定义的时候直接赋值,按顺序依次来就可以了
	struct Student stu3 = {"林黛玉3", 12, 16, 'A', 100};
	// 这样再次赋值也是可以的;但是每个元素的对应关系需要一一对应

	struct Student stu4;
	// stu4= {"林黛玉3", 12, 16, 'A', 100}; 这样是不允许的,只允许在定义的时候赋值,因为后面是一个整体
	printf("\n stu3.name=%s",stu3.name); 
	printf("\n stu1.name=%s",stu1.name);  // 输出也是同上输出

	getchar();
}

P 152 结构体应用实例 2023/3/17

一、基本步骤

  1. 声明(定义)结构体,确定结构体名
  2. 编写结构体的成员
  3. 编写处理结构体的函数

二、应用实例

  • 案例一:

    1. 编写一个Dog结构体,包含name(char[10])、age(int)、weight(double)属性。

    2. 编写一个say函数,返回字符串,信息中包含所有成员值。

    3. 在main方法中,创建Dog结构体变量,调用say函数,将调用结果打印输出。

#include<stdio.h>
	 /*
	编写一个Dog结构体,包含name(char[10])、age(int)、weight(double)属性
	编写一个say函数,返回字符串,信息中包含所有成员值。
	在main方法中,创建Dog结构体变量,调用say函数,将调用结果打印输出
	*/

	// 定义一个Dog结构体

	struct Dog {
	char * name;
	int age;
	double weight;
	};
	
	//say函数, 返回字符串,信息中包含所有成员值
	char * say (struct Dog dog){
		// 将这个信息放入到一个字符串(字符数组)
		static char info[50];   // 最后返回的就是它,是局部静态变量
		sprintf(info,"name=%s age=%d weight=%.2f",dog.name,dog.age,dog.weight);
		// spintf 将值打印到字符串中
		return info;
	}

	void main(){
	struct Dog dog;
	char * info = NULL;
	dog.name = "小黄";
	dog.age = 1;
	dog.weight = 3.4;
	info = say(dog);   // 结构体默认是值传递
	// 函数中修改不会影响到函数外的值
	printf("\n 小狗的信息=%s",info);

	getchar();
}
  • 案例二:

    1. 编程创建一个Box结构体,在其中定义三个成员表示一个立方体的长、宽和高,长宽高可以通过控制台输入。

    2. 定义一个函数获取立方体的体积(volume)。

    3. 创建一个结构体,打印给定尺寸的立方体的体积。

    4. 思路

      struct Box {

      double len;

      double width;

      double height;

      double volumn;//体积

      }

#include<stdio.h>

struct	Box {
	int length;
	int width;
	int height;
};

int total(struct Box box){
	static int volume;
	return	volume=box.height * box.length * box.width;
}

void main(){
	struct Box box;
	int  volume;
	// 输入长
	printf("\n请输入box的长");
	scanf("%d",&box.length);
	// 输入宽
	printf("\n请输入box的宽");
	scanf("%d",&box.width);
	// 输入高
	printf("\n请输入box的高");
	scanf("%d",&box.height);
	volume = total(box);
	printf("\nbox的体积为%d",volume);

	getchar();
	getchar();
}

image-20230317122456954

  • 案例三:景区门票案例
    1. 一个景区根据游人的年龄收取不同价格的门票。
    2. 请编写游人结构体(Visitor),根据年龄段决定能够购买的门票价格并输出。
    3. 规则:年龄>18 , 门票为20元,其它情况免费。
    4. 可以循环从控制台输入名字和年龄,打印门票收费情况, 如果名字输入 n ,则退出程序。
#include<stdio.h>
#include<string.h>

/*
1)一个景区根据游人的年龄收取不同价格的门票。
2) 请编写游人结构体(Visitor),根据年龄段决定能够购买的门票价格并输出
3) 规则:年龄>18 , 门票为20元,其它情况免费。
4) 可以循环从控制台输入名字和年龄,打印门票收费情况, 如果名字输入 n ,则退出程序

*/

//  定义个结构体
struct Visitor{
	char name[10];
	int age;
	double pay;  //  应付门票
};

// 编写函数处理业务
//说明: 因为结构体默认是值传递,会拷贝一份完整的数据,效率就低
//			因此,为了提高效率,我们直接接收一个地址(指针)
void ticket(struct Visitor * visitor){
	// 判断
	if((*visitor).age > 18){  // 这里我们用的指针,需要使用取值符*
		(*visitor).pay = 20;
	}else{
		(*visitor).pay = 0;
	}
}

void main(){
	// 测试
	// 创建结构体变量(创建一个游客)
	struct Visitor visitor;
	// 循环的输入名字和年龄
	while(1){
		printf("\n 请输入游客名字");
		scanf("%s",visitor.name);  // 数组不需要加地址符
		// 如果名字输入 n ,则退出程序
		if(!strcmp("n",visitor.name)){ // 这里可以取反,非0为真就进入if执行break;也可以strcmp("n",visitor.name)==0
			break;
		}
		printf("\n 请输入游客年龄");
		scanf("%d",&visitor.age);

		// 调用函数ticket,获取应付的票价
		ticket(&visitor);		  // 因为形参是指针,这里需要传一个地址;
		// 这样在函数里面操作visitor就是操作的main函数里面的visitor

		printf("\n 该游客应付票价=%.2f",visitor.pay);
	}	
	printf("退出程序");
	getchar();
	getchar();
}

image-20230317141338383

P 153 共用体介绍和快速入门 2023/3/17

一、需求引入

引入:现有一张关于学生信息和教师信息的表格。学生信息包括姓名、编号、性别、职业、分数,教师的信息包括姓名、编号、性别、职业、教学科目。请看下面的表格:

image-20230317174740024

  • 传统方式解决:
    1. 定义结构体,根据人员的职业,使用对应的成员变量。
struct Person{
char name[20];
int num;
char sex;
char profession;
float score; // 学生使用 score
char course[20]; // 老师使用course 
} ;
  • 传统方式的问题分析
    1. 会造成 空间的浪费 , 比如学生只使用 score ,但是 也占用了course 成员的20个字节。
    2. struct Stustruct Teacher [但如果职业很多,就会对应多个结构体类型, 不利于管理]。
    3. 使用共用体。

二、基本介绍

  1. 共用体(Union)属于 构造类型,它可以包含多个类型不同的成员。和结构体非常类似, 但是也有不同的地方。
  2. 共用体有时也被称为联合或者联合体, 定义格式为
union 共用体名{
成员列表
};
  1. 结构体和共用体的区别在于:结构体的各个成员会占用不同的内存,互相之间没有影响;而共用体的所有成员占用同一段内存,修改一个成员会影响其余所有成员。

三、快速入门

  1. 定义共用体类型和共用体变量的三种方式(和结构体一样)。

image-20230317185534901

  1. 案例演示:
#include<stdio.h>
	union data{  // data就是一个共用体,包含三个成员,共用数据空间,该空间的大小以占用最大的成员变量为准
		int n;  // 4字节
		char ch; // 1字节
		short m; // 2字节	
	};

	void main(){
		union data a; // 定义了一个共用体变量 a
		printf("%d, %d\n", sizeof(a), sizeof(union data) ); // 4,4 
		a.n = 0x40;  // 十六进制
		printf("%d, %c, %d\n", a.n, a.ch, a.m);  // 修改了一个成员的值,发现其他成员也有一个值
		a.ch = '9';
		printf("%d, %c, %d\n", a.n, a.ch, a.m);
		a.m = 0x2059;
		printf("%d, %c, %d\n", a.n, a.ch, a.m);
		a.n = 0x3E25AD54;
		printf("%d, %c, %d\n", a.n, a.ch, a.m);
		getchar();
	}

image-20230317192247061

P 154 共用体的内存布局 2023/3/17

一、内存布局

  • 案例同上一节:
#include<stdio.h>
	union data{  // data就是一个共用体,包含三个成员,共用数据空间,该空间的大小以占用最大的成员变量为准
		int n;  // 4字节
		char ch; // 1字节
		short m; // 2字节	
	};

	void main(){
		union data a; // 定义了一个共用体变量 a
		printf("%d, %d\n", sizeof(a), sizeof(union data) ); // 4,4 
		a.n = 0x40;    // 十六进制 

		// int 4 字节,char 1字节,short 2字节
		// 根据内存图判断:    (最低位到最高位是从右到左)
		printf("%d, %c, %d\n", a.n, a.ch, a.m); 
		// 这里第一位输出0x40的十进制64,第二位输出64对应的ASCII码@符,第三位同样64
		a.ch = '9';
		printf("%d, %c, %d\n", a.n, a.ch, a.m);
		// 第一位 字符9对应的ACSII码十进制为57,第二位对应字符为9,第三位为57
		a.m = 0x2059;
		printf("%d, %c, %d\n", a.n, a.ch, a.m);
		// 以下与上面同理:
		a.n = 0x3E25AD54;
		printf("%d, %c, %d\n", a.n, a.ch, a.m);
		getchar();
	}

二、布局图

image-20230317200548542

image-20230317200957782

P 155 共用体的最佳实践 2023/3/18

一、解决实践问题

#include<stdio.h>
#define TOTAL 2 //人员总数
// 定义了一个结构体person

// 1.共用体使用方法一:
union Myunion { // 在下面定义名称
		float score;  
		char course[20];  
};
struct Person{
	char name[20];  // 姓名
	int num;  // 编号
	char sex;  // 性别
	char profession;   // 职业 s=>学生 t=>老师

	union Myunion sc;
	// 2.共用体使用方法二:
	//union{  // 共用体所有成员 公用一段空间所以不会浪费空间
	//	float score;  
	//	char course[20];  
	//} sc;   // sc是一个共用体变量
};
void main(){
	int i;
	struct Person persons[TOTAL];  // 定义一个结构体数组
	// 之前定义了TOTAL等于2,相当于两个人,两种信息

	//输入人员信息
	for(i=0; i<TOTAL; i++){
		printf("Input info: ");
		scanf("%s %d %c %c", persons[i].name, &(persons[i].num), &(persons[i].sex), &(persons[i].profession));
		if(persons[i].profession == 's'){ //如果是学生
			printf("请输入该学生成绩");
			scanf("%f", &persons[i].sc.score);
		}else{ //如果是老师
			printf("请输入该老师课程");
			scanf("%s", persons[i].sc.course);
		}
		fflush(stdin);  // 刷新;输入,保证数据都写入到结构体里面去了
	}
	//输出人员信息

	//输出人员信息
	printf("\nName\t\tNum\tSex\tProfession\tScore / Course\n"); // 想按一个表格输出,所以我们使用制表符\t
	for(i=0; i<TOTAL; i++){
		if(persons[i].profession == 's'){ //如果是学生
			printf("%s\t\t%d\t%c\t%c\t\t%f\n", persons[i].name, persons[i].num, persons[i].sex, persons[i].profession, persons[i].sc.score);
		}else{ //如果是老师
			printf("%s\t\t%d\t%c\t%c\t\t%s\n", persons[i].name, persons[i].num, persons[i].sex, persons[i].profession, persons[i].sc.course);
		}
	}
	getchar();
	getchar();
}

P156 项目-家庭收支软件(1) 2023/3/18

一、需求说明

image-20230318163342944

image-20230318163403959

image-20230318163418563

image-20230318163438600

image-20230318163504410

image-20230318163534895

image-20230318163552789

image-20230318163601511

image-20230318163613308

image-20230318163622772

二、需求实现(1)

#include<stdio.h>
#include<string.h>

void main(){
	// 完成1:显示菜单
	//  分析:
	// 1.使用do-while来显示菜单,如果用户输入4表示程序退出  

	// 完成2:登记收入
	// 分析:
	// 1. 需要一个字符串记录收支入情况

	// 定义相关变量
	char key = '	'; // 表示用户输入了哪个菜单
	int loop = 1; // 控制是否退出菜单
	char details [3000] = "-----------------当前收支明细记录-----------------\n收支\t收支金额\t账户金额\t说 明";  // 记录所有的收入和支出情况
	char note[20] = ""; // 对收入或者支出的说明
	char temp[100] = "";  // 是用于格式化每次的收入或者支出,然后拼接到details中去
	double money = 0.0;
	double balance = 1000.0; // 账号余额

	do{
		printf("\n\n-------家庭收支记账软件-----------");
		printf("\n	1收支明细");
 		printf("\n	2登记收入");                  
 		printf("\n	3登记支出");                   
 		printf("\n	4退出");                            
        printf("\n选择(1-4):");         
		scanf("%c",&key);  
		getchar(); // 过滤回车

		 switch(key) {
		 case '1':
			 printf("%s",details);
			 break;

		 case '2':
			 printf("\n 本次收入金额:");
			 scanf("%lf",&money);
			 getchar();  // 过滤回车
			 balance += money;   // 更新余额
			 printf("\n 本次收入说明:");
			 scanf("%s",note);
			 getchar();  // 过滤回车
			// 将信息拼接到details
			 sprintf(temp,"\n收入\t%.2f\t\t%.2f\t\t%s",money,balance,note);
			 strcat(details,temp);
			 break; 

		 case '3':
			printf("登记支出");
			break;

		 case '4':
			loop = 0;
		 }      

	}while(loop);
				printf("退出菜单!");
				getchar();
}

P157 项目-家庭收支软件(2) 2023/3/19

一、需求实现(2)

  • 项目代码实现改进
    1. 用户输入4退出时,给出提示"你确定要退出吗? y/n",必须输入正确的y/n ,否则循环输入指令,直到输入y 或者 n。
    2. 当没有任何收支明细时,提示 “当前没有收支明细… 来一笔吧!”
    3. 在支出时,判断余额是否够,并给出相应的提示。
#include<stdio.h>
#include<string.h>
void main(){
	// 完成1:显示菜单
	//  分析:
	// 1.使用do-while来显示菜单,如果用户输入4表示程序退出  

	// 完成2:登记收入
	// 分析:
	// 1. 需要一个字符串记录收支入情况

	// 完成3:等级支出
	// 1. 同收入

	// 完成4:
	/*用户输入4退出时,给出提示"你确定要退出吗? y/n",必须输入正确的y/n ,否则
	循环输入指令,直到输入y 或者 n。*/

	// 完成5:
	// 当没有任何收支明细时,提示 "当前没有收支明细... 来一笔吧!"

	// 完成6:
	// 在支出时要判断余额是否够,并给出相应提示:

	// 定义相关变量
	char key = '	'; // 表示用户输入了哪个菜单
	int loop = 1; // 控制是否退出菜单
	char details [3000] = "-----------------当前收支明细记录-----------------\n收支\t收支金额\t账户金额\t说 明";  // 记录所有的收入和支出情况
	char note[20] = ""; // 对收入或者支出的说明
	char temp[100] = "";  // 是用于格式化每次的收入或者支出,然后拼接到details中去
	double money = 0.0;
	double balance = 1000.0; // 账号余额
	char choice = ' ';  // 表示用户选择选择是y/n
	int flag = 0;  //  表示是否有一笔支出或者收入

	do{
		printf("\n\n-------家庭收支记账软件-----------");
		printf("\n	1收支明细");
		printf("\n	2登记收入");                  
		printf("\n	3登记支出");                   
		printf("\n	4退出");                            
		printf("\n选择(1-4):");         
		scanf("%c",&key);  
		getchar(); // 过滤回车

		switch(key) {
		case '1':
			if(flag){
				printf("%s",details);
			}else{
				printf("\n当前没有收支明细……,来一笔吧!");
			}
			break;

		case '2':
			printf("\n 本次收入金额:");
			scanf("%lf",&money);
			getchar();  // 过滤回车
			balance += money;   // 更新余额
			printf("\n 本次收入说明:");
			scanf("%s",note);
			getchar();  // 过滤回车
			// 将信息拼接到details
			sprintf(temp,"\n收入\t%.2f\t\t%.2f\t\t%s",money,balance,note);
			strcat(details,temp);
			flag = 1;
			break; 

		case '3':
			printf("\n 本次支出金额:");
			scanf("%lf",&money);
			getchar();  // 过滤回车

			//判断是否足够支出
			if(money >balance){  // 不够
				printf("余额不足……");		
				break;
			}
			balance -= money;   // 更新余额
			printf("\n 本次支出说明:");
			scanf("%s",note);
			getchar();  // 过滤回车
			// 将信息拼接到details
			sprintf(temp,"\n支出\t%.2f\t\t%.2f\t\t%s",money,balance,note);
			strcat(details,temp);
			flag = 1;
			break; 

		case '4':
			printf("\n你确定要退出吗?y/n");
			do{
				scanf("%c",&choice);
				getchar();
				if(choice == 'y' || choice == 'n'){
					break;
				}
				printf("\n你的输入有误,请重新输入y/n");
			}while(1);
			if(choice == 'y'){  // 输出的为y,就将loop赋值为0
				loop = 0;   
			}
		}     

	}while(loop);
	printf("退出菜单!");
	getchar();
}

P158 项目-家庭收支软件(3) 2023/3/19

一、需求实现(3)

  1. 改成使用结构体完成 => 并且使用函数来提高项目的模块化编程, 利用今后项目的维护和扩展。
  2. 这样更容易维护,当需要增加功能的时候,只需要找到对应的函数进行更改。
#include<stdio.h>
#include<string.h>

// 定义一个结构体
struct MyFamilyAccount {
	int flag;  // 表示是否有一笔收入或者支出
	char details[3000]; // 明细
	double balance; // 余额
} myFamilyAccount;

// 下面为全局变量:
char key = '	'; // 表示用户输入了哪个菜单
int loop = 1; // 控制是否退出菜单
char note[20] = ""; // 对收入或者支出的说明
char temp[100] = "";  // 是用于格式化每次的收入或者支出,然后拼接到details中去
double money = 0.0;
char choice = ' ';  // 表示用户选择选择是y/n

// 使用函数,显示明细
void showDetails(struct MyFamilyAccount * myFamilyAccount){
	if((* myFamilyAccount).flag){
		printf("%s",(* myFamilyAccount).details);
	}else{
		printf("\n当前没有收支明细……,来一笔吧!");
	}
}

//使用函数,完成一个登记收入
void income(struct MyFamilyAccount * myFamilyAccount){

	printf("\n 本次收入金额:");
	scanf("%lf",&money);
	getchar();  // 过滤回车
	(* myFamilyAccount).balance += money;   // 更新余额
	printf("\n 本次收入说明:");
	scanf("%s",note);
	getchar();  // 过滤回车
	// 将信息拼接到details
	sprintf(temp,"\n收入\t%.2f\t\t%.2f\t\t%s",money,(* myFamilyAccount).balance,note);
	strcat((* myFamilyAccount).details,temp);
	(* myFamilyAccount).flag = 1;
}

// 使用函数,完成一个登记支出
void pay(struct MyFamilyAccount * myFamilyAccount){
	printf("\n 本次支出金额:");
	scanf("%lf",&money);
	getchar();  // 过滤回车

	//判断是否足够支出
	// 这里account是在结构体中了,需要取出来
	if(money >(*myFamilyAccount).balance){  // 不够
		printf("余额不足……");		
		//				break;   
		// 这里是break了,不能在函数中使用,函数中自然使用return语句
		return;
	}
	(*myFamilyAccount).balance -= money;   // 更新余额
	printf("\n 本次支出说明:");
	scanf("%s",note);
	getchar();  // 过滤回车
	// 将信息拼接到details
	sprintf(temp,"\n支出\t%.2f\t\t%.2f\t\t%s",money,(*myFamilyAccount).balance,note);
	strcat((*myFamilyAccount).details,temp);
	(*myFamilyAccount).flag = 1;
}

//使用一个函数,完成退出
void myexit(){  // 这里没有使用到结构体,不需要传入
	printf("\n你确定要退出吗?y/n");
	do{
		scanf("%c",&choice);
		getchar();
		if(choice == 'y' || choice == 'n'){
			break;
		}
		printf("\n你的输入有误,请重新输入y/n");
	}while(1);
	if(choice == 'y'){  // 输出的为y,就将loop赋值为0
		loop = 0;   
	}
}   

// 该函数专门用于显示菜单
void mainMenu(struct MyFamilyAccount * myFamilyAccount  ){
	do{
		printf("\n\n-------家庭收支记账软件-----------");
		printf("\n	1收支明细");
		printf("\n	2登记收入");                  
		printf("\n	3登记支出");                   
		printf("\n	4退出");                            
		printf("\n选择(1-4):");         
		scanf("%c",&key);  
		getchar(); // 过滤回车

		switch(key) {
		case '1':
			showDetails(myFamilyAccount);
			break;
		case '2':
			income(myFamilyAccount);
			break;
		case '3':
			pay(myFamilyAccount);
			break;
		case '4':
			myexit();
		}
	}while(loop);
}

void main(){
	// 创建一个结构体变量
	struct MyFamilyAccount myFamilyAccount;
	// 初始化
	myFamilyAccount.flag = 0;
	myFamilyAccount.balance = 1000.0;
	// 使用拷贝的方式赋值
	memset(myFamilyAccount.details,3000,0);  //  先要清零
	strcpy(myFamilyAccount.details,"-----------------当前收支明细记录-----------------\n收支\t收支金额\t账户金额\t说 明");
	// 调用mainMenu显示菜单
	mainMenu(&myFamilyAccount);
	getchar();
}

二、结构示意图

image-20230321170235220

P 159 项目-CRM(1)-程序框架图 2023/3/23

一、项目需求说明

说明:模拟实现基于文本界面的《客户信息管理软件》。该软件能够实现对客户对象的插入、修改和删除(用数组实现),并能够打印客户明细表。

image-20230323192642160

image-20230323192658914

image-20230323192707577

image-20230323192722382

image-20230323192731730

image-20230323192749505

image-20230323192800182

image-20230323192809722

image-20230323192830906

二、程序框架图

作用:描述该项目包含多少个文件,明确文件与文件之间的调用关系。

image-20230323193601301

P 160 项目-CRM(2)-客户结构体 2023/3/23

一、完成Customer结构体

  • 思路:
    1. Customer结构体含有的成员,应该从给出的界面来分析
    2. 分析出有6个成员,数据类型也可以分析出来
    3. 编写一个函数,输出的给出的某个Customer变量的信息
#include<stdio.h>

// 定义结构体数据类型 
struct Customer{
	int id; // 编号
	int age;  // 年龄
	char name[10]; // 名字
	char gender;  // f 表示女,m表示男
	char phone[16]; //  电话号码
	char email[20]; // 邮箱
};

// 显示一个Customer变量的信息
// 这里我们接收的是结构体指针,目的是提高效率
void getCustomerInfo(struct Customer * customer){
	printf("\n%d\t%s\t%s\t%d\t%c\t%s\t%s",(* customer).id,(* customer).gender,(* customer).name,(* customer).age,(* customer).phone,(* customer).email);
}

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

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

相关文章

InternVL2-40B 荣登开源模型榜首丨SuperCLUE中文多模态大模型基准10月榜单

在今年 7 月 4 日举行的 2024 WAIC 科学前沿主论坛上&#xff0c;书生万象多模态大模型&#xff08;InternVL 2.0&#xff09;正式发布&#xff0c;并陆续开源了 1B、2B、4B、8B、26B、40B 以及 76B 共 7 个参数版本的模型。书生万象支持图像、视频、文字、语音、三维点云等模态…

Qt媒体播放器实现

本文介绍Qt媒体播放器实现。 Qt应用程序有时会涉及到视频文件的播放&#xff0c;Qt提供了QVideoWidget类实现视频和音频的播放&#xff0c;本文基于QVideoWidget类实现一个简单的媒体播放器。 1.自定义类&#xff08;基于QVideoWidget类&#xff09; 由于Qt并未提供专门的控…

手写简易shell

我们如果要写一个简易的shell我们要&#xff0c;其实我们搞一个程序替换就行了。 我们分为五部完成 在其中我们最难搞的就是环境变量的更新&#xff0c;因为当我们搞一个子程序出来时&#xff0c;我们子进程的环境变量表是从父进程继承下来的&#xff0c;当我们用cd命令时只会更…

C# 屏幕录制工具

屏幕录制工具 开发语音&#xff1a;C# vb.net 下载地址&#xff1a;https://download.csdn.net/download/polloo2012/89879996 功能&#xff1a;屏幕录制&#xff0c;声卡采集&#xff0c;麦克风采集。 屏幕录制&#xff1a;录制屏幕所有操作&#xff0c;并转换视频格式&…

电脑无线网wifi和有线网同时使用(内网+外网同时使用)

一、要求 我这里以无线网wifi为外网&#xff0c;有线网卡为内网为例&#xff1a; 一、基本信息 无线wifi&#xff08;外网&#xff09;&#xff1a;ip是192.168.179.235&#xff0c;网关是192.168.179.95有线网&#xff08;内网&#xff09;&#xff1a;ip是192.168.10.25&…

《鸟哥的Linux私房菜基础篇》---1 Linux的介绍与如何开启Linux之路

目录 一、Linux的简单介绍 1、Linux的简介 2、Linux的起源与发展 3、主要特点 4、应用场景 二、开启Linux之路 1、学习Linux的相关知识 2、正规表示法、管线命令、数据流重导向 前言 整体大纲预览 一、Linux的简单介绍 1、Linux的简介 &#xff08;1&#xff09;Linu…

【Trulens框架】用TruLens 自动化 RAG 应用项目评估测试

前言&#xff1a; 什么是Trulens TruLens是面向神经网络应用的质量评估工具&#xff0c;它可以帮助你使用反馈函数来客观地评估你的基于LLM&#xff08;语言模型&#xff09;的应用的质量和效果。反馈函数可以帮助你以编程的方式评估输入、输出和中间结果的质量&#xff0c;从而…

K8S---01初识Kubernetes

一.简介 摘取官网: 概述 | KubernetesKubernetes 是一个可移植、可扩展的开源平台&#xff0c;用于管理容器化的工作负载和服务&#xff0c;方便进行声明式配置和自动化。Kubernetes 拥有一个庞大且快速增长的生态系统&#xff0c;其服务、支持和工具的使用范围广泛。https://k…

【C++堆(优先队列)】1882. 使用服务器处理任务|1979

本文涉及知识点 C堆(优先队列) LeetCode1882. 使用服务器处理任务 给你两个 下标从 0 开始 的整数数组 servers 和 tasks &#xff0c;长度分别为 n​​​​​​ 和 m​​​​​​ 。servers[i] 是第 i​​​​​​​​​​ 台服务器的 权重 &#xff0c;而 tasks[j] 是处理…

【寻找one piece的算法之路】前缀和(一)

&#x1f490;个人主页&#xff1a;初晴~ &#x1f4da;相关专栏&#xff1a;寻找one piece的刷题之路 什么是前缀和&#xff1f; 主要是通过预先计算数组或矩阵的前缀和&#xff0c;来快速查询子数组或子矩阵的和。这种算法可以用空间换时间&#xff0c;提高查询效率。 概念…

FileOutputStream类

1.操作本地文件的字节输出流&#xff0c;可以把程序中的数据写到本地文件中。 2.书写步骤&#xff1a; 3.实例代码 结果&#xff1a;可以看到my io下面已经生成了一个a.txt文件。 4.注意细节 &#xff08;1&#xff09;参数是字符串表示的路径或者是File对象 &#xff08;2&…

怎么把音频的速度调慢?6个方法调节音频速度

怎么把音频的速度调慢&#xff1f;调慢音频速度不仅可以帮助我们更好地捕捉细节&#xff0c;还能让我们在分析和学习时更加从容。这对于音乐爱好者来说&#xff0c;尤其有助于理解复杂的旋律和和声&#xff0c;使学习过程变得更加高效。而在语言学习中&#xff0c;放慢语速则能…

Spring Cloud 3.x 集成eureka快速入门Demo

1.什么是eureka&#xff1f; Eureka 由 Netflix 开发&#xff0c;是一种基于REST&#xff08;Representational State Transfer&#xff09;的服务&#xff0c;用于定位服务&#xff08;服务注册与发现&#xff09;&#xff0c;以实现中间层服务的负载均衡和故障转移&#xff…

基于webrtc实现音视频通信

与传统通信方式不同&#xff0c;p2p通信的实现过程不依赖于中间服务器的信息收发&#xff0c;直接通过信令等完成通信过程的建立&#xff1b; 通过websocket实现信令服务器的建立&#xff0c;而通过信令来确定通信双方&#xff1b; webrtc通过 sdp协议来完善通信双方间协议的…

React01 开发环境搭建

React 开发环境搭建 一、创建 React 项目二、项目精简 一、创建 React 项目 执行下述命令创建 react 项目 blu-react-basis npx create-react-app blu-react-basis项目目录结构如下&#xff1a; 执行下述命令启动项目 npm run start启动效果如下&#xff1a; 二、项目精简 …

Java Agent 技术解析

什么是Java Agent Java Agent是在 JDK1.5 引入的一种可以动态修改 Java 字节码的技术。Java 类编译之后形成字节码被 JVM 执行&#xff0c;在 JVM 在执行这些字节码之前获取这些字节码信息&#xff0c;并且通过字节码转换器对这些字节码进行修改&#xff0c;来完成一些额外的功…

维生素对于生活的重要性

在探索健康奥秘的旅途中&#xff0c;维生素作为人体不可或缺的微量营养素&#xff0c;扮演着至关重要的角色。它们虽不直接提供能量&#xff0c;却是酶促反应、细胞代谢、免疫功能乃至心理健康的基石。今天&#xff0c;让我们一同深入探讨人体所需补充的维生素&#xff0c;这些…

Keepalived高可用和Haproxy负载均衡

一、概念 简介 keepalived是集群管理中保证集群高可用的一个服务软件&#xff0c;用来防止单点故障。 工作原理 keepalived是以VRRP协议为实现基础的&#xff0c;N台路由器组成一个路由器组。master上有一个对外提供服务的vip&#xff0c;master会向backup进行发送组播&…

4.stable-diffusion-webui1.10.0--图像修复(adetailer)插件

ADetailer是Stable Diffusion WebUI的一个插件&#xff0c;它通过深度学习模型智能检测图像中的人脸、手部及身体等关键部位&#xff0c;并自动进行重绘修复&#xff0c;使得生成的图像更加自然、符合预期。 ADetailer插件主要应用于图像的细节增强、降噪和修复&#xff0c;特…

Git-bug001 VScode中git clone的地址首次push报错push.default is unset

问题现象&#xff1a; 解释&#xff1a;Git 提醒用户 push.default 配置未设置&#xff0c;且其隐式值已在最新版本的 Git 中更改 解决-输入&#xff1a;git config --global push.default simple 然后重新push就可以了 然后继续报问题&#xff1a;点击OK即可 解释&#xff1…