課程設(shè)計(jì)報(bào)告書(shū)
之前寫(xiě)的,忘發(fā)布了...
在C++學(xué)習(xí)了一段時(shí)間之后,我們開(kāi)始入了課程設(shè)計(jì)。我選擇的題目是:《新生基本信息統(tǒng)計(jì)軟件》。
題目要求:
有新生來(lái)報(bào)到,要逐個(gè)錄入其信息,如:學(xué)生姓名,性別,專(zhuān)業(yè),出生日期,家庭地址,英語(yǔ)入學(xué)成績(jī)。要求設(shè)計(jì)鏈表類(lèi)來(lái)實(shí)現(xiàn),并統(tǒng)計(jì)學(xué)生人數(shù)。文本界面為:
- 新增學(xué)生信息
- 刪除學(xué)生信息
- 導(dǎo)入學(xué)生信息(已經(jīng)保存于的文件信息)
- 學(xué)生信息搜索(按姓名)
- 學(xué)生信息統(tǒng)計(jì)(按專(zhuān)業(yè)或性別或年齡---年齡要自動(dòng)計(jì)算)
- 按英語(yǔ)成績(jī)排序
- 學(xué)生信息保存
- 退出
初學(xué)了一些簡(jiǎn)單的語(yǔ)法之后,感覺(jué)要完成一項(xiàng)工程還是有些困難的。
???
????我覺(jué)得課程設(shè)計(jì)的核心,是對(duì)鏈表的操作,實(shí)現(xiàn)動(dòng)態(tài)鏈表的增、刪、改、查。還要體現(xiàn)面對(duì)對(duì)象的思想,相比于C語(yǔ)言的結(jié)構(gòu)體,引入了類(lèi)的概念。?在寫(xiě)課程設(shè)計(jì)時(shí),比起一下子打出來(lái)完,不如分模塊,分功能的有步驟的去寫(xiě)。
類(lèi)的創(chuàng)建
創(chuàng)建了兩個(gè)類(lèi),一個(gè)是student類(lèi),用于儲(chǔ)存學(xué)生信息,另一個(gè)studentmanage類(lèi),用于實(shí)現(xiàn)各類(lèi)功能。
Studentmanage里的函數(shù),實(shí)質(zhì)上就是指向student的類(lèi)指針,比如說(shuō):Student *Studentmanage::creat() 。
這是一個(gè)可控長(zhǎng)度的鏈表,靠的就是不斷的新申請(qǐng)空間,直到某終止條件出現(xiàn),比如我的就是當(dāng)學(xué)生姓名為#時(shí),跳出當(dāng)前循環(huán),停止錄入。
在第一個(gè)節(jié)點(diǎn)需要特殊處理,即對(duì)頭結(jié)點(diǎn)初始化,之后就是申請(qǐng)空間,初始化,挪指針的循環(huán)往復(fù)了。重點(diǎn)是最后一個(gè)結(jié)點(diǎn)的后繼要賦空(NULL)。
- 增
此功能是建立在已形成的鏈表上的,所以如果鏈表為空,就跳出。
不為空時(shí),申請(qǐng)一片空間,并初始化。這并不是就插在原鏈表的最后,而是找了頭結(jié)點(diǎn)的后一個(gè),把新添加的放到了二者中間。
刪
和增一樣,刪要求原本就存在鏈表。
按照姓名刪除,對(duì)比要?jiǎng)h除的姓名,如果出現(xiàn)。
有兩種情況,一種是頭結(jié)點(diǎn):直接讓頭指針移向下一位,再把原結(jié)點(diǎn)free掉。
另一種情況:其他結(jié)點(diǎn),令p1指針先向后移動(dòng)一位,若不是要?jiǎng)h除的,就每次向后位移。直到出現(xiàn)要?jiǎng)h除結(jié)點(diǎn),
把該指針的上一個(gè)next搭到它的下一個(gè),把它隔過(guò)去,再free掉。改,查
這兩個(gè)的原理差不多,就放到一起說(shuō) 。都是通過(guò)遍歷,找到需要的結(jié)點(diǎn),只不過(guò)一個(gè)找到后重新錄入,覆蓋原本數(shù)據(jù);另一個(gè)只是顯示。
為了方便和代碼的簡(jiǎn)潔,在這里我寫(xiě)了displaynode()函數(shù),每次在顯示和整改時(shí)會(huì)方便很多。存文件,讀文件
這可以說(shuō)是一個(gè)難點(diǎn)了,先說(shuō)寫(xiě)入文件,即 :
當(dāng)前黑框---->txt文件
這里就用到了ofstream,文件輸出流類(lèi),open一個(gè)txt,要是沒(méi)有就新建一個(gè),要是原本有就覆蓋。
把頭賦給p1后,只要p1存值,就把它寫(xiě)入到out所新建的那個(gè)文件里,再讓p1移動(dòng)下一個(gè)。
讀文件的過(guò)程就是一個(gè)新建鏈表的過(guò)程,先把頭置空,這里有和student類(lèi)里一樣的數(shù)據(jù),成功打開(kāi)文件之后,把里面的數(shù)據(jù)一個(gè)個(gè)讀出來(lái),并賦值給p1。此處和創(chuàng)建鏈表也一樣,不贅述。
- 排序
思想:如果說(shuō),原本的鏈表是無(wú)序的,而我最終的目的是創(chuàng)造出有序的。而且我有能力去找到這里面最大的或最小的(遍歷就可以了),那么我何不再去創(chuàng)建一個(gè)新的鏈表,它是由原本鏈表摘出來(lái)的節(jié)點(diǎn)所組成,那必然是有序的。
和其他操作的最開(kāi)始一樣,傳入了頭和它之后的一串鏈表,于以往不同的是,這次開(kāi)始了直接對(duì)頭指針的操作。
(366和367是為了防止傳進(jìn)來(lái)一個(gè)空頭造成錯(cuò)誤。
核心代碼就是white里的循環(huán)了:
第一層循環(huán)
????目的是為了讓頭不斷向后遍歷,只不過(guò)這次的目的,就是遍歷到終點(diǎn)。期間每執(zhí)行一次,就讓我定義的指針重新指向同一塊。
第二層循環(huán)
????p(也就是頭)的遍歷,如果后一個(gè)大于前一個(gè),就讓后一個(gè)成為max,同時(shí)定位它的前一個(gè)節(jié)點(diǎn),以這種方式標(biāo)記過(guò)后,p再繼續(xù)向后推進(jìn),以實(shí)現(xiàn)在循環(huán)過(guò)后,可以過(guò)濾出來(lái)最大的,找到了又怎樣呢,我們來(lái)看接下來(lái)的操作。
第一個(gè)if(379)
????這時(shí)還要考慮到那種情況,也就是頭結(jié)點(diǎn)萬(wàn)一最大該怎么操作,這也并不難想,直接讓head指向下一位,同時(shí)斷開(kāi)max(也就是頭)與原鏈表的聯(lián)系。
其它情況就是,既然上一步(371 while)找出來(lái)了max,那么就在這里把它摘出來(lái),令剛剛標(biāo)記的前一項(xiàng)(pre)指向max的后繼,在斷開(kāi)max與原表的聯(lián)系。
第二個(gè)if(387)
????細(xì)心的你會(huì)發(fā)現(xiàn),在每次的賦值里和之前的幾步操作里,都沒(méi)有用到pnew,不僅如此,它還在一開(kāi)始就被置空了。
我的目的就是讓它成為那個(gè)新的鏈表的頭。在之前幾步,我們分別找到了max,分離出了max,終于要在這一步為max找一個(gè)著落了。
????當(dāng)然,if第一次肯定是會(huì)執(zhí)行的(因?yàn)樯蟻?lái)就讓pnew置空了),我們讓最大的那個(gè)節(jié)點(diǎn)成了新鏈表的第一個(gè),那么可想而知的是,在之后幾次的循環(huán)里,每次都會(huì)執(zhí)行else,并且在里面新摘出來(lái)的max被一個(gè)個(gè)的連到了鏈表的后面。
????到最后,別忘了還有那個(gè)大循環(huán)的,它每次執(zhí)行一遍里面的內(nèi)容。如是,原本的無(wú)序鏈表每次少一個(gè)節(jié)點(diǎn)(最大的節(jié)點(diǎn)),而新有序鏈表每次會(huì)多一個(gè)。
????原鏈表終結(jié)之日,也就是新鏈表生成之時(shí)。屆時(shí),循環(huán)也就徹底結(jié)束了,于是我們令頭指針指向那個(gè)新生鏈表(394),再讓它們共同指向這條有序的鏈表,傳回去就行了。
- 主函數(shù)的選擇功能
在這里包含兩塊,先是一個(gè)菜單界面menu,它的返回值是一個(gè)字符型,由最后的cin寫(xiě)入。下面就緊接著是main函數(shù)的switch的選擇功能,之所以用char而不用int就是為了規(guī)避用戶(hù)亂輸造成的錯(cuò)誤。
以下,附上源代碼:
#include<iostream>
#include<fstream> //用來(lái)讀文件
#include<iomanip> //排版
#include<cstring>//操作字符 ,比較和賦值。
#include<stdlib.h> //new,free
using namespace std;
int n=0;
/*
1.明明head置空,為什么add,display沒(méi)有出現(xiàn)預(yù)期效果? ok
(為什么它又莫名其妙的好了??)
2.free關(guān)鍵字為什么不存在? ok
3.全部刪除之后無(wú)法新建
4.排序鏈斷 ok
5.多讀一次 ok
*/
char stop[12]={"#"};
char name[12];
class Student {
public:
char name[12];
char sex[3];
char study[12];
char addr[12];
int birth[3];
int engli;
Student *next;
};
class Studentmanage {
private:
Student *head,*p1,*p2,*p3;
public:
Studentmanage () {};
Student *creat();
Student *add(Student *head);
Student *delet(Student *head);
void *search(Student *head);
Student *modify(Student *head);
Student *sort(Student*head);
void display(Student *head);
void displaynode(Student *head);
void write_file(Student *head);
Student * read_file();
~Studentmanage () {};
};
Studentmanage s;
Student *Studentmanage::creat() {
p1=p2=new Student;
head=NULL;
cout<<"請(qǐng)輸入學(xué)生的基本信息:以姓名為#結(jié)束。\n";
while(1) {
cout<<"姓名: \t";
cin>>p1->name;
if( strcmp(stop,p1->name)==0 ) {
break;
}
cout<<"性別: \t";
cin>>p1->sex;
cout<<"專(zhuān)業(yè): \t";
cin>>p1->study;
cout<<"家庭住址: \t";
cin>>p1->addr;
cout<<"出生年:";
cin>>p1->birth[0];
cout<<"出生月:";
cin>> p1->birth[1];
cout<<"出生日:";
cin>>p1->birth[2];
cout<<"英語(yǔ):";
cin>>p1->engli;
system("cls");
n=n+1;
if(n==1)
head=p1;
else
p2->next=p1;
p2=p1;
p1=new Student;
}
p2->next=NULL;
return head;
}
Student *Studentmanage::add(Student *head) {
p1=p3=new Student;
p1=head;
if(p1==NULL)
{cout<<"在添加前,先新建!";
return 0;
}
else
{
cout<<"請(qǐng)輸入要添加學(xué)生的信息!\n";
cout<<"姓名: \t";
cin>>p3->name;
cout<<"性別: \t";
cin>>p3->sex;
cout<<"專(zhuān)業(yè): \t";
cin>>p3->study;
cout<<"家庭住址: \t";
cin>>p3->addr;
cout<<"出生年:";
cin>>p3->birth[0];
cout<<"出生月:";
cin>> p3->birth[1];
cout<<"出生日:";
cin>>p3->birth[2];
cout<<"英語(yǔ):";
cin>>p3->engli;
cout<<"\n";
p3->next=p1->next;
p1->next=p3;
cout<<"添加成功!\n";
}
return head;
}
Student *Studentmanage::delet(Student *head) {
p2=p1=new Student;
if(head==NULL)
{
cout<<"沒(méi)有數(shù)據(jù),無(wú)法刪除";
return 0;
}
cout<<"請(qǐng)輸入要?jiǎng)h除學(xué)生的名字:\n";
cin>>name;
p2=p1=head;
int j=0;
if( ( strcmp(name,head->name)==0 ) && (head!=NULL))
{
head=head->next;
free(p1);
j=1;
}
else
{
p1=head->next;
while(p1!=NULL) {
if(strcmp(name,p1->name)==0) {
p2->next=p1->next;
free(p1);
j=1;
break;
} else {
p2=p1;
p1=p2->next;
}
}
}
if(j==0)
cout<<"此學(xué)生不存在,刪除失敗!\n";
else
cout<<"刪除成功!\n";
return head;
}
void *Studentmanage::search(Student *head) {
p1=new Student;
cout<<"請(qǐng)輸入要查找學(xué)生的姓名:\n";
cin>>name;
p1=head;
int j=0;
while(p1!=NULL) {
if( strcmp(name,p1->name)==0 ) {
s.displaynode(p1);
break;
}
p1=p1->next;
}
if(j==0)
cout<<"沒(méi)有找到你要查找學(xué)生的信息。\n\n\n";
else
cout<<"這是你要查找學(xué)生的信息。\n\n\n";
}
Student *Studentmanage::modify(Student *head) {
if(head==NULL)
{
cout<<"沒(méi)有數(shù)據(jù),先新建吧";
return 0;
}
char name1[12];
char sex[3];
char study[12];
char addr[12];
int birth[3];
int engli;
p1=new Student;
int j=0;
p1=head;
cout<<"請(qǐng)輸入你要更改學(xué)生的學(xué)號(hào):\n";
cin>>name;
if(strcmp( name, head->name)==0) {
cout<<"顯示要修改學(xué)生的信息:\n";
s.displaynode(p1);
cout<<"請(qǐng)輸入要更改學(xué)生的信息:\n";
cout<<"姓名: \t";
cin>>name1;
cout<<"性別: \t";
cin>>sex;
cout<<"專(zhuān)業(yè): \t";
cin>>study;
cout<<"家庭住址: \t";
cin>>addr;
cout<<"出生年:";
cin>>birth[0];
cout<<"出生月:";
cin>>birth[1];
cout<<"出生日:";
cin>>birth[2];
cout<<"英語(yǔ):";
cin>>engli;
strcpy(head->name,name1);
strcpy(head->sex,sex);
strcpy(head->study,study);
strcpy(head->addr,addr);
head->birth[0]=birth[0];
head->birth[1]=birth[1];
head->birth[2]=birth[2];
head->engli=engli;
j=1;
} else {
p1=head->next;
while(p1!=NULL) {
if(strcmp(p1->name,name)==0)
cout<<"顯示要修改學(xué)生的信息:\n";
s.displaynode(p1);
cout<<"請(qǐng)輸入要更改學(xué)生的信息:\n";
cout<<"姓名: \t";
cin>>name1;
cout<<"性別: \t";
cin>>sex;
cout<<"專(zhuān)業(yè): \t";
cin>>study;
cout<<"家庭住址: \t";
cin>>addr;
cout<<"出生年:";
cin>>birth[0];
cout<<"出生月:";
cin>>birth[1];
cout<<"出生日:";
cin>>birth[2];
cout<<"英語(yǔ):";
cin>>engli;
strcpy(p1->name,name1);
strcpy(p1->sex,sex);
strcpy(p1->study,study);
strcpy(p1->addr,addr);
p1->birth[0]=birth[0];
p1->birth[1]=birth[1];
p1->birth[2]=birth[2];
p1->engli=engli;
j=1;
break;
}
}
if(j==0)
cout<<"沒(méi)有找到你要更改的學(xué)生,更改失??!\n";
else
cout<<"更改成功!\n";
return head;
}
void Studentmanage::display(Student *head) {
p1=head;
if(p1==NULL)
cout<<"這是一個(gè)空表!請(qǐng)先輸入學(xué)生信息。"<<endl;
else {
while(p1!=NULL) {
s.displaynode(p1);
p1=p1->next;
}
}
}
void Studentmanage::displaynode(Student *head) {
p1=head;
if(p1==NULL)
cout<<"這是一個(gè)空表!請(qǐng)先輸入學(xué)生信息。"<<endl;
else
{
cout<<"姓名:"<<p1->name<<" 性別:"<<p1->sex<<" 專(zhuān)業(yè):"<<p1->study;
cout<<" 家庭住址:"<<p1->addr<<endl;
cout<<p1->birth[0]<<"年";
cout<<p1->birth[1]<<"月:"<<p1->birth[2]<<"日 出生:";
cout<<"年齡:"<<2017-p1->birth[0]<<endl;
cout<<"英語(yǔ)成績(jī):"<<p1->engli<<"\n\n";
}
}
Student *Studentmanage::read_file()
{
int i=0;
char name2[12];
char study[12];
char sex[3];
char addr[12];
int birth[3];
int engli;
p1=p2=new Student;
head=NULL;
ifstream in;
in.open("myC++work.txt");
if(!in) {
cout<<"打開(kāi)文件失?。?<<endl;
}
else
{
while(in>>name2>>sex>>study>>addr>>birth[0]>>birth[1]>>birth[2]>>engli)
{
strcpy(p1->name,name2);
strcpy(p1->sex,sex);
strcpy(p1->study,study);
strcpy(p1->addr,addr);
p1->birth[0]=birth[0];
p1->birth[1]=birth[1];
p1->birth[2]=birth[2];
p1->engli=engli;
i++;
if(i==1) {
head=p2=p1;
} else {
p2->next=p1;
}
p2=p1;
p1=new Student;
p1->next=NULL;
}
cout<<"成功讀取文件!內(nèi)容如下:"<<endl;
}
return head;
}
void Studentmanage::write_file(Student *head)
{
ofstream out;
out.open("myC++work.txt");
if(!out)
{
cout<<"打開(kāi)文件失?。?<<endl;
}
p1=NULL;
p1=head;
while(p1) {
out<<p1->name<<setw(5)<<p1->sex<<setw(5)<<p1->study<<setw(5)<<p1->addr<<setw(5)<<p1->birth[0]<<setw(5)<<p1->birth[1]<<setw(5)<<p1->birth[2]<<setw(5)<<p1->engli<<endl;
p1=p1->next;
}
out.close();
cout<<"寫(xiě)入完畢。";
}
Student *Studentmanage::sort(Student *head)
{
Student*p,*pnew=NULL,*pmax,*ppre;
if(head==NULL) return 0;
else {
while(head->next!=NULL) {
p=pmax=ppre=head;
while(p->next!=NULL) {
if(p->next-> birth[0] > pmax->birth[0]) {
pmax=p->next;
ppre=p;
}
p=p->next;
}
if(head==pmax) {
head=head->next;
pmax->next=NULL;
} else {
ppre->next=pmax->next;
pmax->next=NULL;
}
if(pnew==NULL) {
pnew=pmax;
} else {
pmax->next=pnew;
pnew=pmax;
}
}
head->next=pnew;
pnew=head;
return head;
}
}
char menu() {
system("cls");
char ch;
cout<<"\n\n";
cout<<" ******************新生信息統(tǒng)計(jì)****************\n";
cout<<" 1.新建學(xué)生檔案";
cout<<" 2.增加學(xué)生信息\n";
cout<<" 3.刪除信息";
cout<<" 4.查詢(xún)信息\n";
cout<<" 5.修改信息";
cout<<" 6.展示信息\n";
cout<<" 7.讀檔";
cout<<" 8.保存并退出\n";
cout<<" **********************************************\n";
cin>>ch;
return ch;
}
int main ()
{
Studentmanage s;
Student *head;
head=NULL;
int n=0;
char c;
cout<<"\t\t\t歡迎新生報(bào)到!\n\n\n";
cout<<"\t\t 滲透一班 劉華輝\n";
cout<<"\n\n\n\n\n\n";
system("pause");
while(1)
switch (menu()) {
case'1':
head=s.creat();
system("pause");
break;
case'2':
head=s.add(head);
system("pause");
break;
case'3':
head=s.delet(head);
system("pause");
break;
case'4':
s.search(head);
system("pause");
break;
case'5':
head=s.modify(head);
system("pause");
break;
case'6':
s.sort(head);
s.display(head);
system("pause");
break;
case'7':
head=s.read_file();
s.display(head);
system("pause");
break;
case'8':
s.write_file(head);
cout<<"謝謝使用!再見(jiàn)!\n";
system("pause");
return 0;
default:
cout<<"選擇有錯(cuò),請(qǐng)重新選擇\n";
}
return 0;
}