C语言实现加密通讯录雏形

本程序用C写成,鼓励批评指正! 
Name:Contact++ 
Version:0.2 
Powered By GenialX 
From 沈阳化工大学2011级 
URL:胡旭-煦生活 - 胡旭个人博客 - 一个自由大学生的琐碎 
QQ:2252065614 
QQ交流群:235173087(欢迎加入,增增人气儿...) 
---2013.02.07 
基本功能实现: 
通讯录信息插入、删除、编辑、查找、修改以及信息存盘(contact.ctt)。 

实现原理: 
利用指针操作链表实现通讯录功能。 

记录: 
添加给存盘文档加密的功能(存档文件即根目录下的contact.ctt文件) 
详细:利用异或加密,由于异或操作的特性,所以加密和解密调用,同一个实现即可。 
步骤: 
1、定义密钥常量KEY(默认值为'x')。 
2、修改getInfo()函数。首先创建一个临时文件tmp.ctt(属性设置成系统隐藏文件),然后把源文件(加密文件)读取,并将解密后的内容放入tmp.ctt中。然后将tmp.ctt中的内容逐步读入链表,之后删除临时文件tmp.ctt。 
3、修改saveRecords()函数。原理基本同上,创建系统隐藏文件作为临时缓冲文件(tmp.ctt),之后删除。 
---2013.02.07  21:01 
定义常量 
详细:将一些信息定一场全局常量,便于管理。比如:作者信息。 
---2013.02.08  08:26 
源码:

  1 /**
  2  * @Name:Contact++
  3  * @Desc:这是一个实现通讯录的C源代码
  4  * @Version:0.2
  5  * @Author:GenialX
  6  * @From:沈阳化工大学2011级
  7  * @URL:http://www.ihuxu.com
  8  * @QQ:287156904
  9  * @QQ Group:235173087
 10  */
 11 
 12 #include <stdio.h>
 13 #include <stdlib.h>
 14 #include <string.h>
 15 #include <windows.h>
 16 
 17 //这里定义的是联合体中字符数组的长度。
 18 #define C_NAME_SIZE 10
 19 #define C_SEX_SIZE 3
 20 #define C_AGE_SIZE 5
 21 #define C_PHONE_SIZE 12
 22 #define C_QQ_SIZE 12
 23 #define C_PROVINCE_SIZE 20
 24 #define C_CITY_SIZE 20
 25 #define C_COMMENT_SIZE 100
 26 
 27 //亲,很明显,这是函数说明!
 28 void insRecord();//插入一条记录的实现
 29 void inputs(char *prompt,char *info,int count);//插入一条记录时,逐行输入信息的实现
 30 struct addr *linkNode(struct addr *i,struct addr *top);//输入完一条记录后,将当前的缓冲节点连接到链表中的实现
 31 struct addr *find(char *name);//查找出指定的节点的实现
 32 void seaRecord();//查找记录的实现
 33 void delRecord();//删除记录的实现
 34 int selectMenu();//主菜单的实现
 35 void disRecord(addr *info);//显示一条记录的实现
 36 void disRecords();//显示全部记录的实现
 37 void getInfo(); //根据ctt文本中的记录,逐条返回数据项,并实现将信息插入链表,即程序启动的初始化状态的实现
 38 void initInputs(char *initInfo[]);//输入完一条记录后,将当前的缓冲节点连接到链表中的实现
 39 void saveRecords();//将链表中的信息全部写到磁盘文件中的实现
 40 void saveToFile(addr *info);//将每条信息记录放到新建的文件中的实现
 41 void editRecord();//修改记录的实现
 42 void about();//显示作者信息的实现
 43 
 44 
 45 //全局的东东
 46 
 47 //联合体
 48 struct addr
 49 {
 50     char c_name[C_NAME_SIZE];
 51     char c_sex[C_SEX_SIZE];
 52     char c_age[C_AGE_SIZE];
 53     char c_phone[20];
 54     char c_qq[C_QQ_SIZE];
 55     char c_province[C_PROVINCE_SIZE];
 56     char c_city[C_CITY_SIZE];
 57     char c_comment[C_COMMENT_SIZE];
 58 
 59     struct addr *next;//pointer to next entry ^^
 60 };
 61 
 62 //全局指针变量,info存储当前缓冲的节点、start和last存储最后一个节点、head存储头节点
 63 struct addr *info,*start,*last,*head;
 64 //初始化用,与head有关的变量
 65 static int n = 0;
 66 //加密常量
 67 const char KEY='x';
 68 //作者信息
 69 const char AUTHOR[] = "乌鸟";
 70 const char VERSION[] = "0.2";
 71 const char DESC[] = "本程序用C写成,鼓励批评指正!";
 72 const char QQ[] = "235173087(欢迎加入,增增人气儿...)";
 73 const char URL[] = "http://www.ihuxu.com";
 74 const char FROM[] = "沈阳化工大学2011级";
 75 const char TIME[] = "2013.02.08";
 76 const char APPNAME[] = "Contact++";
 77 
 78     /**
 79      * @desc 显示系统菜单的实现
 80      */
 81     int selectMenu()
 82     {
 83         char s[80];
 84         int c;
 85         printf(" ------------------------------- \n");Sleep(50);
 86         printf("|1.Insert a New Record          |\n");Sleep(50);
 87         printf("|2.Delete a Specific Record     |\n");Sleep(50);
 88         printf("|3.Search the Record            |\n");Sleep(50);
 89         printf("|4.Edit the Record              |\n");Sleep(50);
 90         printf("|5.Display All Records          |\n");Sleep(50);
 91         printf("|6.About                        |\n");Sleep(50);
 92         printf("|7.Quit                         |\n");Sleep(50);
 93         do
 94         {
 95             printf(" ------------------------------- \nEnter your choice:");
 96             gets(s);
 97             c = atoi(s);//atoi(),把字符串转换为整形。
 98         }while(c<1||c>7);
 99         return(c);
100     }
101 
102     /**
103      * @desc 插入一条记录的实现
104      */
105     void insRecord()
106     {
107         struct addr *info;//声明缓冲节点,用来指向新记录的节点地址
108 
109         for(;;n++)
110         {
111             //分配地址给info
112             info = (struct addr *)malloc(sizeof(struct addr));
113             //内存不足的情况
114             if(info == NULL)
115             {
116                 printf("Out of memory!\n");
117                 return;//计算机脑容量不够了,结束了插入操作
118             }
119             printf("\nSet 0 to name to exit insert!");
120             inputs("Enter name",info->c_name,C_NAME_SIZE);
121             if(info->c_name[0] == '0')
122             {
123                 printf("\n");
124                 break;
125             }else{
126                     inputs("Enter sex",info->c_sex,C_SEX_SIZE);
127                     inputs("Enter age",info->c_age,C_AGE_SIZE);
128                     inputs("Enter phone",info->c_phone,C_PHONE_SIZE);
129                     inputs("Enter qq",info->c_qq,C_QQ_SIZE);
130                     inputs("Enter province",info->c_province,C_PROVINCE_SIZE);
131                     inputs("Enter city",info->c_city,C_CITY_SIZE);
132                     inputs("Enter comment",info->c_comment,C_COMMENT_SIZE);
133                     start = linkNode(info,start);//感觉start和last存的是一个节点
134                     if(n == 0)
135                     {
136 //                        printf("\nhead has been initialized\nn:%d",n);
137                         head = start;//head就是头结点
138                     }
139             }
140         }
141     }
142     
143 /**
144  * @desc 插入一条记录时,逐行输入信息的实现
145  * @parame char *promot,提示信息
146  * @parame char *info,存储用户输入数据的节点
147  * @parame int count,数据项最大字节数
148  */
149 void inputs(char *prompt,char *info,int count)
150 {
151     char p[50];
152     do
153     {
154         printf("\n%s:",prompt);
155         gets(p);
156 //        puts(p);
157         if(strlen(p)/2>count)
158         {
159             printf("Too long!\n");
160         }
161     }while(strlen(p)/2>count);
162         strcpy(info,p);//将本函数的p地址复制给缓冲info地址
163 //        puts(info);
164 }
165 
166 /**
167  * @desc 在输入好新的消息记录后,需要将新的节点连接在链表中
168  */
169 struct addr *linkNode(struct addr *current,struct addr *top)
170 {
171     if(!last)
172     {
173         last = current;
174         current->next = NULL;
175         return(current);
176     }
177     else
178     {
179         top->next=current;
180         current->next=NULL;
181         last = current;
182         return(current);
183     }
184 }
185 
186 /**
187  * @desc 查找出指定的节点的实现
188  * @return addr *,指定姓名的指针
189  */
190 struct addr *find()
191 {
192     struct addr *info;
193     info = head;
194     int flag;
195     char str[20];
196 
197     printf("按类别查找 1:名字;2:电话;3:QQ;4:省份;5:城市\n");Sleep(50);
198     printf("请输入相应数字:");
199     scanf("%d",&flag);
200 //    printf("%d",flag);
201     getchar();
202     printf("请输入数据:");
203     gets(str);
204 //    puts(str);
205 
206     //我实在是找不着办法如何动态改变info->后面的东西,正好,让我知道知道什么叫面向过程编程!嘻嘻...
207     switch(flag)
208     {
209         case 1:{
210                 while(info)
211                     {
212                         if(!strcmp(str,info->c_name))
213                         {
214                             return(info);
215                         }
216                         else
217                         {
218                         info = info->next;
219                         }
220                     }
221                 return(info = NULL);
222                };break;
223         case 2:{
224                 while(info)
225                     {
226                         if(!strcmp(str,info->c_phone))
227                         {
228                             return(info);
229                         }
230                         else
231                         {
232                         info = info->next;
233                         }
234                     }
235                 return(info = NULL);
236                };break;        
237         case 3:{
238                 while(info)
239                     {
240                         if(!strcmp(str,info->c_qq))
241                         {
242                             return(info);
243                         }
244                         else
245                         {
246                         info = info->next;
247                         }
248                     }
249                 return(info = NULL);
250                };break;        
251         case 4:{
252                 while(info)
253                     {
254                         if(!strcmp(str,info->c_province))
255                         {
256                             return(info);
257                         }
258                         else
259                         {
260                         info = info->next;
261                         }
262                     }
263                 return(info = NULL);
264                };break;        
265         case 5:{
266                 while(info)
267                     {
268                         if(!strcmp(str,info->c_city))
269                         {
270                             return(info);
271                         }
272                         else
273                         {
274                         info = info->next;
275                         }
276                     }
277                 return(info = NULL);
278                };break;
279         default:return(info = NULL);break;
280     }
281 
282 }
283 
284     /**
285      * @desc 查找记录的实现
286      */
287 void seaRecord()
288 {
289     struct addr *info;
290     info = find();
291     printf("请稍后,正在检索信息...\n");Sleep(800);
292     if(info == NULL)//如果是空节点,证明没有找到
293     {
294         printf("Not founded,im so sorry!\n\n");
295         Sleep(300);
296     }
297     else
298     {
299         disRecord(info);
300     }
301 }
302 
303 /**
304  * @desc 显示一条记录的实现
305  * @param addr *info,记录的节点
306  */
307 void disRecord(addr *info)
308 {
309     printf("\nInfo from %s:\n",info->c_name);Sleep(50);
310     printf("Sex:%s\n",info->c_sex);Sleep(50);
311     printf("Age:%s\n",info->c_age);Sleep(50);
312     printf("Phone:%s\n",info->c_phone);Sleep(50);
313     printf("QQ:%s\n",info->c_qq);Sleep(50);
314     printf("Province:%s\n",info->c_province);Sleep(50);
315     printf("City:%s\n",info->c_city);Sleep(50);
316     printf("Comment:%s\n\n",info->c_comment);
317     Sleep(300);
318 }
319 
320 /**
321  * @desc 显示全部信息记录的实现
322  */
323 void disRecords()
324 {
325     struct addr *info = head;
326 
327     if(info == NULL)
328     {
329         printf("\nSoryy,there is no record!\n\n");
330     }
331     else
332     {
333         while(info)
334         {
335             disRecord(info);
336             info = info->next;
337         }
338         return;
339     }
340 }
341 
342 /**
343  * @desc 删除记录的实现
344  */
345 void delRecord()
346 {
347     struct addr *p1,*p2,*info;
348     info = find();
349     printf("正在检索并删除信息...\n");
350     Sleep(800);
351     //这个循环是关键,要好好理解哟!反正我明白喽~~~
352     if(info != NULL)
353     {
354         if(head == info)
355         {
356             head = info->next;
357             printf("%s Deleted Successfully!\n\n",info->c_name);
358             free(info);
359             Sleep(300);
360         }
361         else
362         {
363             p1 = head->next;
364             p2 = head;
365             while(info != p1)
366             {
367                 p2 = p1;
368                 p1 = p1->next;
369             }
370             p2->next = p1->next;
371             printf("%s Deleted Successfully!\n\n",info->c_name);
372             Sleep(300);
373             free(info);
374         }
375     }
376     else
377     {
378         printf("Im trying,but...but,i coundt find it~~~\n\n");    
379         Sleep(300);
380     }
381 }
382 
383 
384 /**
385  * @desc 根据ctt文本中的记录,逐条返回数据项,并实现将信息插入链表,即程序启动的初始化状态的实现
386  */
387 void getInfo()
388 {
389     FILE *fp,*sfp;
390     char ch;
391     char *info[8];
392     char str[100];
393     int m = 0;//给info做标记用的,没当m到7就意味着info数组已满。
394 
395     //初始化提示信息
396     printf("请稍后,系统正在初始化,先上趟厕所吧...\n");
397 
398     //不知道怎么给指针数组赋值,所以,只能这样喽!!!
399     for(int i = 0; i<8;i++)
400     {
401             info[i] = (char *)malloc( sizeof(char)*50 ); 
402     }
403 
404     if((sfp = fopen("Contact.ctt","r")) == NULL)
405     {
406         printf("Initial file cannot be opened!\n");
407     //    info = NULL;
408         return;
409     }
410     else
411     {
412 
413         if((fp = fopen("tmp.ctt","w+")) != NULL){
414             system("attrib +s +h tmp.ctt");
415 
416             ch = fgetc(sfp);//先从源文件中读取一个字符
417 
418             /** 循环解密读取、并写入临时文件 */
419             while(!feof(sfp)){//feof()函数检测指针未到文件尾部,返回0
420                 fputc(ch^KEY,fp);
421 //printf("%c",ch^'x');
422 //printf("||");
423                 ch = fgetc(sfp);
424             }
425                 rewind(fp);//把文件指针放到文件头部,以便重新读取并存入链表。
426                 fclose(sfp);
427             }else{
428 
429                 printf("tmp file cannot be opened!\n");
430             }
431 
432         Sleep(1000);
433         printf("正在载入通讯录信息...\n");
434         while( (ch = fgetc(fp)) != EOF )
435         {
436             if(ch == ':')//开始标志
437             {    
438                 int i = 0;
439                 while( (ch = fgetc(fp)) != EOF && ch != '\n' )
440                 { 
441                     str[i] = ch;
442                 //    printf("%c",str[i]);
443                     i++;
444                     str[i] = '\0';
445                 }
446     //            printf("这是第%d次判断",m);
447                 if(m == 7)//数组即将满,打包数组送给insRecord()
448                 {
449 
450                     strcpy(info[m++],str);
451                 //    puts(info[0]);
452                 //    printf("这里是m7\n");
453                     m = 0;//归0
454     //                printf("传参");
455                     initInputs(info);
456                 }
457                 else
458                 {
459                     strcpy(info[m++],str);
460                     str[0] = '\0';
461                 //    printf("%d",m);
462                 }
463             //    strcpy(info[0],str);
464             //    puts(info[0]);
465             //    此处应该是实现将info的信息逐条加入链表当中的实现
466             //    return info;
467             }
468             else
469             {
470                 
471             }
472         }
473         Sleep(300);
474         printf("初始化完毕!\n");
475         Sleep(300);
476         fclose(fp);
477         system("del tmp.ctt /q /a");
478     }
479 }
480 
481 /**
482  * @desc 输入完一条记录后,将当前的缓冲节点连接到链表中的实现
483  * @param char *,inifInfo[],缓冲节点
484  */
485     void initInputs(char *initInfo[])
486     {
487         struct addr *info;//声明缓冲节点,用来指向新记录的节点地址
488 
489         for(;;n++)
490         {
491             //分配地址给info
492             info = (struct addr *)malloc(sizeof(struct addr));
493             //内存不足的情况
494             if(info == NULL)
495             {
496                 printf("Out of memory!\n");
497                 return;//计算机脑容量不够了,结束了插入操作
498             }
499             //插入链表
500             strcpy(info->c_name,initInfo[0]);
501             strcpy(info->c_sex,initInfo[1]);
502             strcpy(info->c_age,initInfo[2]);
503             strcpy(info->c_phone,initInfo[3]);
504             strcpy(info->c_qq,initInfo[4]);
505             strcpy(info->c_province,initInfo[5]);
506             strcpy(info->c_city,initInfo[6]);
507             strcpy(info->c_comment,initInfo[7]);
508             start = linkNode(info,start);//感觉start和last存的是一个节点
509 //            puts(start->name);
510             if(n == 0)
511             {
512 //                printf("\nhead has been initialized\nn:%d",n);
513                 head = start;//head就是头结点
514             }
515             n++;
516             return;
517         }
518     }
519 
520 /**
521  * @desc 将链表中的信息全部写到磁盘文件中的实现
522  */
523 void saveRecords()
524 {
525     char flag='\0';
526     struct addr *p1,*p2;
527     FILE *fp,*tmpFp;
528 
529     printf("\nPress 'Y' or 'y' to Save,'N' or 'n' to Exit:");
530     flag = getchar();
531     getchar();
532 
533     if(flag == 'Y' || flag == 'y')    //存盘操作
534     {
535 //        printf("我已存盘!\n");    
536         if(head != NULL)
537         {    
538             p1 = head;
539             Sleep(300);
540             printf("\n存盘中,请稍后,要么再上趟厕所吧......\n");
541             Sleep(300);
542             do
543             {            
544             saveToFile(p1);
545             p2 = p1;
546             p1 = p1->next;
547             free(p2);//释放吧!!
548 //            printf("释放中\n");
549             }while(p1 != NULL);
550             /** 将临时文件tmp.ctt加密,并写到Contact.ctt文件中 */
551             //这段的目的是删除原来文件中的内容。
552             fp = fopen("contact.ctt","w+");
553             if( (tmpFp = fopen("tmp.ctt","r")) != NULL){
554                 char ch;
555                 ch = fgetc(tmpFp);
556                 //加密存盘
557                 while(!feof(tmpFp)){
558                     fputc(ch^KEY,fp);
559                     ch = fgetc(tmpFp);
560                 }
561             }else{
562                 printf("打开tmp.ctt的文件失败~!");
563             }
564             fclose(fp);
565             fclose(tmpFp);
566             //删除临时文件
567             system("del tmp.ctt /a");
568             //将结点设置为空
569             head = start = last = NULL;
570             printf("存盘成功!\n");
571             Sleep(1000);
572             return;
573 
574         }
575         else
576         {
577             printf("\nNo Records!\n");
578             Sleep(1000);
579             return;
580         }
581     }
582     else
583     {    Sleep(300);
584         printf("请稍后,正在退出程序...\n");
585         Sleep(300);
586         printf("退出成功!\n");
587         Sleep(1000);
588 
589     }
590     return;
591 }
592 
593 /**
594  * @desc 将每条信息记录放到新建的文件中的实现
595  */
596 void saveToFile(addr *info)
597 {
598     
599     FILE *fp;
600     if ( ( fp = fopen("tmp.ctt","a") ) != NULL )
601     {
602         system("attrib +s +h tmp.ctt");
603         fprintf(fp,"Name:%s\n",info->c_name);
604         fprintf(fp,"Sex:%s\n",info->c_sex);
605         fprintf(fp,"Age:%s\n",info->c_age);
606         fprintf(fp,"Phone:%s\n",info->c_phone);
607         fprintf(fp,"QQ:%s\n",info->c_qq);        
608         fprintf(fp,"Province:%s\n",info->c_province);
609         fprintf(fp,"City:%s\n",info->c_city);
610         fprintf(fp,"Comment:%s\n",info->c_comment);
611         fclose(fp);//关闭文件,以免数据流失
612     }
613     else
614     {
615         printf("文件不存在,存盘失败");
616         Sleep(1000);
617     }
618     return;
619 }
620 
621 /**
622  * @desc 显示作者信息的实现
623  */
624 void about()
625 {
626     Sleep(300);
627     printf("\n%s\n",DESC);Sleep(200);
628     printf("Name:%s\n",APPNAME);Sleep(200);
629     printf("Version:%s\n",VERSION);Sleep(200);
630     printf("Powered By %s\n",AUTHOR);Sleep(200);
631     printf("From %s\n",FROM);Sleep(200);
632     printf("URL:%s\n",URL);Sleep(200);
633     printf("QQ交流群:%s\n",QQ);Sleep(200);
634     printf("                                           ----%s\n\n",TIME);
635     Sleep(800);
636     return;
637 }
638 
639 /**
640  * @desc 修改记录的实现
641  */
642 void editRecord()
643 {    
644     struct addr *info;
645     info = find();
646     printf("请稍后,正在检索信息...\n");Sleep(800);
647     if(info != NULL)
648     {
649         printf("\n修改前的姓名:");
650         puts(info->c_name);
651         printf("\n请输入修改后的姓名:");
652         gets(info->c_name);        
653         printf("\n修改前的性别:");
654         puts(info->c_sex);
655         printf("\n请输入修改后的性别:");
656         gets(info->c_sex);            
657         printf("\n修改前的年龄:");
658         puts(info->c_age);
659         printf("\n请输入修改后的年龄:");
660         gets(info->c_age);            
661         printf("\n修改前的电话:");
662         puts(info->c_phone);
663         printf("\n请输入修改后的电话:");
664         gets(info->c_phone);            
665         printf("\n修改前的QQ:");
666         puts(info->c_qq);
667         printf("\n请输入修改后的QQ:");
668         gets(info->c_qq);            
669         printf("\n修改前的省份:");
670         puts(info->c_province);
671         printf("\n请输入修改后的省份:");
672         gets(info->c_province);    
673         printf("\n修改前的城市:");
674         puts(info->c_city);
675         printf("\n请输入修改后的城市:");
676         gets(info->c_city);            
677         printf("\n修改前的备注:");
678         puts(info->c_comment);
679         printf("\n请输入修改后的备注:");
680         gets(info->c_comment);    
681         return;
682     }
683     else
684     {
685         printf("查找的东东不纯在呀~~~\n");
686         return;
687     }
688 
689 }
690 
691 /**
692  * @desc 程序入口
693  */
694 int main(){
695 
696     //这是个初始化函数,将存盘文件Contact.ctt读入缓冲区...^^
697     getInfo();
698 
699     //菜单的循环
700     for(;;)
701     {
702         switch(selectMenu())
703         {
704             case 1:insRecord();break;
705             case 2:delRecord();break;
706             case 3:seaRecord();break;
707             case 4:editRecord();break;
708             case 5:printf("正在载入信息...\n");Sleep(800);disRecords();break;
709             case 6:about();break;
710             case 7:saveRecords();exit(0);
711         }
712     }return 0; 
713 }

Its Done~

原文地址:https://www.cnblogs.com/wuniaoheart/p/3101240.html