<span style="font-family: Arial, Helvetica, sans-serif;">/*</span>
******************************************************************
C語言的課程設計 現在開源 希望可以幫助到一些 測試文件沒有附上 自己寫一份就行
@課題設計:學生通訊錄管理系統
@設計時間:2014.2.24
@設計人: 2012級軟件工程專業 劉小洋
@設計題目:學生通訊錄管理系統
@計算機配置:windows 7 旗艦版 32位操作系統 內存:4G CPU :i5--3210
@運行環境:Microsoft Visual C++ 6.0
@設計思路:建立8個子函數,分別用來添加、顯示、刪除、查詢、修改、保存,讀取和統計通訊錄信息,完成通訊錄的功能。
主函數採用密碼,保護了通訊錄數據,可以調用8個子函數,分別完成添加記錄、顯示記錄、刪除記錄、查詢記錄、
修改記錄、保存記錄、讀取記錄、統計記錄、退出系統等功能。在主函數中可以以1、2、3、4、5、6、7、8、9、10、0數字
鍵分別可以執行某個功能模塊。最後在對文件進行加密、解密功能。
@擴展功能:利用system系統函數,實現對程序功能的擴展,爲了方便用戶和大衆軟件的設計方法,利用系統函數system調用windows
dos 命令實現對計算機的關機,重啓,定時關機,註銷等功能。
@主要函數:int Menu_select() 系統用戶登錄後的菜單
int Input(Student stu[]) 添加記錄函數
int sum(Student stu[]) 統計記錄函數(男 女 總 人數)
void Display(Student stu[]) 顯示記錄函數
int Delete(Student stu[]) 刪除記錄函數
void Chick(Student stu[]) 查找記錄函數
void Change(Student stu[]) 修改記錄函數
void WritetoText(Student stu[]) 寫入文件函數
void Read(Student stu[]) 讀取文件函數
void Menu() 對應int Menu_select()函數的子菜單 他調用除主函數意外的所有函數
void encfile(char *in_filename,char *pwd,char *out_file) 文件加密函數
void unencfile(char *in_filename,char *pwd,char *out_file) 文件解密函數
int unpasswd() 解密函數
int passwd() 調用文件加密的函數
int main() 主函數設置密碼功能 調用 Menu 函數
@通訊錄密碼:用戶名:lhy 密碼 :201314
******************************************************************
*/
//#include"stdafx.h"
#include"stdio.h"
#include<stdlib.h>
#include<conio.h>
#include<string.h> // 頭文件
static int n=0; // 定義靜態全局變量,存儲已經讀入記錄的條數。
void encfile(char *in_filename,char *pwd,char *out_file) ; //函數聲明
int passwd(); //函數聲明
int unpasswd(); //函數聲明
void shut(); //函數聲明,c語言關機的函數。
//定義結構體用來存放學生的學號、姓名、性別、工作單位、電話號碼、郵箱的信息。
typedef struct
{
long score; /*學號*/
char name[10]; /*姓名*/
char sex[8]; /*性別*/
char adds[20]; /*工作單位*/
char num[15]; /*電話號碼*/
char email[20]; /*郵箱*/
}Student;
Student T[100];
/*
主菜單 利用 do while、printf簡單實現 調用系統函數顯示當前系統的時間和日期。
這個函數主要供void Mean函數調用。
*/
int Menu_Select()
{
char c;
do{
system("cls"); //清屏
system("date /T");//顯示系統當前日期
system("time /T");//顯示系統當前時間
system("color 0a");//改變控制檯前景,背景顏色
printf("\t\t\t***學生通訊錄***** \n");
printf("\t\t\t******************\n");
printf("\t\t\t* 1. 添加記錄 *\n");
printf("\t\t\t* 2. 顯示記錄 *\n");
printf("\t\t\t* 3. 刪除記錄 *\n");
printf("\t\t\t* 4. 查詢記錄 *\n");
printf("\t\t\t* 5. 修改記錄 *\n");
printf("\t\t\t* 6. 保存記錄 *\n");
printf("\t\t\t* 7. 讀取記錄 *\n");
printf("\t\t\t* 8. 統計記錄 *\n");
printf("\t\t\t* 9. 文件解密 *\n");
printf("\t\t\t* *. 其他功能 *\n");
printf("\t\t\t* 0. 退出程序 *\n");
printf("\t\t\t*****************\n");
printf("\t\t\t請您選擇(0-9)選擇 其他功能 請輸入':':");
c=getchar();
}while(c<'0'||c>'10');
return(c-'0');
}
/*
添加記錄功能函數,利用scanf 重複對結構體每一個要輸入的學生信息添加,
最後輸入Y N 是否要繼續添加記錄 利用 while對輸入的內容比較。
這裏需要的注意的是
** 如果已經有文件讀入,對n+i是對當前文件的下一條進行添加。
*/
int Input(Student stu[])
{
int i=0;
char sign;
while(sign!='n'&&sign!='N')
{
printf("\t學號:");
scanf("\t%d",&stu[n+i].score);
printf("\t姓名:");
scanf("\t%s",stu[n+i].name);
printf("\t性別:");
scanf("\t%s",stu[n+i].sex);
printf("\t電話號碼:");
scanf("\t%s",stu[n+i].num);
printf("\t工作地址:");
scanf("\t%s",stu[n+i].adds);
printf("\t電子郵箱:");
scanf("\t%s",stu[n+i].email);
printf("\n\t是否繼續添加?(Y/N)");
scanf("\t%c",&sign);
i++;
}
return(n+i);
}
/*
統計通訊錄總人數,其中包括男生、女生人數各個總人數。
利用strcmp函數進行比較得出男生人數,自然女生人數就出來了。
*/
int sum(Student stu[])
{
int a=0,b=0,i;
for(i=0;i<n;i++)
{
if(strcmp(stu[i].sex,"男")==0) //比較函數
a++;
}
b=i-a;
printf("\t\t通訊錄總人數爲%d個,\n\t\t 其中男孩有%d個。\n",i,a);
printf("\t\t 其中女孩有%d個。\n",b);
return(n);
system("pause");
}
/*
通訊錄的顯示函數。for循環和printf依次對結構體輸出。
*/
void Display(Student stu[])
{
int i;
printf("------------------------------------------------------------------------------\n"); //顯示的格式
printf("學號 姓名 性別 電話號碼 工作單位 電子郵箱\n");
printf("------------------------------------------------------------------------------\n");
for(i=1;i<n+1;i++)
printf("%-14d%-8s%-6s%-13s%-15s%-15s\n",stu[i-1].score,stu[i-1].name,stu[i-1].sex,stu[i-1].num,stu[i-1].adds,stu[i-1].email);
//-14d% -表示左對齊 14 表示十四個字節的位置 不足用空格補齊
printf("----------------------------------------------------------------------\n");
system("pause"); //系統函數停止。
}
/*
刪除學生通訊錄的記錄函數,這裏利用學號作爲索引,利用strcmp 函數比對
操作完成之後有對刪除是否成功進行判斷
**原理:被刪除記錄的後一條記錄覆蓋當前記錄的原理。
*/
int Delete(Student stu[])
{
int i=0,j;
long m;
printf("\t請輸入想刪除記錄中的學號:");
scanf("%d",&m);
while(stu[i].score!=m&&i<n)i++;
if(i==n)
{
printf("\t通訊錄中沒有此人!\n");
}
else
{
for(j=i;j<n-1;j++)//後一條記錄覆蓋前一條記錄
{
strcpy(stu[j].num,stu[j+1].num);
strcpy(stu[j].name,stu[j+1].name);
strcpy(stu[j].sex,stu[j+1].sex);
strcpy(stu[j].adds,stu[j+1].adds);
strcpy(stu[j].email,stu[j+1].email);
stu[j].score=stu[j+1].score;
}
printf("\t\t\t已經成功刪除!\n");
n=n-1;
}
return (n);
}
/*
查詢通訊錄,三種查詢方式的原理相同,都是利用while循環遍歷每一條結構體
利用strcmp進行比對,如果有跟所查詢的信息匹配的對象,利用循環變量記錄當前位置
然後printf輸出此時位置所對應的信息
**這裏要對人物的名字進行特殊處理,因爲我們生活中不排除有兩個名字一樣的人。
*/
void Chick(Student stu[])
{
int m;
printf("\t\n請選擇查詢方式:\n"); //printf輸出查詢格式
printf("\t**************************************\n");//格式:
printf("\t**1---姓名查詢(不建議用這種方式查詢)**\n");
printf("\t**2--電話查詢(建議使用) **\n");
printf("\t**3--地址查詢 **\n");
printf("\t**************************************\n");
printf("請選擇:");
scanf("%d",&m);
while(m!=1&&m!=2&&m!=3)
{
printf("輸入錯誤,請重新選擇:");
scanf("%d",&m);
}
if(m==1) //此處對名字進行特殊處理
{
char s[20];
int i=0;
printf("\t請輸入想查詢的姓名:");
scanf("\t%s",s);
loop:while(strcmp(stu[i].name,s)!=0&&i<n )
{ //名字如果有重複的也照常輸出
i++;
}
if(i==n)
{
printf("\t通訊錄中沒有此人!\n");
return;
}
else
{
printf("\t學生學號: %d\n",stu[i].score);
printf("\t學生性別: %s\n",stu[i].sex);
printf("\t電話號碼: %s\n",stu[i].num);
printf("\t工作地址: %s\n",stu[i].adds);
printf("\t電子郵箱: %s\n",stu[i].email);
}
if(i<n-1) //運用 goto 語句實現對人名重複的人全部輸出。
{
i++;
goto loop;
}
} ;
if(m==2)//用電話作爲索引查詢
{
char s[20];
int i=0;
printf("\t請輸入想查詢的電話:");
scanf("\t%s",s);
while(strcmp(stu[i].num,s)!=0&&i<n) i++;
if(i==n)
{
printf("\t通訊錄中沒有此人!\n");
return;
}
printf("\t學生學號: %d\n",stu[i].score);
printf("\t學生姓名: %s\n",stu[i].name);
printf("\t學生性別: %s\n",stu[i].sex);
printf("\t工作地址: %s\n",stu[i].adds);
printf("\t電子郵箱: %s\n",stu[i].email);
} ;
if(m==3)//用地址作爲索引查詢
{
char s[20];
int i=0;
printf("\t請輸入想查詢的地址:");
scanf("\t%s",s);
while(strcmp(stu[i].adds,s)!=0&&i<n) i++;
if(i==n)
{
printf("\t通訊錄中沒有此人!\n");
return;
}
printf("\t學生學號: %d\n",stu[i].score);
printf("\t學生姓名: %s\n",stu[i].name);
printf("\t學生性別: %s\n",stu[i].sex);
printf("\t電話號碼: %s\n",stu[i].num);
printf("\t電子郵箱: %s\n",stu[i].email);
} ;
}
/*
修改通訊錄,這裏利用學號作爲索引信息。如果通訊錄中沒有此人,則返回一條信息。
**這裏學號作爲索引信息,用long 長整型。
*/
void Change(Student stu[])
{
int i=0;
long m;
printf("\t請輸入想修改的記錄中人的學號:");
scanf("%d",&m);
while(stu[i].score!=m&&i<n)
i++;
if(i==n)
{
printf("\t通訊錄中沒有此人!\n");
return;
}
printf("\t學號:");
scanf("\t%d",&stu[i].score);
printf("\t姓名:");
scanf("\t%s",stu[i].name);
printf("\t性別:");
scanf("\t%s",stu[i].sex);
printf("\t電話號碼:");
scanf("\t%s",stu[i].num);
printf("\t工作地址:");
scanf("\t%s",stu[i].adds);
printf("\t電子郵箱:");
scanf("\t%s",stu[i].email);
printf("\t修改成功!");
}
/*
寫入文件函數。fopen fclose 打開關閉文件 'W'進行些操作。詳見譚浩強C 語言第十章。
若打不開文件,則執行system系統函數退出。
*/
void WritetoText(Student stu[])
{
int i=0;
FILE *fp; /*定義文件指針*/
char filename[20]; /*定義文件名*/
printf("\t保存到文件\n"); /*輸入文件名*/
printf("\t請輸入所保存的文件名:");
scanf("\t%s",filename);
if((fp=fopen(filename,"w"))==NULL)
{
printf("\t無法打開文件\n");
system("pause");
return;
}
while(i<n)
{
fprintf(fp,"%-13d%-6s\t%-3s\t%-13s\t%-20s\t%-20s\n",stu[i].score,stu[i].name,stu[i].sex,stu[i].num,stu[i].adds,stu[i].email);
i++;
}
fclose(fp); /*關閉文件*/
printf("保存成功!\n");
}
/*
讀取文件,這裏不會上網找的。
*/
void Read(Student stu[])
{
FILE *fp;
int i;
char filename[20];
printf("輸入要讀入的文件名:");
scanf("\t%s",filename);
if((fp=fopen(filename,"r"))==NULL)
{
printf("找不到%s文件!\n",filename);
system("pause");
exit(0);
}
n=0;
// fseek(fp,0L,SEEK_SET); //設置偏移量 SEEK_SET: 文件開頭 數值爲0 ;意思爲:把文件內部指針移動到離文件開頭0 字節處;0L:表示離文件開頭多少個字節。
for(i=0;i<100&&!feof(fp);i++) //這裏的100 是前面已經說明了 最多可以存100條記錄
{
fscanf(fp,"%d %s %s %s %s %s\n",&stu[i].score,stu[i].name,stu[i].sex,stu[i].num,stu[i].adds,stu[i].email);
n++;
}
fclose(fp);
printf("讀取成功,文件%s中的所有信息已經讀入!\n",filename);
}
void Menu()
{
for(;;) //讓這裏程序循環,否則就退出程序了。
{
switch(Menu_Select())
{
case 1:
printf("\n\t添加記錄到通訊錄\n"); /*添加記錄*/
n=Input(T);
break;
case 2:
printf("\n\t\t\t 通訊錄記錄表\n"); /*顯示記錄*/
Display(T);
break;
case 3:
printf("\n\t從通訊錄中刪除記錄\n");
n=Delete(T); /*刪除記錄*/
printf("\t");
system("pause"); /*按任意鍵繼續*/
break;
case 4:
printf("\n\t在通訊錄中查找記錄\n");
Chick(T); /*查找記錄*/
printf("\t");
system("pause");
break;
case 5:
printf("\n\t修改通訊錄中的記錄\n");
Change(T); /*修改數據*/
printf("\t");
system("pause");
break;
case 6:
printf("\n\t保存功能\n");
WritetoText(T); /*保存數據*/
passwd();
printf("\t");
system("pause");
break;
case 7:
printf("\n\t讀取功能\n");
Read(T); /*讀取數據*/
printf("\t");
system("pause");
break;
case 8:
printf("\n\t****學生通訊錄統計人數****\n\n"); /*統計記錄*/
sum(T);
system("pause");
break;
case 9:
printf("\n\t****對學生文件進行解密處理****\n\n"); /*解密處理*/
unpasswd();
system("pause");
break;
case 10: //用C語言實現對計算機的開機 關機 重啓 定時關機 /*其他功能*/
shut();
system("pause");
break;
case 0:
printf("\n\t\t\t歡迎您再次使用本程序!\n"); /*結束程序*/
printf("\n\t\t本程序只適合個人娛樂溝通使用,謝絕商業用途。\n");
printf("\n\t\t\n");
system("pause");
exit(0);
}
}
}
/*
加密函數:利用異或運算的特點對文件進行的加密,
一個數跟同一個數異或兩次,數值本身不變。利用這個原理我們可以先對文件的所有字節進行一次異或,
然後解密就是將加密文件的所有字節與上次加密異或相同的字符或字符串,以達到加密解密的目的。
** 黑馬程序員 教學視頻裏面提到過。
*/
void encfile(char *in_filename,char *pwd,char *out_filename) //加密函數
{
FILE *fp1,*fp2;
char ch;
int j=0;
int j0=0;
fp1=fopen(in_filename,"rb");
if(fp1==NULL)
{
printf("cannot open in-file.\n");
exit(1); //退出
}
fp2=fopen(out_filename,"wb");
if(fp2==NULL)
{
printf("cannot open or create out-file.\n");
exit(1); //退出
}
while(pwd[++j0]); //計算祕鑰長度
ch=fgetc(fp1); //讀取文件的每一個字節
/*加密算法開始*/
while(!feof(fp1))
{
fputc(ch^pwd[j>=j0?j=0:j++],fp2); /*異或後寫入fp2文件*/
ch=fgetc(fp1); //讀取文件的全部字節
}
printf("恭喜文件加密成功!\n");
printf("請牢記您的密碼!\n");
fclose(fp1);/*關閉源文件*/
fclose(fp2);/*關閉目標文件*/
}
/*
這個函數主要是對上面加密函數的調用,注意的問題是當輸入一個以上字符串是用 fflush(stdin)函數清理當前緩存。
*/
int passwd()//加密調用函數
{
char in_filename[30]; /*用戶輸入的要加密的文件名*/
char out_filename[30]; /*用戶輸入加密後保存的文件名*/
char pwd[8]; /*用來保存密碼*/
/* printf("\t爲了安全起見,這裏要對文件做加密處理:\n"); //反覆調試還是沒有通過。。。。。
printf("\t請輸入要加密文件的名字:");
scanf("\t s%",in_filename);
fflush(stdin);
printf("\t請輸入加密後的文件名:");
scanf("\t s%",out_filename);
fflush(stdin);
printf("\t 請輸入密碼(不超過8位):");
scanf("\t s%",pwd);
fflush(stdin);
*/
printf("\t爲了安全起見,這裏要對文件做加密處理:\n");//錯誤處理:這裏反覆調試了很多次了 結果就是沒有用 fflush(stdin) 清空緩存。
printf("\t\n請輸入需要加密文件的名字:\n");
fflush(stdin); //清空緩存 切記
gets(in_filename); //獲取要加密的文件名
printf("\t\n請輸入加密的密碼:\n");
gets(pwd); //獲取密碼
printf("\t\n請輸入加密後文件的名字\n");
gets(out_filename); //加密後的文件名
encfile(in_filename,pwd,out_filename);
return 0;
}
void unencfile(char *in_filename,char *pwd,char *out_filename) //解密函數
{
FILE *fp1,*fp2;
char ch;
int j=0;
int j0=0;
fp1=fopen(in_filename,"rb");
if(fp1==NULL)
{
printf("cannot open in-file.\n");
exit(1); //退出
}
fp2=fopen(out_filename,"wb");
if(fp2==NULL)
{
printf("cannot open or create out-file.\n");
exit(1); //退出
}
while(pwd[++j0]); //計算祕鑰長度
ch=fgetc(fp1); //讀取文件的每一個字節
/*加密算法開始*/
while(!feof(fp1))
{
fputc(ch^pwd[j>=j0?j=0:j++],fp2); /*異或後寫入fp2文件*/
ch=fgetc(fp1); //讀取文件的全部字節
}
printf("恭喜文件解密成功!\n");
printf("現在你可以對文件進行修改了!\n");
fclose(fp1);/*關閉源文件*/
fclose(fp2);/*關閉目標文件*/
}
int unpasswd()//解密調用函數
{
char in_filename[30]; /*用戶輸入的要解密的文件名*/
char out_filename[30]; /*用戶輸入解密後保存的文件名*/
char pwd[8]; /*用來保存密碼*/
/* printf("\t爲了安全起見,這裏要對文件做解密處理:\n");
printf("\t請輸入要解密文件的名字:");
scanf("\t s%",in_filename);
fflush(stdin);
printf("\t請輸入解密後的文件名:");
scanf("\t s%",out_filename);
fflush(stdin);
printf("\t 請輸入密碼:");
scanf("\t s%",pwd);
fflush(stdin);
*/
printf("\t\n請輸入需要解密文件的名字:\n");
fflush(stdin);
gets(in_filename); //獲取要加密的文件名
printf("\t\n請輸入密碼:\n");
gets(pwd); //獲取密碼
printf("\t\n請輸入解密後文件的名字\n");
gets(out_filename); //加密後的文件名
unencfile(in_filename,pwd,out_filename);
return 0;
}
/*
C語言的關機程序,主要調用windows DOS 系統下的system 函數
*/
int print()
{
printf(" ╪╪╪╪╪╪╧╧╧╧╧╧╧╧╪╪╪╪╪╪\n");
printf("╔═══╧╧C語言關機程序 ╧╧═══╗\n");
printf("║******本程序有劉洪陽製作*******\n");
printf("║**********計算機學院***********\n");
printf("║*******************************\n");
printf("║※1.實現10分鐘內的定時關閉計算機║\n");
printf("║※2.立即關閉計算機 ║\n");
printf("║※3.註銷計算機 ║\n");
printf("║※4.重啓計算機 ║\n");
printf("║※0.退出系統 ║\n");
printf("╚════════════════╝\n");
return 0;
}
void shut()
{
char cmd[20]="shutdown -s -t ";
int c;
char t[5]="0";
system("title C語言關機程序 作者:劉小洋");//設置cmd窗口標題
system("mode con cols=45 lines=25");//窗口寬度高度
system("color 0B");
system("date /T");
system("TIME /T");
print();
scanf("%d",&c);
getchar();
switch(c)
{
case 1:printf("您想在多少秒後自動關閉計算機?(0~600)\n");scanf("%s",t);system(strcat(cmd,t));break;
case 2:system("shutdown -p");break;
case 3:system("shutdown -l");break;
case 4:system("shutdown -r");break;
case 0:break;
default:printf("Error!\n");
}
system("pause");
exit(0);
}
/*
主函數,通過for循環和strcmp函數實現密碼功能,登陸成功後可以調用Menu函數。
我們定義的Menu函數主要是利用switch語句對數據進行處理,switch語句相應的字句按各自的內容
調用前面已經寫好的相應的函數。
*/
int main()
{
int flag1;
char name[20]="lhy";
char person[20];
char ch[7];
int i,n;
system("title 通訊錄管理系統 作者:劉洪陽");//控制檯標題修改
system("date /T"); //顯示系統當前日期
system("time /T"); //顯示系統時間
system("color 0b");//修改控制檯前景,背景顏色
//設置的控制檯輸出的格式
printf ("\t\t **********通訊錄管理系統!**********\n\n");
printf ("\t\t\t\t用 戶 登 錄 \n\n");
printf("\t\t\t\t username:");
gets(person);
flag1=strcmp(person,name);
printf("\t\t\t\t password:");
for(i=0;i<3;i++)
{
for(n=0;n<6;n++)
{
ch[n] = getch();
printf("*");
}
printf("\n");
ch[n] = '\0';
if(0 == strcmp(ch,"201314"))
{
printf("\t\t\t\t管理員你好,歡迎你進入本系統!\n");
getch();
Menu();
break;
}
else
{
printf("密碼錯誤,請重新輸入\n");
}
}
if(i==3)
{
printf("你輸入的錯誤的密碼次數達到上限,系統自動退出!請聯繫管理員!");
exit(1);
}
/* gets(password1);
flag2=strcmp(password,password1);
if(flag1==0 && flag2==0) //密碼驗證
{
printf("\t\t\t\t Welcome !\n\t\t\t\t Press any key to enter the menu!\n");//格式
getch();
Menu();
break;
}
else
{
printf ("\t\t\t Your username or password is wrong!\n\t\t\t\t Please input again!\n");
printf ("\t\t\t pay attention you will hava %d chance! \n\n",4-h);
h++;
}
}
if (h=5) //錯誤提示次數
printf ("對不起,您輸入的用戶名或密碼有誤,已被強制退出。\n");
*/
return 0;
}