實驗題目:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<conio.h>
#define ESC 27 //退出鍵
#define Enter 13 //回車鍵
#define BackSpace 8
/* 1************定義日記結構體*************************/
typedef struct Link1
{ char date[10]; //日期 格式2009-12-30
char title[40]; //標題
char content[1000]; //日記內容
char keyword[20]; //關鍵字,可用空格隔開
int tag; //用來標記該日記是否滿足查閱要求,是爲0,否爲-1,初始值爲0;
struct Link1 *nextd;
} Diary;
/* 2 ************定義用戶結構體************************/
typedef struct Link2
{ char username[25]; //用戶名
char password[16]; //登錄密碼
Diary *diarys_list; //該用戶擁有的日記鏈表
struct Link2 *nextu;
} User;
/* 3 *********************函數聲明************************/
int Change_Password(User *U2);
int Create_NewUser(User *U1);
int Delete_Diary(Diary *D);
int Diary_Operation(User *U2,Diary *D1);
int Encrypt_Password(char password[]);
int Enter_Password(char password[]);
User *Find_User(User *U1,char username[]);
Diary *Init_Diary(Diary *D1);
void Initial_Tag(Diary *D1,int tag);
User *Init_User(User *U1);
int Input_Choose();
int Open_Diary(Diary *D1);
Diary *Open_DiaryFile(Diary *D1,char FileName[]);
int Open_File(char FileName[]);
int Printf_DiaryList(Diary *D1);
void Print_Menu1(int *choose1);
void Print_Menu2(int *choose2);
void Print_Menu3(int *choose3);
int Printf_users(User *U1);
int Save_Diary(Diary *D1);
int Save_Users_info(User *U1);
int Search_Diary(Diary *D1);
Diary *Search_order(Diary *D1);
Diary *Filter_word(Diary *D1,char cmpword[],int n);
User *User_Login(User *U1);
int Write_Diary(Diary *D1);
int Change_Password(User *U2)
{ char oldpw[16],newpw1[16],newpw2[16];
do
{
printf("\n\t請輸入舊密碼:\t");
Enter_Password(oldpw);
Encrypt_Password(oldpw);
if(strcmp(U2->password,oldpw)!=0)
printf("\n\t舊密碼輸入錯誤!....\n\n");
}while(strcmp(U2->password,oldpw)!=0);
do
{
printf("\n\t請輸入新密碼:\t");
Enter_Password(newpw1);
printf("\n\t請確認新密碼:\t");
Enter_Password(newpw2);
if(strcmp(newpw1,newpw2)!=0)
printf("\n\t密碼確認錯誤!....\n\n");
}while(strcmp(newpw1,newpw2)!=0);
Encrypt_Password(newpw1);
strcpy(U2->password,newpw1);
printf("\n\n\t密碼修改成功!......");
return 1;
}
/* 5 **********************創建用戶鏈表*********************/
int Create_NewUser(User *U1)
{ int flag=0;
char password2[16];
User *s,*temp;
Diary *D2=NULL;
D2=Init_Diary(D2);
do
{
s=(User *)malloc(sizeof(User));
if(s==NULL)
{
printf("\t用戶創建失敗!");
return 0;
}
printf("\n\t請輸入用戶名:\t");
scanf("%s",&s->username);
temp=Find_User(U1,s->username);
if(temp==NULL)
{
do
{
printf("\n\t請輸入密碼:\t");
Enter_Password(s->password);
printf("\n\t請確認密碼:\t");
Enter_Password(password2);
if(strcmp(s->password,password2)!=0)
printf("\n\t密碼確認錯誤!....\n\n");
}while(strcmp(s->password,password2)!=0);
Encrypt_Password(s->password);
s->diarys_list=D2;
s->nextu=U1->nextu;
U1->nextu=s;
flag=0;
printf("\n\t用戶創建成功!......\n");
}
else
{printf("\n\n\t***對不起**該用戶名已存在!!!!\n");
printf("\n\t是否繼續創建用戶:1/0\t");
scanf("%d",&flag);
}
} while(flag);
return 1;
}
/* 6 *************************刪除日記**********************/
int Delete_Diary(Diary *D)
{ Diary *p;
p=D->nextd;
D->nextd=p->nextd;
free(p);
printf("\n\t日記刪除成功......");
return 1;
}
/* 7 **********************日記操作*************************/
int Diary_Operation(User *U2,Diary *D1)
{ char tempch='1';
int choose2;
char FileName[40];
Diary *p=NULL;
while(tempch!=ESC)
{
system("cls");
printf("\n\t\t\t歡迎用戶---“%s”的到來!......\n\n",U2->username);
Print_Menu2(&choose2);
switch(choose2)
{ case 0:return 0;
case 1:{Write_Diary(D1);
tempch=getch();}break;
case 2:{ printf("\n\t參考文件: 聽雨的思索.txt");
printf("\n\t請輸入文件路徑及文件名:");
scanf("%s",FileName);
p=Open_DiaryFile(D1,FileName);
if(p!=NULL)
Open_Diary(p);
tempch=getch();
};break;
case 3:
{ printf("\n\n\t該用戶有以下日記:\n\n");
Printf_DiaryList(D1);
tempch=getch();
}break;
case 4: {if(Search_Diary(D1)==1)
tempch=getch();}break; //打開幫助文件
case 5: {Change_Password(U2);
tempch=getch();}break;
}
}
return 1;
}
/* 8 ***********************將登錄口令加密*******************/
int Encrypt_Password(char password[])
{ int i=0;
while(password[i]!='\0')
{
if((password[i]>='a'&&password[i]<='z')||(password[i]>='A'&&password[i]<='Z'))
{ password[i]=password[i]+4;
if(password[i]>'Z'&&password[i]<='Z'+4||password[i]>'z')
password[i]=password[i]-26;
}
else if(password[i]>='0'&&password[i]<='9')
{ password[i]=password[i]+4;
if(password[i]>'9'&&password[i]<='9'+4)
password[i]=password[i]-10;
}
else
password[i]=password[i]+4;
i++;
}
return 1;
}
/* 9 **********************獲取登錄口令********************/
int Enter_Password(char password[])
{ char password1[50];
int i=0;
while((password1[i]=getch())!=Enter)
{
password[i]=password1[i];
password1[i]='*';
printf("%c",password1[i]);
i++;
}
password[i]='\0';
rewind(stdin);
return 1;
}
/* 10 *********************查找用戶********************/
User *Find_User(User *U1,char username[])
{
User *q;
q=U1->nextu;
while(q!=NULL&&strcmp(q->username,username)!=0)
q=q->nextu;
if(q!=NULL)
return q;
else
return NULL;
}
/* 11 *******************初始化日記表*******************/
Diary *Init_Diary(Diary *D1)
{ D1=(Diary *)malloc(sizeof(Diary));
if(D1!=NULL)
{ D1->nextd=NULL;
return D1;
}
else
return NULL;
}
/* 12 **********將所有日記記錄的標記tag值置爲0或-1*************/
void Initial_Tag(Diary *D1,int tag)
{
Diary *q;
q=D1->nextd;
while(q!=NULL)
{q->tag=tag;
q=q->nextd;
}
}
/* 13 ****************初始化用戶表**********************/
User *Init_User(User *U1)
{ U1=(User *)malloc(sizeof(User));
if(U1!=NULL)
{ U1->nextu=NULL;
return U1;
}
else
return NULL;
}
/* 14 ***********************菜單操作數的選擇**************************/
int Input_Choose() //此函數用來判斷是否輸入的是正整數,結果將返回該正整數
{ char str1[50];
long n,i=0;
str1[0]=getch();
printf("%c",str1[0]);
if(str1[0]==ESC)
{ rewind(stdin);
return 0;
}
getch();
if(str1[0]>'0'||str1[0]<'9')
{ rewind(stdin);
return (str1[0]-48);
}
n=atoi(str1); //利用atoi函數將字符串str轉換成整型數
return n; //返回輸入的正整數
}
/* 15 *******************打開日記**********************************/
int Open_Diary(Diary *D1)
{
printf("\n\t--------------------------------------------------\n");
printf("\n\t日記日期==>%s",D1->date);
printf("\n\t日記標題==>%s",D1->title);
printf("\n\n\t關鍵字==>%s",D1->keyword);
printf("\n\t--------------------------------------------------\n");
printf("\n\n\t日記正文如下:\n");
printf("\n\t%s",D1->content);
return 1;
}
/* 16 *******************打開並導入日記文件*************************/
Diary *Open_DiaryFile(Diary *D1,char FileName[])
{FILE *fp;
Diary *p=NULL;
if((fp=fopen(FileName,"r"))==NULL)
{
printf("\t文件打開失敗!");
return NULL;
}
else
{ p=(Diary *)malloc(sizeof(Diary));
if(p==NULL)
{
printf("\t日記創建失敗!");
return NULL;
}
fscanf(fp,"\t日期: %s\n",p->date);
fscanf(fp,"\t標題: %s\n",p->title);
fscanf(fp,"\t關鍵字: %s\n",p->keyword);
fscanf(fp,"\t正文如下:\n\t%s\n",p->content);
p->tag=0;
p->nextd=D1->nextd;
D1->nextd=p;
fclose(fp);
return p;
}
}
/* 17 **************打開普通文本文件********************/
int Open_File(char FileName[])
{
FILE *fp;
fp=fopen(FileName,"r"); //以只讀的方式打開文件,將文件指針賦給fp
if(fp==NULL)
{ printf ("\n\t\t無法打開幫助文件!......");
return 0;
}
while(feof(fp)==0) //將文件中的字符讀入
printf("%c",fgetc(fp));
fclose(fp);
return 1;
}
/* 18 ***********************導入用戶信息********************/
int Open_Users_info(User *U1)
{
FILE *fp;
User *U2=NULL,*U3=NULL;
Diary *D1=NULL,*D2=NULL;
char filepn[20],tempstr[80];/*用來存放文件保存路徑以及文件名*/
strcpy(filepn,"Users_info.txt");
if((fp=fopen(filepn,"r"))==NULL)
{
printf("不能打開文件!\n");
return 0;
}
else
{ fscanf(fp,"%s\n",tempstr);
while(strcmp(tempstr,"User:")==0&&(!feof(fp)))
{
U2=(User *)malloc(sizeof(User));
if(U2==NULL)
{
printf("\t用戶空間申請失敗!\n");
return 0;
}
else
{
fscanf(fp,"用戶名:%80s\n",U2->username);
fscanf(fp,"密碼:%80s\n",U2->password);
fscanf(fp,"%80s",tempstr);
D1=(Diary *)malloc(sizeof(Diary));
D1=Init_Diary(D1);
U2->diarys_list=D1;
while(strcmp(tempstr,"Diary:")==0&&(!feof(fp)))
{
D2=(Diary *)malloc(sizeof(Diary));
if(D2==NULL)
{
printf("\t日記空間申請失敗!\n");
return 0;
}
else
{
fscanf(fp,"\t日期: %s\n",D2->date);
fscanf(fp,"\t關鍵字: %s\n",D2->keyword);
fscanf(fp,"\t標題: %s\n",D2->title);
fscanf(fp,"\t日記內容: \n%s\n\n",D2->content);
fscanf(fp,"%s\n",tempstr);
D2->tag=0;
D2->nextd=D1->nextd;
D1->nextd=D2;
}
}
U2->nextu=U1->nextu;
U1->nextu=U2;
}
fscanf(fp,"\n\n");
}
}
fclose(fp);
return 0;
}
/* 19 ********************顯示日記列表**********************/
int Printf_DiaryList(Diary *D1)
{ int count=0;
Diary *D;
D=D1;
printf("\n");
if(D->nextd==NULL)
printf("\t沒有日記信息!.....\n");
else
{ while(D->nextd!=NULL)
{ D=D->nextd;
if(D->tag==0)
{
count++;
printf("\t第%2d篇==>時間:%-10s 日記標題:%-20s \t關鍵字:%-s\n",count,D->date,D->title,D->keyword);
}
}
}
return count;
}
/* 20 ************************進入菜單並選擇操作*************************/
void Print_Menu1(int *choose1)
{
printf("\n\t\t “日記管理系統”---(ESC退出)\n");
printf("\t|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^|\n");
printf("\t| 1.用戶登錄 2.新建用戶 3.顯示用戶列表 4.幫助 |\n");
printf("\t|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^|\n");
do {
printf("\n\t請選擇操作:\t");
*choose1=Input_Choose();
}while(*choose1<0||*choose1>4);
rewind(stdin); /*清空鍵盤緩衝區裏的無用字符*/
}
/* 21*******************進入日記菜單並選擇操作************************/
void Print_Menu2(int *choose2)
{
printf("\n\t\t\t “日記操作”---------(ESC返回上級)\n");
printf("\t|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^|\n");
printf("\t| 1.寫日記 2.導入日記 3.日記列表 4.查閱與刪除 5.更改用戶密碼 |\n");
printf("\t|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^|\n");
do {
printf("\n\t請選擇操作:\t");
*choose2=Input_Choose();
}while(*choose2<0||*choose2>5);
rewind(stdin); /*清空鍵盤緩衝區裏的無用字符*/
}
/* 22 *******************進入日記查閱菜單並選擇操作*********************/
void Print_Menu3(int *choose3)
{
printf("\n\t\t “日記查閱與刪除”---------(ESC返回上級)\n");
printf("\t|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^|\n");
printf("\t| 1.日記列表 2.按順序查閱 3.按標題查閱 4.按日期查閱 5.按關鍵字查閱 |\n");
printf("\t|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^|\n");
do {
printf("\n\t請選擇操作:\t");
*choose3=Input_Choose();
}while(*choose3<0||*choose3>5);
rewind(stdin); /*清空鍵盤緩衝區裏的無用字符*/
}
/* 23 ********************顯示用戶列表**********************/
int Printf_users(User *U1)
{ int count=0;
User *p;
p=U1;
printf("\n\n\t用戶信息列表如下:\n\n");
if(U1->nextu==NULL)
printf("\n\t沒有用戶信息!.....\n");
else
{ while(p->nextu!=NULL)
{ p=p->nextu;
count++;
printf("\t第%d個用戶==>用戶名:%s\n",count,p->username);
}
}
return 1;
}
/* 24 *********************日記保存************************/
int Save_Diary(Diary *D1)
{FILE *fp;
char FileName[40],postfix[6]=".txt\0";
printf("\t請輸入文件路徑及文件名:");
scanf("%s",FileName);
if((fp=fopen(FileName,"w+"))==NULL)
{
printf("\t打開文件失敗!");
return 0;
}
fprintf(fp,"\t日期: %s\n",D1->date);
fprintf(fp,"\t標題: %s\n",D1->title);
fprintf(fp,"\t關鍵字: %s\n",D1->keyword);
fprintf(fp,"\t正文如下:\n\t%s\n",D1->content);
fclose(fp);
printf("\t日記文件保存成功!");
return 1;
}
/* 25 ***********************保存用戶信息********************/
int Save_Users_info(User *U1)
{
FILE *fp;
Diary *D1;
int temp;
char filepn[20];/*用來存放文件保存路徑以及文件名*/
printf("\n\n\t--------------------------------------------------\n");
printf("\t是否保存本次使用所做的所有操作?...\t1-是 0--否\t");
printf("\n\t--------------------------------------------------\n\t");
printf("請選擇操作:\t");
temp=Input_Choose();
if(temp==1)
{
strcpy(filepn,"Users_info.txt");
if((fp=fopen(filepn,"w+"))==NULL)
{
printf("不能打開文件!\n");
return 0;
}
while(U1->nextu!=NULL)
{ fprintf(fp,"User:\n");
U1=U1->nextu;/*下移一個結點*/
fprintf(fp,"用戶名:%s\n密碼:%s\n",U1->username,U1->password);
D1=U1->diarys_list;
while(D1->nextd!=NULL)
{
D1=D1->nextd;
fprintf(fp,"Diary:\n");
fprintf(fp,"\t日期:%s\n\t關鍵字: %s\n",D1->date,D1->keyword);
fprintf(fp,"\t標題:%s\n",D1->title);
fprintf(fp,"\t日記內容:\n%s\n",D1->content);
}
}
fclose(fp);
}
return 0;
}
/* 26 **********************日記查閱*************************/
int Search_Diary(Diary *D1)
{ char tempch='1';
char cmpword[20];
int choose3;
Diary *p;
while(tempch!=ESC)
{ system("cls");
Print_Menu3(&choose3);
p=D1;
if(p->nextd==NULL)
printf("\n\t沒有日記......\n");
else
{
switch(choose3)
{ case 0: return 0;
case 1:
{ printf("\n\t該用戶有以下日記:\n\n");
Printf_DiaryList(D1);
}break;
case 2:Search_order(D1);break;
case 3:{ printf("\n\t參考標題: 我不再愛你了");
printf("\n\t請輸入要查閱的日記標題:\t");
scanf("%s",cmpword);
Filter_word(D1,cmpword,1);
}break; //按標題查閱
case 4:{ printf("\n\t請輸入要查閱的日記日期(2009-4-11):\t");
scanf("%s",cmpword);
Filter_word(D1,cmpword,2);
} break; //按日期查閱
case 5:{ printf("\n\t請輸入要查閱的關鍵字(如:想你):\t");
scanf("%s",cmpword);
Filter_word(D1,cmpword,3);
}break; //按關鍵字查閱
}
}
Initial_Tag(D1,0);
tempch=getch();
rewind(stdin); /*清空鍵盤緩衝區裏的無用字符*/
}
return 1;
}
/* 27 *********************按順序查閱*********************/
Diary *Search_order(Diary *D1)
{ int choose,count,count1=0;
int temp;
Diary *D;
D=D1;
count=Printf_DiaryList(D);
if(count>0)
{ do
{ printf("\n\t您要查閱的是第幾篇(<=%d):\t",count);
choose=Input_Choose();
}while(choose<1||choose>count);
while(D->nextd!=NULL)
{ if(D->nextd->tag==0)
{
if(count1==choose-1)
{ Open_Diary(D->nextd);
printf("\n\n\t--------------------------------------------------\n");
printf("\t是否要刪除此篇日記?\t1-是 0--否\t");
printf("\n\t--------------------------------------------------\n\t");
printf("\t請選擇操作:\t");
temp=Input_Choose();
if(temp==1)
Delete_Diary(D); //刪除P的下一個結點
return D;
}
count1++;
}
D=D->nextd;
}
}
else if(count==0)
printf("\n\t沒有符合查閱要求的日記.....");
return D;
}
/* 28 *********************按標題、日期、關鍵字查閱****************************/
Diary *Filter_word(Diary *D1,char cmpword[],int n) //採用的是篩選算法
{ char *temp=NULL;
Diary *D,*D2;
Initial_Tag(D1,0);
D=D1;
while(D->nextd!=NULL)
{ if(n==1)
temp=strstr(D->nextd->title,cmpword);
else if(n==2)
temp=strstr(D->nextd->date,cmpword);
else if(n==3)
temp=strstr(D->nextd->keyword,cmpword);
if(temp==NULL)
D->nextd->tag=-1;
D=D->nextd;
}
printf("\n\n\t有以下的日記符合查閱要求:\n");
D2=Search_order(D1);
Initial_Tag(D1,0);
return D1;
}
/* 29 ******************************登錄個人用戶*************************/
User *User_Login(User *U1) //登錄成功返回改用戶的日記鏈表指針
{ int i=0,temp;
User *s=NULL,*tempU=NULL;
printf("\n\t--------------------------------------------------\n");
printf("\t是否要顯示用戶列表?\t1-是 ESC--否\t");
printf("\n\t--------------------------------------------------\n\t");
temp=Input_Choose();
if(temp==1)
Printf_users(U1);
printf("\n\t系統默認用戶:admin 密碼:123 \n");
s=Init_User(s);
tempU=Init_User(tempU);
printf("\t請輸入用戶名:\t");
scanf("%s",&s->username);
tempU=Find_User(U1,s->username);
if(tempU==NULL)
{printf("\n\t該用戶不存在!......\n");
getch();
}
else
{
printf("\t請輸入密碼:\t");
rewind(stdin);
Enter_Password(s->password);
Encrypt_Password(s->password);
if(strcmp(tempU->password,s->password)==0)
return tempU;
else
printf("\n\t密碼錯誤!.....\n\n");
getch();
}
return NULL;
}
/* 30 **********************寫新的日記**************************/
int Write_Diary(Diary *D1)
{ int temp;
Diary *p=NULL;
p=Init_Diary(p);
p=(Diary *)malloc(sizeof(Diary));
printf("\n\n\t請輸入日期(2008-12-31):\t");
scanf("%s",&p->date);
printf("\n\t請輸入標題:\t");
scanf("%s",&p->title);
printf("\n\t請開始寫日記:......\n\n\t");
scanf("%s",&p->content);
printf("\n\t請爲該日記寫關鍵字:\t");
scanf("%s",&p->keyword);
p->tag=0;
p->nextd=D1->nextd;
D1->nextd=p;
printf("\n\t--------------------------------------------------\n");
printf("\t是否要以文件方式保存日記?\t1-是 0--否\t");
printf("\n\t--------------------------------------------------\n\t");
temp=Input_Choose();
if(temp==1)
Save_Diary(p);
return 1;
}
/* 31**********************主菜單**************************/
int main()
{ User *U1=NULL;
User *U2=NULL;
Diary *D1=NULL;
int choose1;
char tempch='1',FileName[20];
U1=Init_User(U1);
D1=Init_Diary(D1);
Open_Users_info(U1);
while(tempch!=ESC)
{
system("cls");
Print_Menu1(&choose1); //輸出菜單,並輸入choose的值
switch(choose1)
{
case 0: Save_Users_info(U1);return 0;
case 1:
{ U2=User_Login(U1);
if(U2!=NULL)
{
D1=U2->diarys_list;
if(Diary_Operation(U2,D1)==1)
tempch=getch();
}
}break;
case 2: { Create_NewUser(U1);
tempch=getch();
}break;
case 3: { Printf_users(U1);
tempch=getch();
}break;
case 4: {system("cls");
strcpy(FileName,"help.txt");
Open_File(FileName);
tempch=getch();
}break;
}
system("cls");
}
Save_Users_info(U1);
system("PAUSE");
return 1;
}