1、構造留言簿的結構
一個留言必不可少的是內容、其次是留言的日期和時間。和們就按這兩點定義留言記錄的結構。
strUCt record
{
struct date t_date; /*留言日期*/
struct time t_time; /*留言時間*/
char event[100]; /*留言內容*/
struct record *next; /*指向下一個節點的指針*/
};
在上結構的定義中,用字符串event[100]存放留言內容,結構成員t_date存放留言的日期,t_time存放留言的時間。結構data和time的定義是Turbo C提供的。它們的定義分別如下所示:
struct date
{
int da_year;
char da_day;
char da_mon;
};
struct time
{
unsigned char ti_min;
unsigned char ti_hour;
unsigned char ti_hund;
unsigned char ti_sec;
};
2、入隊操作
入隊操作比較簡單,只要能找到隊列的最後一個節點(即尾節點)修改尾節點的指針域,讓其指針指向新增加的節點即可。於是問題的要害就在於如何找到尾節點,或是找到尾節點的指針域。
這裡采用設置頭節點和尾指針的方法來完成入隊操作。
隊列在還沒有任何一條記錄時稱為隊空。此時我們在隊列中設置一個不存放任何記錄的節點,稱為“頭節點”(采用頭節點的好處在以後會體現出來),由於並無記錄,我們設置的指向隊尾的尾指針也指向這個頭節點。
一旦需要添加記錄,就讓尾指針指向新節點(稱為節點1),而後把節點1的指針域賦給尾指針。由於尾指針為頭節點的指針域,這樣含頭節點就鏈接了節點1,即頭節點的指針指向節點1,形成了鏈的初始模型。當增加第二個節點(稱為節點2)時,仍然修改尾指針,讓其指向節點2,而後把節點2的指針域賦給尾指針。由於原來尾指針為節點1的指針域,因此節點1和節點2又鏈接在一起。現在的隊列由頭節點、節點1和節點2相互鏈接而成。依此類推,鏈隊就通過修改尾指針的值形成了。
入隊操作的基本算法如下所示:
void queue_add(struct element *rear,struct element *p)
{
p->next=NULL;
rear->next=p;
rear=p;
}
其中rear即為尾指針,而指針p指向新增的節點。算法的流程和上述完全一樣。
錄入留言記錄的函數代碼如下所示:
void Data_Input(struct record *p)
{
struct data *d;
struct time *t;
front++;
getdate(t); /*取系統時間*/
p->t_time.ti_hour=ti_hour;
p->t_time.ti_min=ti_min;
p->time.ti_sec=ti_sec;
printf("
Date:%4d %2d %2d",p->t_date.da_year,p->t_date.da_mon,p->t_date.da_day);
printf("
Time: %2d: %2d: %2d",p->t_time.ti_hour,p->t_time.ti_min,p->t_time.ti_sec);
printf("
Please input record:");
gets(p->event); /*輸入留言內容*/
p->next=NULL;
}
上述函數中,采用了getdate()和gettime()兩個函數用來獲取系統的日期和時間。這兩個函數只返回指向當前日期和時間的兩個指針,還需要將值立即賦給留言記錄中的結構成員。
3、出隊操作---留言記錄的刪除
和入隊操作相反的是出隊操作,即在隊頭將記錄刪除,這也是符合“先進先出”的原則的。
由於設置了頭節點,因此出隊操作顯得非常簡單。只需要修改頭節點的指針域,讓其指向第二個節點即可。而第一個節點則將其釋放掉。其余節點,包括尾指針都不必做任何修改操作。
例如一個隊列原本由頭節點、節點1和節點2相鏈而成,執行出隊操作時,相當於將頭節點和節點1、節點1和節點2之間的兩條鏈斷開,而用斷鏈將頭節點和節點2鏈上,多出來的節點1將其釋放掉。
典型的出隊操作算法如下:
void queue_delete(struct element head)
{
struct element *temp;
temp=head.next->next;
head.next=temp;
}
在執行出隊操作時,一定要記住需要將出隊的節點釋放。由於采用鏈式存儲,事先無法估計需要多大的存銷售市場空間,也不必去估計。每次新增一個節點時,都是調用內存分配函數為新節點申請一塊內存,如下所示:
p=malloc(sizeof(struct record)
函數malloc開辟了一塊大小為record 結構元素的內存區域,把掻向該區域的指針賦給指針p,這塊內存單元的所有權就從系統轉移到了指針p。當p指向的數據元素被刪除(出隊)時,一定要用如下方式將內存單 所有權還給系統:
free(p);
函數free()的作用和malloc()剛好相反,它將指定的內存單元還給了系統。因為系統的內存單元是有限的,假如不及時釋放占用的內存,會造成內存資源耗盡或由於內存的減少導致程序執行速度下降。
4、記錄的存取的讀取
void Data_Save(struct record *p) /*記錄文件的存取*/
{
int j;
fp=fopen(tele_rec.txt","w"); /*以可寫方式打開記錄文件*/
while(p!=NULL) /*若未到隊尾,徨將記錄存儲到文件中*/
{
fwrite(p.sizeof(struct record),1,fp);
p=p->next;
}
fclose(fp); /*關閉指定的文件*/
}
struct event *Data_Load() /*從記錄文件中讀取記錄*/
{
long k;
struct record *p,*q;
p=event_head.next;
fp=fopen("tele_rec.txt","r+t"); /*以讀方式打開記錄文件*/
if(fp!=NULL)
{
while(!feof(fp)) /*依次讀取記錄並執行入隊操作*/
{
fread(q,sizeof(struct record),1,fp);
p->next=q; /*這裡p為尾指針,q為指向新節點的指針*/
p=q;
}
p->next=NULL;
event_end=p;
}
else
{
fp=fopen("tele_rec.txt","w"); /*若文件不存在,創建指定文件名的新文件*/
event_head.next=NULL;
event_end=event_head.next;
}
}
/*-------------留言簿代碼如下-------------*/
#include<stdio.h>
#include<conio.h>
#include<dos.h>
struct record
{
struct date t_date; /*定義留言日期*/
struct time t_time; /*定義留言時間*/
char event[100]; /*定義電話內容*/
struct record *next; /*指向下一個節點的指針*/
}event_head;
struct record *event_end;
int front;
FILE *fp;
void Data_Save(struct record *p) /*記錄文件的存儲*/
{
int j;
fp=fopen("tele_rec.txt","w"); /*以可寫方式打開記錄文件*/
while(p!=NULL)