學(xué)生管理系統(tǒng) (梳理)
1.目標(biāo)明確
A.學(xué)生:查詢學(xué)生個(gè)人信息(基本、課程)
B.老師:查詢老師個(gè)人信息
C.管理員:增刪改查
2.數(shù)據(jù)存儲(chǔ):數(shù)據(jù)庫里(文件)
保存哪些數(shù)據(jù):
a.保存所有用戶信息的文件users.txt
b.每個(gè)文件保存用戶具體信息jack.txt merry.txt
3.準(zhǔn)備知識(shí)
枚舉enum
單鏈表
結(jié)點(diǎn)
泛型(void*)
- void*任意指針類型抵蚊,這個(gè)指針變量可以指向任意的數(shù)據(jù)類型,使用這個(gè)變量的時(shí)候必須轉(zhuǎn)化為對(duì)應(yīng)的類型
枚舉
枚舉是一種公共類型贞绳,同一片內(nèi)存空間可能存在多種值
(讓多個(gè)變量共用一種類型)
宏定義:(沒有聯(lián)系致稀,不能將多個(gè)值當(dāng)做一種類型來看待)
#define teacher 0
#define student 1
#define administrator 2
//默認(rèn)值從零開始熔酷,后邊依次遞增
enum Type{
teacher;//0
student;//1
administrator;//2
}
enum Type tt = teacher;
數(shù)據(jù)結(jié)構(gòu)
線性表——數(shù)組
優(yōu)點(diǎn):查詢方便
缺點(diǎn):增刪效率低
單鏈表
優(yōu)點(diǎn):增刪效率極高
缺點(diǎn):查詢不方便
- 創(chuàng)建一個(gè)鏈表需要有頭指針和尾指針豺裆,頭指針永遠(yuǎn)不動(dòng)指向第一個(gè)結(jié)點(diǎn)号显,尾指針用來記錄當(dāng)前的尾結(jié)點(diǎn)
結(jié)點(diǎn):存儲(chǔ)數(shù)據(jù)單元(一個(gè)結(jié)點(diǎn)同時(shí)包含數(shù)據(jù)域和指針域,一般為結(jié)構(gòu)體)
1.數(shù)據(jù)域:存儲(chǔ)具體數(shù)據(jù) 90
2.指針域:記錄下一個(gè)結(jié)點(diǎn)或上一個(gè)結(jié)點(diǎn)
鏈表的使用
/*
從終端輸入整數(shù)蔑歌,用鏈表存儲(chǔ)揽碘,輸出所有數(shù)據(jù)
數(shù)據(jù)域:整數(shù)
指針域:*
*/
#include <stdio.h>
//定義一個(gè)類型,結(jié)點(diǎn)類型
typedef struct score{//struct Score是一種類型
int score;//數(shù)據(jù)域
struct score* next;//指向下一個(gè)結(jié)點(diǎn)的指針域
}Score;
//typedef是類型重定義將Score代替struct Score(單純名字的替換)
int main(){
//鏈表頭指針很重要(結(jié)點(diǎn)的第一個(gè)地址)
//定義一個(gè)頭指針
//struct Score *pHeader;類型重定義前定義頭指針的方法
Score *pHeader = NULL;//Score *pHeader == NULL;類等價(jià)于型重定義前定義頭指針的方法
//尾指針
Score *pTail = NULL;
int i = 0;
while(i < 3){
//先創(chuàng)建一個(gè)結(jié)構(gòu)體來存儲(chǔ)數(shù)據(jù)
Score temp = {};
printf("請(qǐng)輸入成績(jī):");
scanf("%d",&(temp,score));
//判斷是否是第一個(gè)結(jié)點(diǎn)
if(pHeader ==NULL){
//頭指針指向第一個(gè)結(jié)點(diǎn)
pHeader = &temp;
//尾指針指向第一個(gè)結(jié)點(diǎn)
pTail = &temp;
} else{
//讓當(dāng)前的這個(gè)next指向這個(gè)結(jié)點(diǎn)
pHeader->next = &temp;
//尾指針指向最后一個(gè)結(jié)點(diǎn)
pTail = &temp;
}
i++;
}
//輸出
//臨時(shí)指針指向頭結(jié)點(diǎn)
Score *pTemp = pHeader;
while(1){
//輸出當(dāng)前這個(gè)結(jié)點(diǎn)數(shù)據(jù)
printf("%d",pTemp->score);
//指針指向下一個(gè)結(jié)點(diǎn)
if(pTemp->next == NULL){
break;
}else{
pTemp = pTemp->next;
//尾指針
}
}
return 0;
}
由于局部變量的局限性,以及系統(tǒng)分配的地址會(huì)被釋放導(dǎo)致出現(xiàn)了指向不明的情況劫灶,所以應(yīng)該改進(jìn)代碼為手動(dòng)分配內(nèi)存,手動(dòng)釋放本昏,這樣就不會(huì)出現(xiàn)指向不明的擔(dān)心枪汪。
#include <stdio.h>
#include <stdlib.h>
//定義一個(gè)類型,結(jié)點(diǎn)類型
typedef struct score{//struct Score是一種類型
int score;//數(shù)據(jù)域
struct score* next;//指向下一個(gè)結(jié)點(diǎn)的指針域
}Score;
//typedef是類型重定義將Score代替struct Score(單純名字的替換)
int main(){
//鏈表頭指針很重要(結(jié)點(diǎn)的第一個(gè)地址)
//定義一個(gè)頭指針
//struct Score *pHeader;類型重定義前定義頭指針的方法
Score *pHeader = NULL;//類等價(jià)于宏定義前定義頭指針的方法
//尾指針
Score *pTail = NULL;
int i = 0;
while(i < 3){
//先創(chuàng)建一個(gè)結(jié)構(gòu)體來存儲(chǔ)數(shù)據(jù)
Score *pNode = (Score*)malloc(sizeof(Score));//手動(dòng)分配內(nèi)存空間
if(pNode == NULL){
exit(EXIT_FAILURE);
}
//初始化指針量
pNode->next = NULL;
printf("請(qǐng)輸入成績(jī):");
scanf("%d",&(pNode->score));
//判斷是否是第一個(gè)結(jié)點(diǎn)
if(pHeader == NULL){
//頭指針指向第一個(gè)結(jié)點(diǎn)
pHeader = pNode;
//尾指針指向第一個(gè)結(jié)點(diǎn)
pTail = pNode;
} else{
//讓當(dāng)前的這個(gè)next指向這個(gè)結(jié)點(diǎn)
pTail->next = pNode;
//尾指針指向最后一個(gè)結(jié)點(diǎn)
pTail = pNode;
}
i++;
}
//輸出
//臨時(shí)指針指向頭結(jié)點(diǎn)
Score *pTemp = pHeader;
while(1){
//輸出當(dāng)前這個(gè)結(jié)點(diǎn)數(shù)據(jù)
printf("%d",pTemp->score);
//指針指向下一個(gè)結(jié)點(diǎn)
if(pTemp->next == NULL){
break;
}else{
pTemp = pTemp->next;
//尾指針
}
}
pTemp = pHeader->next;
while(1){
//釋放當(dāng)前結(jié)點(diǎn)
free(pHeader);
//指針指向下一個(gè)結(jié)點(diǎn)
if(pTemp == NULL){
break;
}else{
pHeader = pTemp;
pTemp = pTemp->next;
}
}
return 0;
}