基于C++实现(控制台)仓库管理系统【100010021】

news2024/11/15 23:32:46

1题目与要求

1.1问题描述

某电子公司仓库中有若干批次的同一种电脑,按价格、数量来存储。要求实现功能:

  1. 初始化 n 批不同价格电脑入库;
  2. 出库:销售 m 台价格为 p 的电脑;
  3. 入库:新到 m 台价格为 p 的电脑;
  4. 盘点:电脑的总台数,总金额,最高价,最低价,平均价格。

注:每个数据元素含有价格与数量;同一价格的电脑存储为一个数据元素。

1.2本系统涉及的知识点

仓库管理系统可以使用顺序表、有序表、单链表、有序循环链表等实现,本设计采用有序表实现。

所谓有序表,是指这样的线性表,其中所有的元素以递增或递减方式有序排列。

首先要指出的是,有序表是基于顺序表而延伸出来的一种数据结构,其共同点是用一组地址连续的存储单元依次存储线性表的数据元素。

其次,是有序表的独特之处,它其中的数据元素按照一定的顺序有序排列。仓库管理系统适合采用有序表,原因是可以按照商品的价格或数量进行有序

排列,方便用户比对价格、数量。

1.3功能要求

  1. 初始化仓库:初始化 n 批不同型号的电脑入库;
  2. 入库:新到 m 台价格为 p 的电脑;
  3. 出库:销售 m 台价格为 p 的电脑;
  4. 盘点仓库:列出仓库的关键数据:电脑的总台数、总金额、最高价、平均价格等;

按照有序表的特点以及所使用的编程语言(C++)的特性,本程序还提供了以下功能:

  1. 查询某一型号的电脑的价格、数量;
  2. 重新对仓库数据按照一定规则排序;
  3. 导出仓库数据到外部文件;
  4. 从外部文件导入数据,以初始化仓库。

2 功能设计

2.1数据结构定义

一、基本数据元素:电脑

typedef struct computer { char type[50]; // 型号 
    double price; // 价 格 
    int number;	// 数量 
} Computer, ElemType;

基本数据元素电脑(Computer/ElemType)采用结构体表示,用于存储某一类电脑的信息:型号(type[50])、价格(price)、库存数量(number)。

二、数据结构:有序表

typedef struct {
ElemType *elem;	// 基地址 
    int length;	// 当前有效数据的个数 
    int listsize;	// 当前存储容量
bool isInit{false}; // 有序表是否已经初始化 
    int sortWay{1};	// 有序表的排序方式 
} SqList;

数据结构有序表(SqList)由以下几个部分组成:

  1. 数组指针 elem 指示有序表的基地址;
  2. length 指示有序表的当前有效数据个数(长度);
  3. listsize 指示有序表当前分配的存储空间大小,一旦因插入数据元素(Computer)而空间不足时,可进行再分配;
  4. isInit 指示有序表是否已经初始化(即是否有一个确定的基地址);
  5. sortWay 指示有序表的排序方式,按照值的不同,对应的有序表排序方式也不同。本程序具体设计了以下四种排序方式:1-按照价格升序、2-按照价格降序、3-按照数量升序、4-按照数量降序。

整体的数据结构如下图所示:

在这里插入图片描述

图 1.1 有序表数据结构

2.2模块图

一、入库

入库有两种方式,一是在仓库中已有和待入库电脑型号相同的数据,此时, 检查给出的价格是否与仓库中一致,若一致,同意用户的入库操作。然后只需更改仓库中此种电脑型号的数量。

示意图如下:

在这里插入图片描述

图 2.1 入库仓库中已有型号的电脑

第二种方式,入库一种新型号的电脑,则应该按照有序表的排序方式

(sortWay)在正确位置插入元素。示意图如下:

在这里插入图片描述

图 2.2 入库一种新型号的电脑

二、出库

可以出库的前提是,在仓库中有待出库型号的电脑且仓库中的库存数量大于等于待出库数量。

第一类情况,待出库电脑的数量在库存中充足(即库存数量大于待出库数量),此时只需更改相应的数据元素。

示意图如下:

在这里插入图片描述

图 2.3 出库电脑数量充足

第二类情况,此种型号的电脑恰好全部出库完,则需要删除相应的数据元素。示意图如下:

在这里插入图片描述

图 2.4 此种型号的电脑恰好全部出库完

3 功能代码

3.1初始化动态顺序表

有序表的数据结构是基于顺序表实现的,所以在进行一切操作前,应当初始化一个空的动态顺序表。

代码如下:

Status InitSqList(SqList &L, int n) {
auto listsize{((n / 10) + 1) * 10}; // 确定顺序表初始内存占用空间 
    L.elem = new ElemType[listsize];	// 分配基地址、顺序表内存 
    if (!L.elem)	// 内存不足 
        return OVERFLOW;
L.length = 0;	// 此时顺序表还没有元素,L.length 为 0
L.listsize = listsize; return OK;
}

有序表初始分配的内存空间(listsize)并没有简单采用一个常数大小(如 10

个 ElemType 字节),这样不用限制用户输入的电脑类型最大个数,对用户友好。具体是通过给定的 n,计算表达式((n/10)+1)*10,使得初始分配的内存为 10 的整数倍大小的 ElemType 字节,比如 n 为 12,表达式((n/10)+1)*10 则为 20。

需要注意的是,初始化动态顺序表时,还暂无数据元素,L.length 应为 0。

3.2创建(初始化)仓库

创建仓库的前提是,已经初始化过一个空的动态顺序表,这个检测可以在主函数中完成。

创建有序表式的仓库步骤:

  1. 输入 n 个数据元素,存储到顺序表中;
  2. 对已创建的顺序表按照有序表的排序方式(L.sortWay)进行快速排序。
  3. 更新有序表的相应参数(length、isInit、sortWay)

代码如下:

void CreateWarehouse(SqList &L, int n, int sort_way) {
cout << "请输入这" << n << "种电脑各自的型号、单价、总数:(以空格分隔)"
<< endl;
// 输入n 个数据元素 
    for (int i = 0; i < n; i++)
cin >> L.elem[i].type >> L.elem[i].price >> L.elem[i].number;
// 按照 sort_way 对刚创建的顺序表排序 
    switch (sort_way) { case 1:
// 按价格升序 
            sort(L.elem, L.elem + n, cmp1); break;
case 2:
// 按价格降序 
            sort(L.elem, L.elem + n, cmp2); break;
case 3:
// 按数量升序 
            sort(L.elem, L.elem + n, cmp3); break;
case 4:
// 按数量降序 
            sort(L.elem, L.elem + n, cmp4); break;
default:
break;
}
// 更新L 的参数 
    L.sortWay = sort_way; L.length = n; L.isInit = true;
}

如果使用文件流创建仓库,那么代码略有不同,这部分属于 C++的知识。

不同代码(输入 n 数据元素)如下:

string s;
// 从文件流输入n 个数据元素 
for (int i = 0; i < n; i++) {
ImportFile >> L.elem[i].type >> L.elem[i].price >> L.elem[i].number; getline(ImportFile, s);
}

3.3显示仓库

顾名思义,就是将仓库的数据打印出来。代码如下:

// 显示仓库 
void PrintWarehouse(SqList L) { if (!L.length)
cout << "当前仓库没有数据!" << endl; else {
cout << "当前仓库数据如下:" << endl; string sort_way;
switch (L.sortWay) { case 1:
sort_way = "(按照价格升序)"; break;
case 2:
sort_way = "(按照价格降序)"; break;
case 3:
sort_way = "(按照数量升序)"; break;
case 4:
sort_way = "(按照数量降序)"; break;
default:
break;
}
cout << sort_way << endl;
cout << " 	                                                         " << endl;
cout << setLeft
<< setw(5) << "序号"
<< setw(20) << "型号"
<< setw(15) << "单价"
<< setw(15) << "数量"
<< endl;
cout << " 	                                                         " << endl;
for (int i = 0; i < L.length; i++) cout << setLeft
<< setw(5) << i + 1
<< setw(20) << L.elem[i].type
<< setw(15) << L.elem[i].price
<< setw(15) << L.elem[i].number
<< endl;
cout << " 	                                                         " << endl;
}
}

3.4入库

入库要考虑两种情况,第一种情况,仓库中已经有和待入库电脑相同型号的数据元素,那么需要先比较价格是否一致(不一致拒绝用户的入库操作),然后更改仓库中此种电脑数据元素的数量值。

第二种情况入库一种新型号的电脑,那么则要插入一个新的数据元素

(Computer)到仓库中,并且在插入之前还要检查有序表的内存空间(listsize) 是否充足,如果不足,则需要再分配有序表的内存大小,即为顺序表增加一个大小为存储 LISTINCREMENT 个数据元素的空间。然后,根据有序表的排序方式

(L.sortWay),找到可以插入元素的地址。插入时,先将该地址及以后的地址全部后移一位,接着将当前地址写入要入库的数据元素。

代码如下:

Status Enter(SqList &L, const Computer &c) {
// 寻找仓库中是否已经有和 c.type 同类型的电脑 
    for (int i = 0; i < L.length; i++) {
if (strcmp(c.type, L.elem[i].type) == 0) {
if (c.price == L.elem[i].price) {	// 检查价格价格是否与
c.price 相等 
                L.elem[i].number += c.number;
return OK;
} else {
cout << "提示:" << endl; showInfo(L.elem[i]); return ERROR;
}

}
}

// 入库一个新类型的电脑 
    if (L.length >= L.listsize) {	// 顺序表占用空间不足 
        // 申请新的基地址、内存空间 
        auto *newbase = (ElemType *) realloc(L.elem, (L.listsize +
LISTINCREMENT) * sizeof(ElemType)); if (!newbase)
return OVERFLOW;
L.elem = newbase;	// L 的基地址更改为 newbase
L.listsize += LISTINCREMENT;
}
// 按照 L.sort_way 对插入到顺序表中 
    int item{L.length}; // 确定要插入的位序 
    for (int i = 0; i < L.length; i++) { switch (L.sortWay) {
case 1: {
if (c.price < L.elem[i].price) { item = i;
goto change_sq;
}
}
break;
case 2: {
if (c.price > L.elem[i].price) { item = i;
goto change_sq;
}
}
break;
case 3: {
if (c.number < L.elem[i].number) { item = i;
goto change_sq;
}
}
break;
case 4: {
if (c.number > L.elem[i].number) { item = i;
goto change_sq;
}
}
break;
}
}
change_sq:
ElemType *q = &L.elem[item];
// 将q 及q 以后的元素全部后移一位 
    for (ElemType *p = L.elem + L.length - 1; p >= q; p--)
*(p + 1) = *p;
// 将新元素赋给q
*q = c; L.length++;
return ok;
}

要注意的是如果是入库一种新型号的电脑,完成操作后,应当将有序表的长度加 1(L.length++)。

3.5出库

出库要考虑以下几种情况:

1、 仓库中是否有待出库电脑的型号的相应数据元素,如果没有找到相应的电脑型号,则应当拒绝用户的出库操作;

2、 仓库中现有库存数量是否充足,满足出库要求,如果库存数量小于待出库数量,则应当拒绝用户的出库操作;

3、 如果库存数量大于待出库数量,那么只需更改相应数据元素的数量值;

4、 如果库存数量恰好等于待出库数量,那么此时这种型号的电脑应从仓库中“剔除”。具体操作是,找到该数据元素的地址,将该地址及以后的地址全部前移一位。最后,更新 L.length 参数。

代码如下:

Status Out(SqList &L, const char *type, int num) {
// 确定要出库元素的位序 
    int item{L.length + 1};
for (int i = 0; i < L.length; i++) {
if (strcmp(type, L.elem[i].type) == 0) { item = i;
break;
}
}
// 没有找到要出库元素的位序,说明在仓库中没有元素,返回错误 
    if (item > L.length) return -1;

// 确定要出库元素现有库存的数量是否可以出库 
    if (num < L.elem[item].number) {
// 正常出库 
        L.elem[item].number -= num; return OK;
} else if (num == L.elem[item].number) {
// 全部出库 
        cout << "提示:" << endl
<< L.elem[item].type << "型号的电脑已全部出库!" << endl;

// 将p 及p 以后的元素全部后移一位 
        for (ElemType *p = &L.elem[item + 1]; p <= &L.elem[L.length - 1]; p++) {
*(p - 1) = *p;
}
L.length--; return OK;
} else {
// 库存不足 
        cout << "提示:" << endl; showInfo(L.elem[item]); return ERROR;
}
}

3.6查询电脑数据

查询电脑数据,只需从基地址开始遍历,直到找到数据元素的型号和待查询的型号相同,那么返回电脑信息。

可以定义一个 item 参数,初始值为 L.length + 1,如果找到数据元素,则将其更新为数据元素的逻辑位序。如果遍历结束,item 都未更新,说明未找到。因为数据元素的最大逻辑位序是有序表的表长(L.length),所以判断是否找到数据元素的条件是:item > L.length。

代码如下:

void getInfo(SqList L, const char *type) {
// 确定要查找的电脑的元素位序 
    int item{L.length + 1};
for (int i = 0; i < L.length; i++) {
if (strcmp(type, L.elem[i].type) == 0) { item = i;
break;
}
}
if (item > L.length)
cout << "没有找到" << type << "型号的电脑" << endl; else {
cout << "信息如下:" << endl; showInfo(L.elem[item]);
}
}

3.7盘点仓库

从基地址开始遍历,求得关键数据:总台数(numSum)、总金额(priceSum)、最高价(priceMax)、最低价(priceMin)、平均价(priceAverage)。

代码如下:

void Check(SqList L) {
int numSum{0};
double priceSum{0.0}, priceMax{L.elem[0].price}, priceMin{L.elem[0].price}, priceAverage{0.0};
vector<char *> priceMaxComputer;	// 存储价格最高的电脑的类型名 
    vector<char *> priceMinComputer;	// 存储价格最低的电脑的类型名 
 
    if (!L.length) {
cout << "当前仓库没有数据!" << endl;
} else {
// 求总数、总金额、最高价、最低价 
        for (int i = 0; i < L.length; i++) { numSum += L.elem[i].number;
priceSum += L.elem[i].price * L.elem[i].number; priceMax = max(priceMax, L.elem[i].price); priceMin = min(priceMin, L.elem[i].price);
}
// 记录价格最高、最低的电脑类型名 
        for (int i = 0; i < L.length; i++) { if (L.elem[i].price == priceMax)
priceMaxComputer.push_back(L.elem[i].type); if (L.elem[i].price == priceMin)
priceMinComputer.push_back(L.elem[i].type);
}
// 求平均价 
        priceAverage = priceSum / numSum;
// 输出信息 
        cout << "盘点数据如下" << endl
<< "电脑的总台数: " << numSum << endl
<< "电脑的总金额: " << priceSum << endl
<< "电脑的最高价: " << priceMax << endl
<< "	+ 对应的型号是: "; for (const auto &c:priceMaxComputer)
cout << c << "\t"; cout << endl;
cout << "电脑的最低价: " << priceMin << endl
<< "	+ 对应的型号是: "; for (const auto &c:priceMinComputer)
cout << c << "\t"; cout << endl;
cout << "电脑的平均价格: " << priceAverage << endl;
}
}

这里定义了两个 char*向量(priceMaxComputer、priceMinComputer),用以存

储价格最高的电脑的类型名、最低的电脑的类型名,因为可能若干种型号的电脑都是最高价或最低价,所以使用 C++的向量数据结构比较合适。这样,可以显示出最高价、最低价相应的电脑类型名,对用户友好。

3.8重新对仓库排序

只需按照给定的排序方式,对仓库进行快速排序,然后更改 L.sortWay 参数为相应值。

代码如下:

cout << "请输入要重新对仓库排序的主要方式" << endl
<< "1. 按价格升序 2. 按价格降序" << endl
<< "3. 按数量升序 4. 按数量降序" << endl
<< "选择 1-4:";
auto select = input_number(1, 4); switch (select) {
case 1:
sort(L.elem, L.elem + L.length, cmp1); break;
case 2:
sort(L.elem, L.elem + L.length, cmp2); break;
case 3:
sort(L.elem, L.elem + L.length, cmp3); break;
case 4:
sort(L.elem, L.elem + L.length, cmp4); break;
default:
break;
}
L.sortWay = select;
cout << "重新排序成功!" << endl;

其中,4 种排序方式的代码如下:

// computer 排序方式:按价格升序 
bool cmp1(const Computer &a, const Computer &b) { return a.price < b.price;
}

// computer 排序方式:按价格降序 
bool cmp2(const Computer &a, const Computer &b) { return a.price > b.price;
}

// computer 排序方式:按数量升序 
bool cmp3(const Computer &a, const Computer &b) {
return a.number < b.number;
}

// computer 排序方式:按数量降序 
bool cmp4(const Computer &a, const Computer &b) { return a.number > b.number;
}

3.9导出仓库数据到文件

原理和显示仓库大同小异,只是多了文件流的操作。代码如下:

void output(SqList L, const string &filename) {
// 定义输出文件流 filename.txt
ofstream OutFile(filename + ".txt");
// 输出文件头,用于下次输入时识别文件 
    OutFile << "Computer Warehouse Data" << endl; if (!L.length)
OutFile << "no data" << endl; else {
OutFile << "The information is as follows:" << endl; switch (L.sortWay) {
case 1:
OutFile	<<	"Sort	Way:	1	(Ascending by price)" << endl;
break;					
case 2:					
OutFile	<<	"Sort	Way:	2	(Descending by price)" << endl;
break;					
case 3:					
OutFile	<<	"Sort	Way:	3	(Ascending by number)" << endl;
break;					
case 4:					
OutFile	<<	"Sort	Way:	4	(Descending by number)" << endl;
break;					
default:					
break;					
}
OutFile << "Total Type: " << L.length << endl;

// 输出数据信息 
        for (int i = 0; i < L.length; i++) OutFile << L.elem[i].type << " "
<< L.elem[i].price << " "
<< L.elem[i].number
<< endl;
// 关闭文件 
        OutFile.close();
}
}

4 调试与测试

注意:本设计使用的编译器是 G++ 8.1.0,在 Windows 平台上编译、运行成功。编译命令为:“g++ main.cpp sqlist.cpp -o main”(不含引号)。

4.1调试分析

一、创建仓库

为方便用户操作,本程序可以导出仓库数据到文件,然后在下次操作时,可以用此文件做仓库的初始化。这是在考虑到程序的友好性后增加的功能。

无论是手动创建还是从文件导入,方法是大同小异的。本模块时间复杂度:()(快速排序())

二、入库、出库、查询、盘点仓库

时间复杂度均为:()

考虑到程序的友好性,对入库、出库、查询的拒绝操作均给出具体信息。比

如,在出库时如果库存数量小于待出库数量,则先显示当前库存,然后提示库存数量不足。

三、其他

菜单和主函数设计中,由于经常需要检测输入数字是否在某一范围内,使得生成大量重复代码。于是,将这些代码设计成函数,增加了代码的可读性。并且考虑到,用户的误输入(非数字)会导致程序崩溃,设计了正则表达式匹配,检测用户输入。

函数代码如下:

// 输入 from 至 end 范围内的数字 
int input_number(int from, int end) { auto select{0};
string input;
regex r("[0-9]*"); // 正则表达式:数字 0-9,可以出现多次 
    while (true) {
cin >> input;
bool isNumber = regex_match(input,r);
if (!isNumber) // 如果 input 和正则表达式匹配 
            cout << "输入错误,请输入数字" << from << "-" << end << ":"; else {
select = atoi(input.c_str());
if (select < from || select > end)
cout << "输入错误,重新输入" << from << "-" << end << ":"; else
break;
}
}
return select;
}

另外一个是,如果用户在初始化仓库的情况下,进行入库、出库等操作,亦会导致程序崩溃。所以,后来在有序表中增加了一个参数 isInit,用于指示当前有序表是否已经初始化。在每次操作之前,检测是否已经初始化,这样避免了这一类型的崩溃。

4.2用户手册

启动本程序后,按照菜单的提示进行操作即可。注意:

1、 第一步必须先初始化仓库,否则,您无法进行其他的操作,将返回“仓库还未初始化!”。

2、 初始化仓库时,可以选择“2.从外部文件导入”,但前提是,该外部文件要存在,且是以前程序生成的导出合法文件。否则,不存在的文件将提示“没有文件/文件无法打开”,不是合法文件将提示“文件内容不符合要求”,这会导致初始化仓库失败。所以,请检查您输入的文件名和文件内容!

3、 建议在入库操作之前先显示仓库,确保增加仓库中某一电脑型号的数量时,输入的价格和仓库中一致;

4、 建议在出库操作之前先显示仓库,确保仓库中有您想要出库的电脑型号, 以及其数量充足;

5、 您可以选择菜单项“7.重新对仓库排序”,按照您喜爱的方式对仓库排序, 本程序提供了四种主要排序方式:1-按照价格升序、2-按照价格降序、3- 按照数量升序、4-按照数量降序

6、 建议每次结束程序前,导出仓库数据到文件,这样可以保存仓库数据, 方便下次操作。

4.3测试过程

本设计给出了一个输入文件 info.txt

Computer Warehouse Data The information is as follows:
Sort Way: 1 (Ascending by price) Total Type: 12
RedmiBook-14 3299 30
Dell-G5 5699 14
Surface-Pro-7 5788 20
Lenovo-Air14 5999 17
Lenovo-R7000 6057 12
Lenovo-Yoga14 6299 8
Lenovo-Pro14 6299 10
MiBook-Pro-15.6 6999 13
Dell-G3 6999 15
Dell-XPS13 8888 5
MacBook-Pro-13 9199 5
MacBook-Pro-16 17399 3

下面是各种操作的输出结果(截图):

  1. 菜单显示
    在这里插入图片描述
    图 4.1 菜单显示

  2. 初始化仓库

在这里插入图片描述

图 4.2 初始化仓库

  1. 显示仓库

在这里插入图片描述

图 4.3 显示仓库

  1. 入库
  2. 入库 Dell-G5 5699 2:

在这里插入图片描述

图 4.4 入库(1)

入库后显示仓库:

在这里插入图片描述

图 4.5 入库(2)

入库 Huawei-MateBook-X 8999 2:

在这里插入图片描述

图 4.6 入库(3)

入库后显示仓库:

在这里插入图片描述

图 4.7 入库(4)

  1. 出库

出库 Huawei-MateBook-X 2:

在这里插入图片描述

图 4.8 出库(1)

出库后显示:

在这里插入图片描述

图 4.9 出库(2)

  1. 查询

查询 Lenovo-Pro14

在这里插入图片描述

图 4.10 查询

  1. 盘点仓库

在这里插入图片描述

图 4.11 盘点仓库

  1. 重新对仓库排序

    按数量升序对仓库排序:

在这里插入图片描述

图 4.12 重新对仓库排序(1)

显示重新排序后的仓库:

在这里插入图片描述

图 4.13 重新对仓库排序(2)

5 总结

通过本次课程设计,在数据结构课程中所学到的顺序表基础上,实现了有序表,并通过基本数据元素(Computer)和数据结构(SqList)的设计,实现了简易的仓库管理系统。

在本次课程设计中,也学习到很多的 C++的知识,如 STL 中数据结构与算法的应用(vector、sort)、文件流(fstream)。

通过设计输入输出文件的功能,解决了以往繁琐的数据输入步骤。同时,也增加了程序的友好性。

通过输入检测、正则表达式匹配,解决了非法输入导致程序崩溃的问题。但限于编程能力,本程序仍存在某些问题,如初始化时,没有对输入相同型

号的数据做处理,这是程序的改进方向。

♻️ 资源

在这里插入图片描述

大小: 1.62MB
➡️ 资源下载:https://download.csdn.net/download/s1t16/87248076

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

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

相关文章

Burp Suite Professional 22.11.4 Crack

Burp Suite Professional 是网络安全测试人员的首选工具包。使用它来自动执行重复的测试任务 - 然后使用其专家设计的手动和半自动安全测试工具进行更深入的挖掘。Burp Suite Professional 可以帮助您测试 OWASP Top 10 漏洞 Burp Suite 被描述为通过 Port Swigger 提供给用户…

Python学习基础笔记三十七——collections模块

1、collections模块&#xff1a; 内置数据类型&#xff1a;列表list、字典dict、集合set、元组tuple。 Collections模块提供了另外的数据类型&#xff1a; 队列deque、双端队列&#xff1a;可以快速地从另外一侧追加和推出元素&#xff1b; namedtuple&#xff1a; 生成可以…

游戏开发53课 阴影

4.8 阴影 阴影的实现方式有很多种&#xff0c;消耗和效果各异。 4.8.1 贴图阴影 贴图的方式最简单&#xff0c;做法是制作一张阴影纹理&#xff0c;放到物体脚下&#xff08;下图&#xff09;&#xff0c;跟随物体一起运动。 贴图阴影渲染非常简单&#xff0c;只需要两个三角…

智能聊天机器人技术研究与应用

文章大纲 1. 聊天机器人简介聊天机器人进化历史聊天机器人核心技术2. 预训练模型与聊天机器人研究进展transfomer 架构回顾预训练对话模型3. 知识图谱与智能问答4. 智能聊天机器人应用实践5. 总结与展望正确使用chatGPT“高端的食材往往只需要最朴素的烹饪方式”参考文献与学习…

OpenFeign使用

OpenFeign使用 在微服务的架构中&#xff0c;传统的http客户端如Httpclient Okhttp HttpURLConnection RestTemplate WebClient 显然不适合。毕竟需要动态的获取服务地址&#xff0c;和进行负载均衡调用。 RPC框架 PC 全称是 Remote Procedure Call &#xff0c;即远程过程调…

NTC-Templates解析与采集H3C(Comware Version 7)信息

本文仅供本人参考与学习NTC-Templates模板使用。 设备环境&#xff1a;HCL S6850 S5820V2-54QS-GE&#xff1b;Version 7.1.075, Alpha 7571 模板采用&#xff1a;hp_comware_display_xxxxxxxx.textfsm 在线模板测试&#xff1a;https://textfsm.nornir.tech/ hp_comware_d…

httpbin的使用

在学习过程中我们想知道我们发送处的http格式是什么样子的&#xff0c;是否符合我们的要求&#xff0c;寻找一个这样的工具&#xff0c;满足验证测试需要。 Httpbin服务可以满足查看我发出去的请求到底是什么样子的。你需要查看请求中的那部分信息&#xff0c;就调用什么样的接…

【Qt入门第37篇】 网络(七)TCP(一)

导语 TCP即TransmissionControl Protocol&#xff0c;传输控制协议。与UDP不同&#xff0c;它是面向连接和数据流的可靠传输协议。也就是说&#xff0c;它能使一台计算机上的数据无差错的发往网络上的其他计算机&#xff0c;所以当要传输大量数据时&#xff0c;我们选用TCP协议…

游戏开发45课 性能优化4

2.6 粒子 粒子特效也是性能的一个大杀手&#xff0c;主要体现在&#xff1a; 每帧计算量大。涉及发射器/效果器/曲线插值等&#xff0c;耗费CPU性能。频繁操作内存。粒子在生命周期里&#xff0c;实例持续不断地创建/删除&#xff0c;即便有缓存机制下&#xff0c;依然避免不…

算法day43|1049,494,474

1049. 最后一块石头的重量 II class Solution:def lastStoneWeightII(self, stones: List[int]) -> int:summ sum(stones)target summ//2#dp下标和数组的定义,dp[j]代表的是最大价值dp [0]*15001#递归公式for i in range(len(stones)):for j in range(target,stones[i]-…

Zero-Shot Learning across Heterogeneous Overlapping Domains

极简论文阅读 摘要 a zero-shot learning approach:零样本学习方法。 natural language understanding domain&#xff1a;自然语言处理域。 a given utterance&#xff1a;给定的话语。 domains at runtime&#xff1a;运行时的域。 utterances and domains 给定话语和域。 …

Yolact

YOLACT 1.Abstract 原理: 生成一组 prototype masks (原型掩码) 个数&#xff08;nm&#xff09;可自定义&#xff0c;基于protonet的最后一组卷积核个数 通过一组 coefficients (掩码系数) 预测每个 instance mask (输出mask) 掩码系数由head层输出&#xff0c;shape为&…

微服务框架 SpringCloud微服务架构 微服务保护 32 隔离和降级 32.2 线程隔离

微服务框架 【SpringCloudRabbitMQDockerRedis搜索分布式&#xff0c;系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】 微服务保护 文章目录微服务框架微服务保护32 隔离和降级32.2 线程隔离32.2.1 线程隔离32.2.2 优缺点对比32 隔离和降级 32.2 线程隔离 32.…

算法7:平衡二叉树(AVLTree)

二叉排序树&#xff08;BST, Binary Sort Tree&#xff09;也称二叉查找树&#xff08;Binary Search Tree&#xff09;, 或二叉搜索树。 定义&#xff1a;一颗二叉树&#xff0c;满足以下属性&#xff1a; 左子树的所有的值小于根节点的值右子树的所有值大于根节点的值左、右…

关键词(四)

关键词&#xff08;四&#xff09;一.具有争议的关键词—goto二.“空”的关键字—void1.void为什么不能定义变量2.void修饰函数返回值和参数3.void指针一.具有争议的关键词—goto goto语句非常灵活&#xff0c;其实就是从goto这个位置直接跳转到goto后面的那个数据&#xff08;…

单例模式、工厂模式

单例模式、一、单例模式1.1 饿汉模式1.1.1 实现1.1.2 补充1.2 懒汉模式1.2.1 单线程版1.2.2 多线程版二、工厂模式一、单例模式 单例模式是校招中最常考的设计模式之一。 啥是设计模式&#xff1f; 设计模式好比象棋中的"棋谱"&#xff1a;红方当头炮&#xff0c;黑…

软件测试人员究竟要掌握什么技能?顺便说下行业现状

最近团队内部产品在做性能测试中碰到一个问题&#xff0c;不仅仅这次性能测试&#xff0c;其实这在我这近10年工作过程中&#xff0c;经常碰到一些类似的事情&#xff0c;今天拿出来一件事说叨说叨。 1、事情经过 月中上线了一个功能&#xff0c;该功能会应对峰值流量&#x…

【安卓APP源码和设计报告(含PPT)——订餐系统

订餐系统实验报告 课程名称&#xff1a; Android程序设计 班 级&#xff1a; 学 号&#xff1a; 姓 名&#xff1a; 任课教师&#xff1a; 程序功能与环境&#xff08;服务器&#xff0c;手机实物照片&#xff0c;自己拍&#xff09; 程序功能 餐厅订餐系统服务器&#…

45. python %占位符格式化处理

45. %占位符格式化处理 文章目录45. %占位符格式化处理1.课题导入2. %占位符概念3. %d格式化为整数3.1 %d将整数格式化到指定位置3.2 %d将浮点数格式化为整数1. 知识回顾&#xff1a;用int函数将浮点数转换为整数2. 用%将浮点数格式化为整数4. %s格式化为字符串4.1 %s将整数格式…

论文笔记-时序预测-Triformer

论文标题&#xff1a; Triformer: Triangular, Variable-Specific Attentions for Long Sequence Multivariate Time Series Forecasting 论文链接&#xff1a; https://arxiv.org/abs/2204.13767v1 代码链接&#xff1a; https://github.com/razvanc92/triformer 摘要 各种现…