<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;
}