zoukankan      html  css  js  c++  java
  • 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~

  • 相关阅读:
    shell--练习--简易计算器
    shell--运算符
    shell--传递参数
    PHP数学函数的练习
    PDO对数据库的操作
    PHP实现手机短信的验证
    ThinkPHP框架 _ 学习16
    ThinkPHP框架 _ 学习15
    ThinkPHP框架 _ 学习14
    ThinkPHP框架 _ 学习13
  • 原文地址:https://www.cnblogs.com/wuniaoheart/p/3101240.html
Copyright © 2011-2022 走看看