軟體開發與創新作業
第一篇部落格
對已有專案進行分析,改進做二次開發
本次選用的是本平臺的圖書管理系統
(1)專案來源
原專案部落格:https://www.cnblogs.com/xinglichao/p/9064415.html
以下是原始碼
點選檢視程式碼
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define AVAILABLE 0
#define UNAVAILABLE 1
#define MAXNAME 30
#define CLEAR "cls"
typedef struct book{
char *name;
int id;
int count;
int status;
struct book *next;
}Book;
void welcome();
void error(char *); // [異常提醒]
char land(); // [主頁面專案]
int usrstudent(); // [學生入口]返回 0表示返回主頁 1表示繼續執行本函式
int usrmanager(); // [管理員入口]返回 0表示返回主頁 1表示繼續執行本函式
int viewbook(); // [檢視圖書]返回列印的圖書個數 失敗返回-1
int addbook(); // [註冊圖書]新增圖書成功 返回圖書id 失敗返回-1
int modbook(); // [修改圖書]修改圖書資訊 成功後返回id 失敗 -1
int delbook(); // [登出圖書]刪除成功 返回被刪除圖書的id 失敗返回-1
void printbook(Book *); // [列印圖書]
Book *lookup(char *, int); // [搜尋圖書]
int borrowbook(); // [借閱圖書]
int returnbook(); // [歸還圖書]
Book *head = NULL;
int nbook = 0;
int main(){
welcome();
return 0;
}
void welcome(){
printf("*************************歡迎使用圖書管理系統*************************\n");
while(1){
printf("-------------------------------------\n");
printf("請輸入專案前編號執行相關操作:\n");
printf("\n[1] 管理員入口\n\n[2] 學生入口\n\n[0] 退出\n\n");
switch(land()){
case '1':
while(1){
if(usrmanager()){
continue;
}else{
break;
}
}
break;
case '2':
while(1){
if(usrstudent()){
continue;
}else{
break;
}
}
break;
case '0':
exit(0);
default:
error("採集專案引數失敗");
}
}
}
char land(){
char c, flag;
int i;
while(1){
for(i = 0; (c = getchar()) != '\n'; flag = c, ++i)
;
if(i == 1){
if(flag == '1' || flag == '2' || flag == '0'){
return flag;
}
}else if(i == 0){
continue;
}
error("[請輸入命令: 1 / 2 / 0 選擇專案]");
}
return '\0';
}
void error(char *s){
fprintf(stderr, "%s\n", s);
}
char dostudent(){
char c, flag;
int i;
while(1){
for(i = 0; (c = getchar()) != '\n'; flag = c, ++i )
;
if(i == 1){
if(flag == '1' || flag == '2' || flag == '3' || flag == '0'){
return flag;
}
}else if(i == 0){
continue;
}
error("[請輸入命令: 1 / 2 / 3/ 0 選擇專案]");
}
}
int usrstudent(){
printf("-------------------------------------\n");
printf("請輸入專案前編號執行相關操作:\n\n");
printf("[1] 借閱圖書\n[2] 歸還圖書\n[3] 檢視館存圖書\n");
printf("[0] 返回主頁\n");
switch(dostudent()){
case '1':
borrowbook();
break;
case '2':
returnbook();
break;
case '3':
viewbook();
break;
case '0':
return 0;
default:
error("採集專案引數失敗");
break;
}
return 1;
}
int borrowbook(){
system(CLEAR);
char sname[MAXNAME];
printf("搜尋圖書:\n");
scanf("%s", sname);
getchar();
Book *bp;
char *namep = NULL;
if((bp = lookup(namep = strdup(sname), 0)) == NULL){
printf("圖書 %s 不存在\n", namep);
fflush(stdin);
return -1;
}else{
printbook(bp);
if(! bp->status){
printf("借閱圖書: Y N\n");
}else{
printf("圖書外借中\n");
return 0;
}
while(1){
char c = '\0';
scanf("%c", &c);
getchar();
if(!(c == 'Y' || c == 'y' || c == 'N' || c == 'n')){
fflush(stdin);
error("指令無效");
continue;
}
if(c == 'Y' || c == 'y'){
--bp->count > -1 ? printf("成功\n") : printf("失敗\n");
if(! bp->count){
bp->status = UNAVAILABLE;
}
return bp->id;
}else{
return 0;
}
}
}
return -1;
}
int returnbook(){
system(CLEAR);
char sname[MAXNAME];
printf("歸還圖書:\n");
scanf("%s", sname);
getchar();
Book *bp;
char *namep;
if((bp = lookup(namep = strdup(sname), 0)) == NULL){
fflush(stdin);
printf("此圖書並不是館內圖書\n");
return -1;
}else{
printbook(bp);
printf("歸還圖書: Y N\n");
while(1){
char c = '\0';
scanf("%c", &c);
getchar();
if(!(c == 'Y' || c == 'y' || c == 'N' || c == 'n')){
fflush(stdin);
error("指令無效");
}else if(c == 'Y' || c == 'y'){
bp->count++ ? : (bp->status = AVAILABLE);
printf("成功\n");
return bp->id;
}else{
return 0;
}
}
}
return -1;
}
char domanager(){
char c, flag;
int i;
while(1){
for(i = 0; (c = getchar()) != '\n'; flag = c, ++i)
;
if(i == 1){
if(flag == '1' || flag == '2' || flag == '3' || flag == '4' || flag == '0'){
return flag;
}
}else if(i == 0){
continue;
}
error("[請輸入命令: 1 / 2 / 3/ 4 / 0 選擇專案]");
}
return '\0';
}
int usrmanager(){
printf("-------------------------------------\n");
printf("請輸入專案前編號執行相關操作:\n\n");
printf("[1] 檢視已存圖書\n[2] 註冊新圖書\n[3] 修改已有圖書資訊\n[4] 登出現存圖書\n");
printf("[0] 返回主頁\n");
switch(domanager()){
case '1':
viewbook();
break;
case '2':
addbook();
break;
case '3':
modbook();
break;
case '4':
delbook();
break;
case '0':
return 0;
default:
error("採集專案引數失敗");
break;
}
return 1;
}
int viewbook(){
system(CLEAR); ///////////////////////////////////////////
Book *bp;
for(bp =head; bp != NULL; bp = bp->next){
printbook(bp);
}
if(nbook){
return nbook;
}else{
printf("圖書館還沒有圖書哦\n");
return 0;
}
return -1;
}
void printbook(Book *bp){
printf("圖書編號:%d\n", bp->id);
printf("圖書名:%s\n", bp->name);
printf("圖書存數:%d\n", bp->count);
printf("圖書狀態:%s\n", bp->status ? "不可借" : "可借");
}
int addbook(){
system(CLEAR); ///////////////////////////////////////////
char sname[MAXNAME];
int id, count;
char *namep;
while(1){
id = 0;
count = 0;
namep = NULL;
printf("請輸入圖書名:\n");
scanf("%s", sname);
getchar();
printf("請輸入小於1000的圖書編號:\n");
scanf("%d", &id);
getchar();
if(!(id > 0 && id < 1000)){
error("輸入編號不符合要求");
fflush(stdin);
continue;
}
printf("請輸入小於50的圖書數量:\n");
scanf("%d", &count);
getchar();
if(!(count > 0 && count < 50)){
error("輸入數目不符合要求");
fflush(stdin);
continue;
}
Book *bp;
if((bp = lookup(namep = strdup(sname), id)) == NULL){
bp = (Book *)malloc(sizeof (Book));
if(bp == NULL || (bp->name = namep) == NULL){
error("註冊圖書失敗");
fflush(stdin);
continue;
}
bp->id = id;
bp->count = count;
bp->status = AVAILABLE;
++nbook;
bp->next = head;
head = bp;
printf("圖書 %s 註冊成功\n", sname);
return id;
}else{
fflush(stdin);
error("圖書名或編號已經被佔用");
}
}
return -1;
}
Book *lookup(char *s, int id){
Book *bp;
for(bp = head; bp != NULL; bp = bp->next){
if(id == bp->id || strcmp(s, bp->name) == 0){
return bp;
}
}
return NULL;
}
int modbook(){ // 修改除id之外的資訊 因為要修改id 直接刪掉後重新新增會更好
system(CLEAR); ///////////////////////////////////////////
Book *bp = NULL;
while(1){
int id = 0;
printf("請輸入要修改資訊的圖書編號:\n");
scanf("%d", &id);
getchar();
if(!(id > 0 && id < 1000)){
fflush(stdin);
error("圖書編號不符合要求");
continue;
}
if((bp = lookup("", id)) != NULL){
printf("以下為要修改的圖書的現有資訊:\n");
printbook(bp);
printf("[1] 修改圖書名\n[2] 修改圖書數量\n[3] 修改圖書狀態\n[0] 放棄修改\n");
while(1){
int i;
scanf("%d", &i);
getchar();
if(!(i == 1 || i == 2 || i == 3 || i == 0)){
fflush(stdin);
error("輸入專案前編號選擇相關專案");
continue;
}
switch(i){
case 1:
while(1){
char newname[MAXNAME], *namep;
printf("圖書名:\n");
scanf("%s", newname);
getchar();
if((lookup(namep = strdup(newname), 0)) != NULL){
fflush(stdin);
error("圖書名已存在");
continue;
}
if((bp->name = namep) != NULL){
printf("修改成功\n");
return id;
}
}
break;
case 2:
while(1){
int bnum;
printf("輸入圖書數量:\n");
scanf("%d", &bnum);
getchar();
if(!(bnum > 0 || bnum < 1000)){
fflush(stdin);
error("數目不符合要求");
continue;
}
bp->count = bnum;
printf("修改成功\n");
return id;
}
break;
case 3:
while(1){
char c;
int status;
status = bp->status;
status == AVAILABLE ? printf("修改狀態為[不可借]: Y N\n") : printf("修改狀態為[可借]: Y N\n");
scanf("%c", &c);
getchar();
if(!( c == 'Y' || c == 'y' || c == 'N' || c == 'n')){
fflush(stdin);
error("指令無效");
continue;
}
if(c == 'Y' || c == 'y'){
status == AVAILABLE ? bp->status = UNAVAILABLE : (bp->status = AVAILABLE);
printf("修改成功\n");
return id;
}else{
printf("放棄修改\n");
return 0;
}
}
break;
case 0:
return 0;
default:
error("獲取引數失敗");
break;
}
}
}else{
printf("沒有此圖書\n");
return 0;
}
}
return -1;
}
int delbook(){
system(CLEAR);
Book *bp, *fbp;
int id = 0;
printf("請輸入要登出的圖書編號:\n");
scanf("%d", &id);
getchar();
if(!(id > 0 && id < 1000)){
fflush(stdin);
error("圖書編號不符合要求");
return -1;
}
for(fbp = bp = head; bp != NULL; fbp = bp, bp = bp->next){
if(bp->id == id){
printbook(bp);
break;
}
}
if(bp != NULL){
while(1){
printf("確定要登出此圖書:Y N\n");
char YN;
scanf("%c", &YN);
getchar();
if(!((YN == 'Y' || YN == 'y') || (YN == 'N' || YN == 'n'))){
fflush(stdin);
error("指令無效\n");
continue;
}
if(YN == 'Y' || YN == 'y'){
bp == head ? head = bp->next : (fbp->next = bp->next);
free(bp->name); //新增釋放name這塊記憶體//bp記憶體的只是指向name的指標
free(bp); bp = NULL;
printf("圖書登出成功\n");
break;
}else{
printf("放棄登出\n");
return 0;
}
}
return id;
}else{
printf("要登出的圖書編號不存在\n");
return -1;
}
return -1;
}
(2)執行環境和執行結果
DevC++,Windows11
1.主頁面
2.管理員頁面
2.1檢視已有圖書
2.2註冊新圖書
2.3修改已有圖書
2.3.1修改圖書名
2.3.2修改圖書數量
2.3.3修改圖書狀態
2.4登出現存圖書
3.學生頁面
3.1借閱圖書
3.2歸還圖書
3.3檢視館存圖書
(3)主要問題列表
1.管理員登陸不需要特定的輸入
2.修改圖書後沒有顯示修改後的效果,無法及時確定是否成功修改
3.頁面過於簡略,使用者使用不便
(4)新程式碼
點選檢視程式碼
void welcome(){
printf("------------------------------------------------------------------------------------------------------------------------\n");
printf("*************************************************歡迎使用圖書管理系統**************************************************\n");
while(1){
printf("------------------------------------------------------------------------------------------------------------------------\n");
printf("輸入專案前編號執行相關操作:\n");
printf("\n [1] 管理員入口\n\n [2] 學生入口\n\n [0] 退出\n\n");
printf("請輸入:");
switch(land()){
case '1':
while(1){
int m;char n;
printf("請輸入管理員代號:");
scanf("%d",&m);
if(m==1)
printf("登入成功\n");
else break;
if(usrmanager()){
continue;
}else{
break;
}
}
break;
case '2':
while(1){
if(usrstudent()){
continue;
}else{
break;
}
}
break;
case '0':
exit(0);
default:
error("採集專案引數失敗");
}
}
}
int usrstudent(){
printf("------------------------------------------------------------------------------------------------------------------------\n");
printf("請輸入專案前編號執行相關操作:\n\n");
printf(" [1] 借閱圖書\n [2] 歸還圖書\n [3] 檢視館存圖書\n");
printf(" [0] 返回主頁\n");
switch(dostudent()){
case '1':
borrowbook();
break;
case '2':
returnbook();
break;
case '3':
viewbook();
break;
case '0':
return 0;
default:
error("採集專案引數失敗");
break;
}
return 1;
}
int usrmanager(){
printf("------------------------------------------------------------------------------------------------------------------------\n");
printf("請輸入專案前編號執行相關操作:\n\n");
printf(" [1] 檢視已存圖書\n [2] 註冊新圖書\n [3] 修改已有圖書資訊\n [4] 登出現存圖書\n");
printf(" [0] 返回主頁\n");
printf("請輸入編號:");
switch(domanager()){
case '1':
viewbook();
break;
case '2':
addbook();
break;
case '3':
modbook();
break;
case '4':
delbook();
break;
case '0':
return 0;
default:
error("採集專案引數失敗");
break;
}
return 1;
}
int modbook(){ // 修改除id之外的資訊 因為要修改id 直接刪掉後重新新增會更好
system(CLEAR); ///////////////////////////////////////////
Book *bp = NULL;
while(1){
int id = 0;
printf("請輸入要修改資訊的圖書編號:\n");
scanf("%d", &id);
getchar();
if(!(id > 0 && id < 1000)){
fflush(stdin);
error("圖書編號不符合要求");
continue;
}
if((bp = lookup("", id)) != NULL){
printf("以下為要修改的圖書的現有資訊:\n");
printbook(bp);
printf("[1] 修改圖書名\n[2] 修改圖書數量\n[3] 修改圖書狀態\n[0] 放棄修改\n");
while(1){
int i;
scanf("%d", &i);
getchar();
if(!(i == 1 || i == 2 || i == 3 || i == 0)){
fflush(stdin);
error("輸入專案前編號選擇相關專案");
continue;
}
switch(i){
case 1:
while(1){
char newname[MAXNAME], *namep;
printf("圖書名:\n");
scanf("%s", newname);
getchar();
if((lookup(namep = strdup(newname), 0)) != NULL){
fflush(stdin);
error("圖書名已存在");
continue;
}
if((bp->name = namep) != NULL){
printf("修改成功\n");
printbook(bp);
return id;
}
}
break;
case 2:
while(1){
int bnum;
printf("輸入圖書數量:\n");
scanf("%d", &bnum);
getchar();
if(!(bnum > 0 || bnum < 1000)){
fflush(stdin);
error("數目不符合要求");
continue;
}
bp->count = bnum;
printf("修改成功\n");
printbook(bp);
return id;
}
break;
case 3:
while(1){
char c;
int status;
status = bp->status;
status == AVAILABLE ? printf("修改狀態為[不可借]: Y N\n") : printf("修改狀態為[可借]: Y N\n");
scanf("%c", &c);
getchar();
if(!( c == 'Y' || c == 'y' || c == 'N' || c == 'n')){
fflush(stdin);
error("指令無效");
continue;
}
if(c == 'Y' || c == 'y'){
status == AVAILABLE ? bp->status = UNAVAILABLE : (bp->status = AVAILABLE);
printf("修改成功\n");
printbook(bp);
return id;
}else{
printf("放棄修改\n");
return 0;
}
}
break;
case 0:
return 0;
default:
error("獲取引數失敗");
break;
}
}
}else{
printf("沒有此圖書\n");
return 0;
}
}
return -1;
}
(5)重構結果
1.使用者頁面
2.修改後顯示書籍效果
(6)總結
1.閱讀程式碼和理解程式碼有著一定的難度,每個人寫程式碼的習慣有所不同,在理解的時候有著一定的差錯。
2.對程式碼進行完善最佳化,也是有著很大的難度,修改程式碼時有可能會破壞原有的邏輯,也有可能破壞原有的結構順序,本來準備最佳化介面之間的層次和跳轉,但這樣會改變程式碼的邏輯的結構,所需要改動的幅度過大,所以並沒有選擇最佳化介面的這方面問題。
3.對於管理員登入輸入的問題,因為本次專案本來就足夠完整,結構也是很齊整,對於使用者需求也是基本上都滿足了,插入一個管理員登入輸入,系統便崩潰了,又摸索著簡化了原本寫入的輸入資訊,然後才成功。
4.在本次實驗中,也學習到了一些相同問題的不同的處理方式,對於一些函式的使用,檔案流的讀寫,有了更多的瞭解。