大一C语言课设 服装销售系统 代码实现与项目总结

问题分析

服装信息管理及销售管理系统。方便对库存服装的信息管理和添加新服装数据,同时兼具库存数量管理功能。

功能实现

1、建立服装信息库,包括:服装代码、型号、规格、面料、颜色、单价、数量;
2、建立销售信息库,包括:服装代码,数量,日期,售价,小记
3、程序分为两大模块:库存模块和销售模块。库存模块主要用于对服装信息的增加、删除、修改。销售模块主要用于管理库存数量;
4、浏览:管理员可以查询库存信息和销售信息。
5、查找或修改:可以通过编号查找服装。可以根据编号进行修改、删除信息;
6、登记:可以通过编号登记库存情况、销售情况,同时改变库存信息。

现在来看,这个项目最大的难点就是利用c语言的文件系统实现同时修改多个文件,例如服装下单时,要先检查剩余库存;购买时不仅要扣减库存,还要写入购买记录。在没有数据库时实现这一功能比较麻烦。

代码实现

/*该程序运行编译器为Dev-C++ 5.4.0 ,64位系统*/ 
#include<stdio.h>
#include<string.h>
typedef struct _clothes{int nu;			//nu as number,服装代码 char name[30];	char si[10];		//si as sizechar ma[20];	//ma as materialchar co[10];	//co as colorfloat pr;		//pr as prizeint qu;			//qu as quantity
}Clothes;			//建立clothes结构类型,方便进行读写
typedef struct _sale{int rn;			//rn as real number,means the sequence of infomationint nu;			//nu as number,服装代码 int qu;			//qu as quantitychar da[9];		//da as date,save by 8 bytes char;float pr;		//pr as prizechar note[20]; 
}Sale;				//建立sale结构类型,方便进行读写 
//键盘输入新的库存信息
void cgetlist(Clothes aClo[],int number,int innumber){				 int i;for(i=0;i<number;i++,innumber++){								//输入number个数据 printf("服装代码为(系统自动分配):%d\n",innumber+1);aClo[i].nu=innumber;printf("\t输入型号:");scanf("%29s",aClo[i].name);printf("\t输入规格:");scanf("%9s",aClo[i].si); printf("\t输入面料:");scanf("%19s",aClo[i].ma);printf("\t输入颜色:");scanf("%9s",aClo[i].co);printf("\t输入单价:");scanf("%f",&aClo[i].pr);printf("\t输入库存数量:");scanf("%d",&aClo[i].qu);}
}
//键盘输入新的销售信息 
int sgetlist(Sale aSal[],int number,int innumber){					int i;for(i=0;i<number;i++,innumber++){printf("销售记录代码为:%d\n",innumber+1); aSal[i].rn=innumber;printf("\t输入服装代码:");scanf("%d",&aSal[i].nu);printf("\t输入销售数量:");scanf("%d",&aSal[i].qu);if(reducecheck(aSal[i].nu,aSal[i].qu)==-1)	{return -1;}	//检查库存是否足够,不够就返回,中止后面的输入 printf("\t输入日期:");scanf("%s",aSal[i].da); printf("\t输入售价:");scanf("%f",&aSal[i].pr);printf("\t小记:");scanf("%s",aSal[i].note);}return 0;														//不然就不返回值 
}
//将cgetlist输入的信息写入文件,与文件直接通信
int save(Clothes aClo[],int number){								 int ret=-1;														//作为是否成功写入的标记值 FILE*fp=fopen("clothes.data","a");								//尝试用追加打开,用w打开的话会把之前的数据全部清除 if(!fp){														//如果打开失败(假设是由于没有可打开的文件) fclose(fp);													//就关闭文件指针 FILE*fp=fopen("clothes.data","w");							//再用w打开来建立文件 fclose(fp);													//然后关闭指针 FILE*fpc=fopen("clothes.data","a");							//再用追加打开 ret=fwrite(aClo,sizeof(Clothes),number,fpc);				//写入aClo结构体数组,同时给ret一个值 fclose(fpc);												//关闭指针 }else if(fp){													//如果用追加方式打开了 ret=fwrite(aClo,sizeof(Clothes),number,fp);					//就直接写入 fclose(fp);}return ret==number;												//返回number 
}
//将sgetlist输入的信息写入文件,与文件直接通信 
int ssave(Sale aSal[],int number){									int ret=-1;													//作为是否成功写入的标记值FILE*fp=fopen("sale.data","a");								//同save,用w或a打开 if(!fp){fclose(fp);FILE*fp=fopen("sale.data","w");fclose(fp);FILE*fpc=fopen("sale.data","a");ret=fwrite(aSal,sizeof(Sale),number,fpc);fclose(fpc);}else if(fp){ret=fwrite(aSal,sizeof(Sale),number,fp);fclose(fp);}return ret==number;
}
//读取打印库存数据 
void read(FILE*fp,int index){										fseek(fp,index*sizeof(Clothes),SEEK_SET);						//fp指针移动到指定数据的位置 Clothes clo;													//建立结构体用来接受文件里的数据 if(fread(&clo,sizeof(Clothes),1,fp)==1){						//从文件读取数据,如果不成功的话就不输出到控制台 printf("服装代码:%d",index+1);								//用printf输出clo里的数据 printf("\t型号:%s\n",clo.name);printf("\t规格:%s\n",clo.si);printf("\t面料:%s\n",clo.ma);printf("\t颜色:%s\n",clo.co);printf("\t单价:%.2f\n",clo.pr);printf("\t数量:%d\n",clo.qu);}
}
//read函数的封装,无形参,操作界面里调用 
void reads(){														FILE*fp=fopen("clothes.data","r");								//只读方式打开库存信息 if(fp){															//如果成功打开 fseek(fp,0L,SEEK_END);										//移动到文件末位 long size=ftell(fp);										//读取文件末位的数据量 int number=size/sizeof(Clothes);							//计算有几条数据 int index=0;												//让用户输入查找的服装编号 printf("共有%d条数据,输入要检查的服装代码:",number);		scanf("%d",&index);											//输入服装编号 read(fp,index-1);											//系统分配服装编号为了不出现0号,加了一,因此这里减一 fclose(fp);}getchar();														//scanf后输入了回车,这里接收掉 screen();														//回到操作界面 
}
//这里和read基本一样,但是打印的是销售数据 
void sread(FILE*fp,int index){										fseek(fp,index*sizeof(Sale),SEEK_SET);Sale sal;if(fread(&sal,sizeof(Sale),1,fp)==1){printf("销售记录编号:%d\n",index+1);printf("\t服装代码:%d\n",sal.nu);printf("\t销售数量:%d\n",sal.qu);printf("\t日期:%s\n",sal.da);printf("\t售价:%.2f\n",sal.pr);printf("\t小记:%s\n",sal.note);}
}
//sread的封装,和reads基本一样 
void sreads(){														FILE*fp=fopen("sale.data","r");if(fp){fseek(fp,0L,SEEK_END);long size=ftell(fp);int number=size/sizeof(Sale);int index=0;printf("共有%d条数据,输入要检查的销售记录编号:",number);scanf("%d",&index);sread(fp,index-1);fclose(fp);}getchar();screen();
}
//库存信息添加函数
void add(){															int number=0,innumber=0;										//number是用来遍历输入数据的,innumber是系统分配的代码 printf("要添加的服装种类数量:");scanf("%d",&number);Clothes aClo[number];											//建立number个aClo结构体 FILE*fp=fopen("clothes.data","r");								//以只读打开库存数据,以下这段代码是为了分配服装代码 if(fp){																	fseek(fp,0L,SEEK_END);										//移动到文件末尾 long size=ftell(fp);										//读取文件长度 innumber=size/sizeof(Clothes);								//计算已有的结构体数量 fclose(fp);													//关闭文件 }cgetlist(aClo,number,innumber);									//用getlist获取新库存信息 if(!save(aClo,number)){											//保存文件,如果返回-1的话 printf("服装入库失败\n");									//打印失败 }else printf("服装入库成功\n");									//否则打印成功 getchar();														//接受scanf输入的回车 screen();														//返回操作界面 
}
//销售信息添加函数,和add的实现方式基本一样 
void sadd(){														int number=0,innumber=0;printf("要添加的销售记录条数:");scanf("%d",&number);Sale aSal[number];												//建立number个aSal结构体 FILE*fp=fopen("sale.data","r");if(fp){fseek(fp,0L,SEEK_END);										//这段代码作用是读取有多少个数据 long size=ftell(fp);										//这样就可以由系统自动分配下一个编号 innumber=size/sizeof(Sale);fclose(fp);}if(sgetlist(aSal,number,innumber)==-1){							//如果sgetlist返回-1,说明库存不足 printf("^销售信息写入失败\n");}else{															//如果没有返回-1,调用ssave尝试保存 if(!ssave(aSal,number)){									//保存sgetlist输入的aSal结构体 printf("*销售信息添加失败\n");							}else printf("^销售信息添加成功\n");} getchar();														//接受scanf输入的回车screen();
}
//检查库存是否足够和修改库存,x是服装编号,y是销售数量
int reducecheck(int x,int y){FILE*fpr=fopen("clothes.data","r+");							//只读方式打开库存信息 if(fpr){						 								//如果成功打开Clothes clo[1];												//建立结构体用来接受文件里的数据			 fseek(fpr,(x-1)*sizeof(Clothes),SEEK_SET);					//fp指针移动到指定数据的位置								 fread(&clo,sizeof(Clothes),1,fpr);							//读取文件中的数据 if(clo[0].qu<y){											//如果库存不足 printf("库存不足 ");return -1;												//返回-1到getlist,getlist会返回-1到sadd }else {									printf("\t^^^库存充足\n");			clo[0].qu=clo[0].qu-y;									//将clo中的数量值修改为销售后的数量 fseek(fpr,(x-1)*sizeof(Clothes),0);						//移动到数据位置 fwrite(clo,sizeof(Clothes),1,fpr);						//用aclo覆盖原来的数据 fclose(fpr);											//关闭clothes.data,此时sale.data依然打开 }}													
}
//库存信息修改函数的实现,有形参
void change(FILE*fp,int index){Clothes aClo[1];												//建立临时结构体aClo接收数据 cgetlist(aClo,1,index);											//用cgetlist写入数据 到aClo fseek(fp,index*sizeof(Clothes),0);								//指针移动到数据位置 fwrite(aClo,sizeof(Clothes),1,fp);								//保存aClo到文件中 
}
//库存信息修改函数的封装,无形参
void changes(){FILE*fp=fopen("clothes.data","r+");								//只读方式打开库存信息 if(fp){															//如果成功打开 fseek(fp,0L,SEEK_END);										//移动到文件末位 long size=ftell(fp);										//读取文件末位的数据量 int number=size/sizeof(Clothes);							//计算有几条数据 int index=0;												//让用户输入修改的服装编号 printf("共有%d条数据,输入要修改的服装代码:",number);		scanf("%d",&index);											//输入服装编号 change(fp,index-1);											//调用修改函数,系统分配服装编号时为了不出现0号,加了一,因此这里减一 fclose(fp);}getchar();														//scanf后输入了回车,这里接收掉 screen();
}
//删除函数用的getlist
void dcgetlist(Clothes aClo[],int innumber){aClo[0].nu=innumber;strcpy(aClo[0].name,"此处数据已删除"); 							//为了查找系统正常工作,不清空数据,而是替换为空 strcpy(aClo[0].si,"");strcpy(aClo[0].ma,"");strcpy(aClo[0].co,"");aClo[0].pr=0;aClo[0].qu=0;
}
//删除函数
void del(FILE*fp,int index){Clothes aClo[1];												//建立临时结构体aClo dcgetlist(aClo,index-1);										//将aClo变为删除后的特殊结构体 fseek(fp,index*sizeof(Clothes),0);								//指针移动到数据位置 fwrite(aClo,sizeof(Clothes),1,fp);								//把aClo写入文件 
}
//删除函数的封装,无形参,操作界面里调用
void dels(){FILE*fp=fopen("clothes.data","r+");								//只读方式打开库存信息 if(fp){															//如果成功打开 fseek(fp,0L,SEEK_END);										//移动到文件末位 long size=ftell(fp);										//读取文件末位的数据量 int number=size/sizeof(Clothes);							//计算有几条数据 int index=0;												//让用户输入删除的服装编号 printf("共有%d条数据,输入要删除的服装代码:",number);		scanf("%d",&index);											//输入服装编号 del(fp,index-1);											//系统分配服装编号为了不出现0号,加了一,因此这里减一 fclose(fp);}getchar();														//scanf后输入了回车,这里接收掉 screen();
}
//操作界面函数
int screen(){char a;printf("N-服装信息登记,M-服装信息修改,R-服装信息查找\n");printf("D-服装信息删除,S-服装销售登记,G-销售信息查找\n");printf("Q-退出系统\n");printf("输入字母来决定操作:");scanf("%c",&a);switch(a){case'N':add();break;case'M':changes();break;case'R':reads();break;case'D':dels();break;case'S':sadd();break;case'G':sreads();break;}																		
}
int main(){screen();
}

项目总结(大一时所写原文,未改动)

首先,从结果来看,整个程序并不复杂,结构很简单,但是设计过程中依然碰到了很多问题并严重延长了开发周期,这一方面时体现了对c语言仍然不够熟练,另一方面也表明对程序设计难度的低估。
先来说说几个遇到的问题。首先在还没开始时就犯了难。要如何能够把数据写进文件,还能按原样一个一个读出来呢?又要如何实现查找呢?最早还没开始做时,设想过用链表和二叉树来写,但实际操作才发现文件里实现不了。后来想过用“#”等符号作为分隔符,但是这样好像也很难实现按型号、规格等一条条输出,而且修改很困难。后来通过进一步学习才发现用二进制写入可以实现写入结构体和链表。现在写入的问题解决了,接下来就要解决查找的问题。一开始想法是把文件里内容全部读进内存再用strstr找,但这里也有问题,一是strstr查找精度不高,比如要查找Tom,函数可能找到Toma就返回了。其次,找到之后,要输出接下来的数据也比较难。最终决定,由系统自动分配专门编号,再由这一编号来进行查找、修改和删除等。这一决定也使得之后的销售系统对库存进行修改的操作变得更加简单。
开始的添加和查找函数都比较简单,所以遇到的困难不多。这里有一点,增加函数要么用“w”打开,要么用“a”打开,用w的话,之后再打开文件夹添加库存时,会直接清空以前的文件;而用a打开的话,则无法创建文件夹。最后是设置了一个if语句来判断是否存在文件。修改就有些麻烦了。考虑到删除也可以看作修改,就先从删除函数开始。因为要按照上文的按编号查找的话,是不能直接清空一个结构体的,这样会直接导致后面的编号全部乱掉。所以采取了把数据替换为空字符的做法。这样虽然不能直接减少空间,但考虑到本身就是数据量很小的纯字符数据,所以这样影响也不大。然后就是删除函数的实现。首先肯定不能用w方法打开,这样一打开就什么都没了。然后用过用a打开,结果即使用fseek把指针移动到指定位置,也只能写到文件末尾。最后发现,用“r+”方法打开就可以实现覆盖到指定位置。之后还犯了一个小错误,直接把新字符串=原字符串,结果出现了乱码。然后才发现要用strcpy函数。解决了删除函数之后,修改函数也就不难了,只需要把删除里面的空白结构体换成用户输入结构体即可。
然后是销售管理部分。添加和查找销售记录都比较简单,和上面一样,只要修改一下结构体就可以。但涉及到和库存函数的通信,就有些麻烦了。当我们输入完服装编号和销量后,就应该立刻判断是否库存不够,如果不够就立即弹出信息并返回;同时输入的数据也要及时清除,防止混进下一次输入造成乱码。于是这里用了一个检测函数,并且可以直接return退出。但是这个检测函数也没那么简单,碰到了很多麻烦。同时检测函数也要担负把销售后剩余库存信息写进库存文件的功能。最终的解决办法是,再检测函数里用另一个文件指针打开库存文件,读取这里的信息,检测是否库存足够,足够的话就把原有信息修改后,覆盖到原来的位置。
最后是操作界面函数。以上的函数都能正常工作,但是放到switch里面时,要么不能打开,要么直接退出,要么显示两次操作界面。最后发现,每个函数都要用scanf输入数据,这个过程会往缓冲区里写入一个回车符,随后它就直接输入到了操作界面,这就引发了上面的诸多问题。最后的解决办法是往每个函数末尾添加了一个getchar()来接收回车符。
通过这个项目的编写,认识到了以下几个点:

  1. 对C语言的很多操作,尤其是对文件的操作,其实还并不了解。此外,用等号给字符数组赋值的错误操作也出现了。
  2. C++的确是对C语言的非常重要的扩展。例如String类,就可以直接用等号赋值;更重要的是,上面的服装信息系统和销售信息系统本质上非常相似,其实完全可以用类来实现。以及一些函数,只是一些参数有变化,应该也可以用模板函数实现。
  3. 数据库是非常伟大的发明。用C自带的文件通讯还是比较麻烦的,而且经常会有一些错误操作导致数据损坏。用数据库的话,不仅可以方便的储存一些更高级的数据结构,同时在一些方面也更安全。

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

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

相关文章

lua拼接字符串

在Lua中&#xff0c;拼接字符串可以使用多种方法&#xff0c;包括使用..操作符、string.format函数&#xff0c;或者使用循环和table.concat函数。下面是一些常见的字符串拼接示例&#xff1a; 使用..操作符 local part1 "Hello" local part2 "World" lo…

类和对象(中)【类的6个默认成员函数】 【零散知识点】 (万字)

类和对象&#xff08;中&#xff09; 1.类的6个默认成员函数 如果一个类中什么成员都没有&#xff0c;简称为空类。 空类中真的什么都没有吗&#xff1f;并不是&#xff0c;任何类在什么都不写时&#xff0c;编译器会自动生成以下6个默认成员函数。 默认成员函数&#xff1…

【Python】如何使用 Python 自动发送每日电子邮件报告

人不走空 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌赋&#xff1a;斯是陋室&#xff0c;惟吾德馨 目录 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌…

整合Spring Boot 框架集成Knife4j

本次示例使用Spring Boot作为脚手架来快速集成Knife4j,Spring Boot版本2.3.5.RELEASE ,Knife4j版本2.0.7 POM.XML完整文件代码如下&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0…

智能合约引领:探索Web3的商业革新之路

随着区块链技术的迅速发展&#xff0c;智能合约作为其重要应用之一&#xff0c;正在逐步改变着商业世界的格局。Web3作为下一代互联网的代表&#xff0c;正引领着智能合约在商业领域的广泛应用和创新。本文将深入探讨智能合约在Web3中的作用&#xff0c;以及智能合约如何引领着…

【正在线上召开】2024机器智能与数字化应用国际会议(MIDA2024),免费参会

【ACM出版】2024机器智能与数字化应用国际会议&#xff08;MIDA2024&#xff09; 2024 International Conference on Machine Intelligence and Digital Applications 【支持单位】 宁波财经学院 法国上阿尔萨斯大学 【大会主席】 Ljiljana Trajkovic 加拿大西蒙菲莎大…

【JavaScript脚本宇宙】跨越边界:挖掘JavaScript验证库的无限可能

引领技术潮流&#xff1a;六大顶级JavaScript验证库解析 前言 在现代编程中&#xff0c;数据验证是一个非常重要的环节。本文将探索六种不同的JavaScript数据验证库&#xff0c;分别介绍它们的概述&#xff0c;主要特性&#xff0c;使用示例和使用场景。 欢迎订阅专栏&#x…

PHP身份证真假API在线文档、身份证ocr识别、身份证三要素人像核验

翔云PHP身份证真假API文档&#xff0c;为开发者提供了一个详尽的操作指南和接口说明。通过简洁明了的文档&#xff0c;开发者可以轻松集成身份证验证功能到各类网站或应用程序中&#xff0c;无需从零开始编写复杂的验证逻辑&#xff0c;大大缩短了开发周期&#xff0c;降低了技…

使用画图工具修改图片文字

方法思路&#xff1a; 使用背景色将需要修改的文字覆盖&#xff0c;然后在原来的地方加入修改后的字。 第一步&#xff1a; 选中图片后右键&#xff0c;选择“编辑”&#xff08;默认会使用画图工具打开&#xff09; 第二步&#xff1a; 选取颜色选取器&#xff0c;如下图 使…

cpprestsdk https双向认证小测

概述 因项目需要在系统中引入https双向认证&#xff0c;由于程序使用C/C和cpprestsdk库编写&#xff0c;从网上经过一顿检索折腾&#xff0c;总算测试通过&#xff0c;故而博文记录用以备忘。 系统环境 Ubuntu 22.04.3 LTS libcpprest-dev&#xff08;jammy,now 2.10.18-1bu…

【Text2SQL 论文】DIN-SQL:分解任务 + 自我纠正 + in-context 让 LLM 完成 Text2SQL

论文&#xff1a;DIN-SQL: Decomposed In-Context Learning of Text-to-SQL with Self-Correction ⭐⭐⭐⭐ NeurIPS 2023, arXiv:2304.11015 Code: Few-shot-NL2SQL-with-prompting | GitHub 文章目录 一、论文速读1.1 Schema Linking Module1.2 Classification & Decompo…

【每日刷题】Day52

【每日刷题】Day52 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;每日刷题&#x1f34d; &#x1f33c;文章目录&#x1f33c; 1. 2965. 找出缺失和重复的数字 - 力扣&#xff08;LeetCode&#xff09; 2. 350. 两个数组的交集 II …

kaggle竞赛系列基于图像对水稻分类代码案例

目录 依赖环境 代码 导入依赖包 定义数据集路径&#xff1a; 创建训练集、验证集和测试集的文件夹&#xff1a; 代码的作用&#xff1a; 设置新的数据集路径与类别名称 代码的作用&#xff1a; 定义数据预处理和增强变换&#xff1a; 代码的作用&#xff1a; 定义数…

【源码】多语言H5聊天室/thinkphp多国语言即时通讯/H5聊天室源码/在线聊天/全开源

多语言聊天室系统&#xff0c;可当即时通讯用&#xff0c;系统默认无需注册即可进入群聊天&#xff0c;全开源 【海外聊天室】多语言H5聊天室/thinkphp多国语言即时通讯/H5聊天室源码/在线聊天/全开源 - 吾爱资源网

每日5题Day13 - LeetCode 61 - 65

每一步向前都是向自己的梦想更近一步&#xff0c;坚持不懈&#xff0c;勇往直前&#xff01; 第一题&#xff1a;61. 旋转链表 - 力扣&#xff08;LeetCode&#xff09; /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;…

STM32学习和实践笔记(32):电容触摸按键实验

1.电容触摸按键原理介绍 触摸按键与传统的机械按键相比&#xff0c;不仅美观而且耐用、寿命长&#xff0c;它颠覆了传统意义上的机械按键控制&#xff0c;只要轻轻触摸&#xff0c;就可以实现按键开关的控制、量化调节甚至方向控制。触摸按键已广泛应用于手机、DVD、洗衣机等消…

宿舍管理系统带文档java项目基于springboot+vue的宿舍管理系统

文章目录 宿舍管理系统一、项目演示二、项目介绍三、八千字项目文档四、部分功能截图五、部分代码展示六、底部获取项目源码和8000字论文参考&#xff08;9.9&#xffe5;带走&#xff09; 宿舍管理系统 一、项目演示 宿舍管理系统 二、项目介绍 基于springbootvue的前后端分…

MVC、MVP 和 MVVM 架构总结

MVC、MVP 和 MVVM 是常见的软件架构模式&#xff0c;主要用于组织应用程序的结构&#xff0c;特别是在用户界面和业务逻辑之间进行分离。以下是对它们的详细解释&#xff0c;包括它们的差异、优缺点。 MVC&#xff08;Model-View-Controller&#xff09; 结构 Model&#xf…

C++的继承(十一):私有继承和受保护的继承

但凡用过C的人都知道&#xff1a;私有继承的成员在派生类里均为私有&#xff0c;受保护的继承公有和受保护的成员在派生类里为受保护。另外C不对私有继承和受保护的继承的派生类指针自动转化为基础类。 #include <stdio.h> struct X {int a;X():a(9) {}int sqare() {ret…

5.nginx平滑升级

nginx平滑升级 一、nginx平滑升级1、下载新版本的安装包2、以之前的安装参数来编译新版本软件3、将新版本的nginx拷贝到安装目录4、启动新版本进程5、平缓关闭旧工作进程6、清理旧版本的nginx 一、nginx平滑升级 USR2 启动新版本进程 WINCH 平缓关闭旧工作进程 1、下载新版本…