大一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.pswp.cn/bicheng/20021.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/20021.shtml
英文地址,請注明出處:http://en.pswp.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、下載新版本…