需求分析
1、本程式由用戶輸入運行命令和數據,運行結果顯示在其後。
2、程式執行的命令包括:
1)創建一個鍊表;2)執行鍊表的逆置;3)結束。
2、測試數據
鍊表:abc123
概要設計
1、鍊表的抽象數據類型定義為:
ADTNumber{
數據對象:D={ai|ai∈(0,1,…,9),i=0,1,2,…,n,n≥0}
數據關係:R={<ai-1,ai>|ai-1,ai∈D,i=1,2,…,n}
基本操作:
CreateList(&L)
操作結果:創建一個鍊表L。
PrintList(L)
初始條件:鍊表L已存在。
操作結果:在螢幕上輸出鍊表的值。
InverseList(L)
初始條件:鍊表L已存在。
操作結果:將鍊表逆置。
DestroyList(&L)
初始條件:鍊表L已存在。
操作結果:銷毀鍊表L。
} ADTNumber
2、本程式包含五個模組:
(1)主程式模組:
int main(){
定義變數;
接受命令;
處理命令;
退出(return 0);
}
(2)創建鍊表模組——產生一個鍊表;
(3)輸出鍊表模組——把鍊表輸出;
(4)鍊表逆置模組——將鍊表逆置;
(5)銷毀鍊表模組——程式結束後釋放鍊表開闢的空間。
各模組之間的調用關係如下:
主程式模組 創建鍊表模組
創建鍊表模組 輸出鍊表模組 鍊表逆置模組
輸出鍊表模組 創建鍊表模組 銷毀鍊表模組
詳細設計
#include<iostream>
using namespace std;
struct Number //鍊表的類型
{
char data; //鍊表當前結點的值
struct Number *next; //鍊表當前結點指向下一結點的指針
}*number;
void CreateList(Number *&L) //創建鍊表
{
Number *s,*r; //定義兩個鍊表類型的臨時指針
char x; //定義一個臨時字元變數
L=(Number *)malloc(sizeof(Number)); //為頭結點開闢空間
L->next=NULL; //此時頭結點的後繼指針和前驅指針賦值為空
r=L; //是r指針指向頭結點
x=getchar(); //用x接受一個從鍵盤輸入的字元
while(x!="\n") //控制當輸入回車鍵時結束
{
s=(Number *)malloc(sizeof(Number)); //開闢下一結點的空間
s->data=x;
r->next=s; //r的後繼指針指向s
r=s; //是s指向r
x=getchar(); //用x接受一個從鍵盤輸入的字元
}
r->next=NULL; //當創建結束時,r的後繼指針為空
}
void PrintList(Number *L) //輸出鍊表
{
Number *p=L->next; //定義一個臨時指針並指向鍊表的第一個結點
while(p!=NULL) //判斷結點是否為空,空就結束
{
cout<<p->data; //輸出結點的值
p=p->next; //指向下一個結點
}
cout<<endl; //換行
}
void InverseList(Number *L) //鍊表的逆置
{
Number *p=L->next,*q=L->next;
q=q->next;
p->next=NULL;
p=q;
while(p!=NULL)
{
q=q->next;
p->next=L->next;
L->next=p;
p=q;
}
}
void DestroyList(Number *&L) //銷毀鍊表
{
Number *p=L,*q=p->next;
while(q!=NULL)
{
free(p); //釋放p的空間
p=q;
q=p->next;
}
cout<<"釋放鍊表"<<endl;
}
int main()
{
cout<<"請輸入一個鍊表:";
CreateList(number); //調用創建鍊表
cout<<"********************************************************************************";
cout<<"輸入的鍊表為:"<<endl;
PrintList(number); //調用輸出鍊表
InverseList(number); //調用逆置鍊表
cout<<"此鍊表的逆置為:"<<endl;
PrintList(number); //調用輸出鍊表
cout<<"********************************************************************************";
DestroyList(number); //調用銷毀鍊表的函式
return 0;
}
調試分析
1、在創建長整數時,沒有使用getchar()來接受字元,而用C++中的cin>>來輸入,這樣使得每一次輸入之後都要按回車鍵,而且在輸入結束時控制也不方便,使用getchar()函式解決了這一問題。
2、首先,遇到的問題就是if條件中的“= =”中少了一個“=”導致編譯正確,但是一運行就錯誤,這個問題不該錯的,以後一定重視每一個細節。還有就是鍊表的使用過程中,指針太多,一會兒指向這個,一會兒又指向那個,如果思路不清楚的話,很容易弄暈的;有時候一個指針指向空的時候根本就不知道,編譯沒錯誤,檢查不出來,一運行就不正確,有時候運行正確了,但是結果卻不正確,這還好點,有時候指針指向空了,運行就彈出錯誤要終止程式。經過一步一步的測試,一步一步的運行,花了不少時間終於弄出來了。
3、在銷毀鍊表的時候,也遇到過一個問題,還沒弄明白是為什麼。在銷毀鍊表的函式中,如果參數接受兩個鍊表來銷毀的話,如:void DestroyList(Number *&L1,Number *&L2),運行會出錯,或許是我寫的代碼不正確;但是,當用void DestroyList(Number *&L)來一個鍊表一個鍊表的銷毀就沒問題。
運行環境
(1)Windows 7系統下
(2)編程環境:VC6.0++ ,TC2.0