自从上次通讯录项目被字符串项目整的自闭了之后,用了5天时间重新整理了一下通讯录的思路,并且能够正常的使用,今天按模块把基于链表的通讯录2.0版本记录一下,供后续积累经验。

  首先总结一下 通讯录2.0版的不足之处:

  1. 由于程序基本都写在堆区和栈区,所以当程序结束后,内存里的东西也就没了,如果继续优化的话,考虑连接数据库,或者低级一点,结束前写入.txt文本,开启程序前再从.txt文件写入
  2. 界面粗糙,也算是c语言程序的特性吧,不像java甚至于c++能写的界面友好一点,但是作为我在这个学习阶段的逻辑训练和代码量的积累,还是比较成功的

  那么接下来就分模块讲述一下整个通讯录的思路吧,先列一下思路图

第一个,就说一下上次初次尝试写通讯录时让我很纠结的 字符串输入问题,上一次利用指针和字符数组写入,要么是报错,要么就是最后一次输入内容会把前面所有字符串内容都给覆盖掉,其实上一次也有想到过利用 getchar() 函数去自己写一个getstring()的函数,但由于当时重点放在指针上(最后是因为scanf无法给指向堆区的指针写入内容),就没有太多尝试

1.getstring()函数

 char *GetString()
{
int size = ;
int count = ;
char *str = (char *)malloc(size);
char *pMark = str;
char *newstr = NULL;
char c;
while((c = getchar()) != '\n')
{
*str = c;
str++;
count++;
if(count + == size)
{
*str = '\0';
size += ;
newstr = (char *)malloc(size);
strcpy_s(newstr,size,pMark);
free(pMark);
pMark = newstr;
str = newstr + count;
}
}
*str = '\0'; return pMark;

思路:由于字符数组在程序运行后,长度是定下来的,对用户的输入长度就有很大限制,所以首先在堆区开辟第一个空间,利用Getchar()获取输入缓冲区内内容,向第一个空间内依次输入字符,并计数。利用计数给第一个空间留一个‘\0’的位置,再开辟一个同样大小的空间,将第一个空间内的字符串复制给这个空间内,然后用pMark始终指向后一个开辟的空间,str从‘\0’位置继续赋值,直到识别到‘\n’为止

第二个,在编程过程中发现利用scanf()输入时,在字符缓冲区内总是会有残留的'\n',每一次都得用getchar()去清理缓存区,一是太麻烦,二是经常会忘,干脆就封装一个函数,专门用来获取字符,而且不会受到换行符的麻烦

2.GetKey()

 char GetKey()
{
char c;
char z = '!';
int flag = ;
while((c=getchar()) != '\n' || == flag) //考虑了\n在之前的情况
{
z = c;
flag = ;
}
return z;
}

思路:没有什么复杂的思路,就是把'\n'排除在外,我另外又设置了一个标记,就是因为在后面的模块写的过程当中忘记了自己封装好的函数,直接使用scanf然后后面的函数也成功的把‘\n’获取进去了(好无奈啊,这个找了很长时间的bug),所以干脆就加个标记。

第三个,也是因为自己太懒了,不想每次都添加很多信息,就写了三个随机生成序号,姓名和电话号码的函数,在前期测试的时候使用

3.GetTestMessage()

 int GetId()
{
static int id = ; //使用静态变量
id++;
return id;
}
char *GetName() //随机分配姓名
{
char *pname = (char *)malloc();
int i;
for(i = ;i < ;i++)
{
pname[i] = rand()% + 'a';
}
pname[i] = '\0'; return pname;
}
char *GetTel() //随机分配电话号码
{
char *ptel = (char *)malloc();
int i;
int num = rand()%+;
switch(num)
{
case :
strcpy_s(ptel,,"");
break;
case :
strcpy_s(ptel,,"");
break;
case :
strcpy_s(ptel,,"");
break;
default:
strcpy_s(ptel,,"");
break;
}
for(i = ;i < ;i++)
{
ptel[i] = rand()% + '';
}
ptel[i] = '\0'; return ptel;
}

思路:看了很多面经经常会问到 static的作用,我这里也是最浅显的一个作用声明静态变量,全局范围内可以使用,其他的我也在深入的了解,另外为了号码伪造的更像一点,用了三个号码段吧

第四个:到这才正式进入通讯录主题功能的编写,首先是获取通讯录单个结点,我分为两个部分来写,一方面是测试数据,一方面在后面可以添加

4.GetNode()

List *GetNode()                                              //获取测试数据
{
List *pTemp = (List *)malloc(sizeof(List));
pTemp->id = GetId();
pTemp->name = GetName();
pTemp->tel = GetTel();
pTemp->next = NULL; return pTemp;
} List *GetMyNode() //获取自我添加数据
{
List *pTemp = (List *)malloc(sizeof(List));
pTemp->id = GetId();
printf("请输入姓名: ");
pTemp->name = GetString();
printf("请输入电话: ");
pTemp->tel = GetString();
pTemp->next = NULL; return pTemp;
}

思路:典型的链表添加

第五个:想一想能不能做一个分页功能呢,当数据量大的时候利用ws来翻页,所以我分为三个模块来实现这个分页功能,第一个是获取分页信息(当前页码,总共页码数,总共信息数,一页多少信息数),第二个是遍历链表按每页多少信息数,来截分,第三个是实现利用w s键来翻页,以及能返回主界面等等功能按键

5.Page()

 Page *GetPage(List *pHead,int OnePageInfo)                       //获取页码信息
{ Page *pPage = (Page *)malloc(sizeof(Page));
pPage->CurrentPage = ;
pPage->TotalInfo = ;
pPage->OnePageInfo = OnePageInfo;
while(pHead)
{
pPage->TotalInfo++;
pHead = pHead->next;
}
pPage->TotalPage = pPage->TotalInfo%pPage->OnePageInfo == ? pPage->TotalInfo / pPage->OnePageInfo : pPage->TotalInfo / pPage->OnePageInfo + ; //三目运算符 相当于if-else的简写 return pPage;
}
void ShowInfo(List *pHead,Page *pPage) //对结点进行截分
{
int PageBegin = (pPage->CurrentPage - ) * pPage->OnePageInfo + ;
int PageEnd = (pPage->CurrentPage) * (pPage->OnePageInfo);
int InfoNum = ;
while(pHead)
{
InfoNum++;
if(InfoNum >= PageBegin && InfoNum <= PageEnd)
printf("%d\t%s\t%s\n",pHead->id,pHead->name,pHead->tel);
pHead = pHead->next;
}
return; }
void TurnPage(List *pHead,Page *pPage) //利用按键进行翻页以及其他功能
{
char c = 's';
while()
{
switch(c)
{
case 's':
if(pPage->CurrentPage < pPage->TotalPage)
{
pPage->CurrentPage++;
ShowInfo(pHead,pPage);
ShowMenu(pPage);
}
else
{
printf("已经是最后一页了!\n");
ShowMenu(pPage);
}
break;
case 'w':
if(pPage->CurrentPage > )
{
pPage->CurrentPage--;
ShowInfo(pHead,pPage);
ShowMenu(pPage);
}
else
{
printf("已经是第一页了!\n");
ShowMenu(pPage);
}
break;
case 'e':
return;
break;
case 'c':
return;
break;
case 'd':
return;
break;
case 'y':
return;
break;
case 'u':
return;
break;
default:
printf("请输入规定的按键!\n");
break;
}
c = GetKey();
g_Key = c;
// getchar(); //清空缓冲区内的\n
}
}

思路:难点在于第一个模块中确定哪些信息是能直接获取的,哪些是间接获得的。也是心血来潮用了一个三目运算符,感觉和if-else没啥区别,可能是我太菜了,哈哈哈,第二个模块中结点截获的开始位置和终止位置的确定也是一个难点,利用已知信息来确定。第三个难点其实就是我找了很长时间bug的那个‘\n’,有兴趣的话可以把 c = GetKey(); 直接写成c = getchar()体验一下。

第六个:添加功能过于简单就不直接把模块列出来了,直接在源码中展示,画个重点,我觉得最难的部分 查询功能就要来了

6.Query()

 void Query(List *pHead)
{
List *pDel;
List *newpHead = NULL;
List *newpEnd = NULL;
char Choose;
char *KeyWord = NULL;
List *pNode = NULL;
List *pMark = pHead;
while()
{
while()
{
printf("请输入查询关键字: ");
KeyWord = GetString();
printf("a.确认 其他键.重新输入\n");
Choose = GetKey();
//switch(Choose)
//{
//case 'a':
// printf("%s\n",KeyWord);
// return;
// break;
//case 'c':
// printf("请重新输入!\n");
// free(KeyWord); //堆区内存不需要的话就要及时释放
// break;
//}
if(Choose == 'a') //第二种方法
{
break;
}
else
{
free(KeyWord); //堆区内存不需要的话就要及时释放
KeyWord = NULL;
}
}
pHead = pMark;
while(pHead)
{
if(!strncmp(pHead->name,KeyWord,strlen(KeyWord)) || !strncmp(pHead->tel,KeyWord,strlen(KeyWord))) //输入的长度可以用字符串长度
{
pNode = (List *)malloc(sizeof(List)); //创建一个新的链表 用现成的接口和函数进行调用
pNode->id = pHead->id;
pNode->name = pHead->name;
pNode->tel = pHead->tel;
pNode->next = NULL;
AddNode(&newpHead,&newpEnd,pNode);
}
pHead = pHead->next;
}
Browse(newpHead);
while(newpHead) //清除之前所有的结点
{
pDel = newpHead;
newpHead = newpHead->next;
free(pDel);
pDel = NULL;
}
if('e' == g_Key || 'd' == g_Key || 'u' == g_Key)
{
return;
}
}
}

思路:我想做一个前缀模糊查询,难点在于1.多个功能按键的嵌套 2.如何加入按键 3.查询后的信息如何在遍历呢,解决如下1.我也做了尝试发现switch的话一个case里需要加很多东西,就用if-else代替了,意外发现效果还不错,2.利用已有的获取菜单里的模块 加入按键,并且设一个全局变量,能在不同模块下都有不一样的菜单 3.这个我也是思考了很久,决定重新创建一个链表,专门存查找的信息,并且为了养成好滴习惯,堆区不用的空间,立马及时的清理干净。

接下来的修改和删除功能就很简单了,总结起来就是 不要造成内存浪费,记得一级和二级指针的区别,其他的和查询就很像啦

接下来直接上源码了

 #include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<string.h>
typedef struct NODE
{
int id;
char *name;
char *tel;
struct NODE *next;
}List;
typedef struct PAGE
{
int CurrentPage; //当前页数
int TotalPage; //总页数
int TotalInfo; //总条数
int OnePageInfo; //每页多少条
}Page;
int GetId();
char *GetName();
char *GetTel();
List *GetNode();
List *GetMyNode();
void AddNode(List **ppHead,List **ppEnd,List *pNode); //添加通讯录信息
void InitInfo(List **ppHead,List **ppEnd,int n); //初始化数据
Page *GetPage(List *pHead,int OnePageInfo); //获得页码信息
void ShowInfo(List *pHead,Page *pPage); //展示当前页信息
void TurnPage(List *pHead,Page *pPage); //翻页功能
char GetKey(); //获得按键,将缓冲区内的\n给排除掉
void Browse(List *pHead); //浏览通讯录信息
void ShowMenu(Page *pPage); //页码信息显示
char *GetString(); //获取字符串(scanf()函数无法给指针赋值)
void AddMessage(List **ppHead,List **ppEnd); //添加通讯录信息功能
void Query(List *pHead); //查询功能
void DeleteInfo(List **ppHead,List **ppEnd); //删除通讯录信息功能
void DeleteNode(List **ppHead,List **ppEnd,int id); //删除结点模块
void UpDataInfo(List *pHead); //修改通讯录信息功能
int g_MenuType; //全局变量以g_开头
char g_Key; //判断是否为b
int main()
{
char c;
List *pHead = NULL;
List *pEnd = NULL;
InitInfo(&pHead,&pEnd,);
while()
{
printf("1.查看通讯录\n");
printf("2.添加信息\n");
printf("3.查询信息\n");
printf("4.删除信息\n");
printf("5.修改信息\n");
printf("q.退出\n");
c = GetKey();
switch(c)
{
case '':
g_MenuType = ;
Browse(pHead);
break;
case '':
AddMessage(&pHead,&pEnd);
break;
case '':
g_MenuType = ;
Query(pHead);
break;
case '':
g_MenuType = ;
DeleteInfo(&pHead,&pEnd);
break;
case '':
g_MenuType = ;
UpDataInfo(pHead);
break;
case 'q':
return ;
break;
}
}
return ;
}
int GetId()
{
static int id = ;
id++;
return id;
}
char *GetName() //随机分配姓名
{
char *pname = (char *)malloc();
int i;
for(i = ;i < ;i++)
{
pname[i] = rand()% + 'a';
}
pname[i] = '\0'; return pname;
}
char *GetTel() //随机分配电话号码
{
char *ptel = (char *)malloc();
int i;
int num = rand()%+;
switch(num)
{
case :
strcpy_s(ptel,,"");
break;
case :
strcpy_s(ptel,,"");
break;
case :
strcpy_s(ptel,,"");
break;
default:
strcpy_s(ptel,,"");
break;
}
for(i = ;i < ;i++)
{
ptel[i] = rand()% + '';
}
ptel[i] = '\0'; return ptel;
}
List *GetNode()
{
List *pTemp = (List *)malloc(sizeof(List));
pTemp->id = GetId();
pTemp->name = GetName();
pTemp->tel = GetTel();
pTemp->next = NULL; return pTemp;
}
List *GetMyNode()
{
List *pTemp = (List *)malloc(sizeof(List));
pTemp->id = GetId();
printf("请输入姓名: ");
pTemp->name = GetString();
printf("请输入电话: ");
pTemp->tel = GetString();
pTemp->next = NULL; return pTemp;
}
void AddNode(List **ppHead,List **ppEnd,List *pNode)
{
if(*ppHead == NULL)
{
*ppHead = pNode;
}
else
{
(*ppEnd)->next = pNode;
}
*ppEnd = pNode; return;
}
void InitInfo(List **ppHead,List **ppEnd,int n)
{
int i;
srand((unsigned int)time(NULL));
for(i = ;i < n;i++)
{
AddNode(ppHead,ppEnd,GetNode());
} }
Page *GetPage(List *pHead,int OnePageInfo)
{ Page *pPage = (Page *)malloc(sizeof(Page));
pPage->CurrentPage = ;
pPage->TotalInfo = ;
pPage->OnePageInfo = OnePageInfo;
while(pHead)
{
pPage->TotalInfo++;
pHead = pHead->next;
}
pPage->TotalPage = pPage->TotalInfo%pPage->OnePageInfo == ? pPage->TotalInfo / pPage->OnePageInfo : pPage->TotalInfo / pPage->OnePageInfo + ; //三目运算符 相当于if-else的简写 return pPage;
}
void ShowInfo(List *pHead,Page *pPage)
{
int PageBegin = (pPage->CurrentPage - ) * pPage->OnePageInfo + ;
int PageEnd = (pPage->CurrentPage) * (pPage->OnePageInfo);
int InfoNum = ;
while(pHead)
{
InfoNum++;
if(InfoNum >= PageBegin && InfoNum <= PageEnd)
printf("%d\t%s\t%s\n",pHead->id,pHead->name,pHead->tel);
pHead = pHead->next;
}
return; }
void TurnPage(List *pHead,Page *pPage)
{
char c = 's';
while()
{
switch(c)
{
case 's':
if(pPage->CurrentPage < pPage->TotalPage)
{
pPage->CurrentPage++;
ShowInfo(pHead,pPage);
ShowMenu(pPage);
}
else
{
printf("已经是最后一页了!\n");
ShowMenu(pPage);
}
break;
case 'w':
if(pPage->CurrentPage > )
{
pPage->CurrentPage--;
ShowInfo(pHead,pPage);
ShowMenu(pPage);
}
else
{
printf("已经是第一页了!\n");
ShowMenu(pPage);
}
break;
case 'e':
return;
break;
case 'c':
return;
break;
case 'd':
return;
break;
case 'y':
return;
break;
case 'u':
return;
break;
default:
printf("请输入规定的按键!\n");
break;
}
c = GetKey();
g_Key = c;
// getchar(); //清空缓冲区内的\n
}
}
char GetKey()
{
char c;
char z = '!';
int flag = ;
while((c=getchar()) != '\n' || == flag) //考虑了\n在之前的情况
{
z = c;
flag = ;
}
return z;
}
void Browse(List *pHead)
{
Page *pPage = GetPage(pHead,);
TurnPage(pHead,pPage);
}
void ShowMenu(Page *pPage)
{
switch(g_MenuType)
{
case :
printf("当前%d页 共%d页 共%d条 w上一页\ts下一页\te返回\n",pPage->CurrentPage,pPage->TotalPage,pPage->TotalInfo);
break;
case :
printf("当前%d页 共%d页 共%d条 w上一页\ts下一页\tc重新查询\te返回\n",pPage->CurrentPage,pPage->TotalPage,pPage->TotalInfo);
break;
case :
printf("当前%d页 共%d页 共%d条 w上一页\ts下一页\td删除信息\te返回\n",pPage->CurrentPage,pPage->TotalPage,pPage->TotalInfo);
break;
case :
printf("当前%d页 共%d页 共%d条 w上一页\ts下一页\tu修改信息\te返回\n",pPage->CurrentPage,pPage->TotalPage,pPage->TotalInfo);
break;
} }
char *GetString()
{
int size = ;
int count = ;
char *str = (char *)malloc(size);
char *pMark = str;
char *newstr = NULL;
char c;
while((c = getchar()) != '\n')
{
*str = c;
str++;
count++;
if(count + == size)
{
*str = '\0';
size += ;
newstr = (char *)malloc(size);
strcpy_s(newstr,size,pMark);
free(pMark);
pMark = newstr;
str = newstr + count;
}
}
*str = '\0'; return pMark;
}
void AddMessage(List **ppHead,List **ppEnd)
{
List *pNode = GetMyNode();
AddNode(ppHead,ppEnd,pNode);
}
void Query(List *pHead)
{
List *pDel;
List *newpHead = NULL;
List *newpEnd = NULL;
char Choose;
char *KeyWord = NULL;
List *pNode = NULL;
List *pMark = pHead;
while()
{
while()
{
printf("请输入查询关键字: ");
KeyWord = GetString();
printf("a.确认 其他键.重新输入\n");
Choose = GetKey();
//switch(Choose)
//{
//case 'a':
// printf("%s\n",KeyWord);
// return;
// break;
//case 'c':
// printf("请重新输入!\n");
// free(KeyWord); //堆区内存不需要的话就要及时释放
// break;
//} //第一种方法 用switch去选择按键
if(Choose == 'a') //第二种方法
{
break;
}
else
{
free(KeyWord); //堆区内存不需要的话就要及时释放
KeyWord = NULL;
}
}
pHead = pMark;
while(pHead)
{
if(!strncmp(pHead->name,KeyWord,strlen(KeyWord)) || !strncmp(pHead->tel,KeyWord,strlen(KeyWord))) //输入的长度可以用字符串长度
{
pNode = (List *)malloc(sizeof(List)); //创建一个新的链表 用现成的接口和函数进行调用
pNode->id = pHead->id;
pNode->name = pHead->name;
pNode->tel = pHead->tel;
pNode->next = NULL;
AddNode(&newpHead,&newpEnd,pNode);
}
pHead = pHead->next;
}
Browse(newpHead);
while(newpHead) //清除之前所有的结点
{
pDel = newpHead;
newpHead = newpHead->next;
free(pDel);
pDel = NULL;
}
if('e' == g_Key || 'd' == g_Key || 'u' == g_Key)
{
return;
}
}
}
void DeleteNode(List **ppHead,List **ppEnd,int id)
{
List *pDel = NULL;
List *pMov = *ppHead;
if((*ppHead)->id == id)
{
pDel = *ppHead;
*ppHead = (*ppHead)->next;
free(pDel->name);
free(pDel->tel);
free(pDel);
pDel = NULL;
printf("删除成功!\n");
return;
}
if(pMov->next)
{
if(pMov->next->id == id)
{
if(pMov->next == *ppEnd)
{
pDel = *ppEnd;
*ppEnd = pMov;
(*ppEnd)->next = NULL;
}
else
{
pDel = pMov->next;
pMov->next = pMov->next->next;
}
free(pDel->name);
free(pDel->tel);
free(pDel);
pDel = NULL;
printf("删除成功!\n");
return;
}
pMov = pMov->next;
}
}
void DeleteInfo(List **ppHead,List **ppEnd)
{
int i;
while()
{
Query(*ppHead);
if('e'==g_Key)
{
break;
}
printf("请输入要删除的编号: ");
scanf("%d",&i);
DeleteNode(ppHead,ppEnd,i);
printf("y.继续删除 其他键返回\n");
if(GetKey() != 'y')
{
break;
}
}
}
void UpDataInfo(List *pHead)
{
char *str = NULL;
int id;
while()
{
Query(pHead);
if('e'==g_Key)
{
break;
}
printf("请输入修改的编号: ");
scanf("%d",&id); //用getchar()清除缓冲区内信息
getchar();
while(pHead)
{
if(pHead->id == id)
{
printf("请修改姓名: ");
str = GetString();
if(strlen(str) > )
{
free(pHead->name);
pHead->name = str;
}
printf("请修改电话号: ");
str = GetString();
if(strlen(str) > )
{
free(pHead->tel);
pHead->tel = str;
}
return;
}
pHead = pHead->next;
}
}
}

2019-04-28 23:37:16  编程小菜鸡自我反省,大佬勿喷,谢谢!!!

c语言小项目---通讯录2.0的更多相关文章

  1. [IT学习]Python 小项目 通讯录 思路

    建立一个通讯录查询软件,暂时只支持按姓名检索.出发点:无需登录企业门户,即可检索.要注意保护员工手机号,除非他自己同意显示. 欢迎您访问www.cnblogs.com/viphhs.转载请联系作者授权 ...

  2. C语言小项目-基于TCP协议和SOCKET编程的网络通信系统

    1.1 功能结构图   网络通信系统一共由4个模块组成,分别是点对点客户端.点对点服务端.服务器中转服务端.服务器中转客户端.这4个模块是成对使用的,点对点客户端和点对点服务端一起使用,服务器中转服务 ...

  3. c语言小项目-使用mysql数据库的图书管理系统

    VS2013通过MySQL方式连接到MySQL MySQL官网上C++的API有两个.一个是很成熟的mysql++,另一个是MySQL Connector/C++,近两年才出的,模仿JDBC做的,封装 ...

  4. C语言小项目-火车票订票系统

    list.h #ifndef __LIST_H__ #define __LIST_H__ #include "stdafx.h" #include <stdio.h> ...

  5. 小项目特供 贪吃蛇游戏(基于C语言)

    C语言写贪吃蛇本来是打算去年暑假写的,结果因为ACM集训给耽搁了,因此借寒假的两天功夫写了这个贪吃蛇小项目,顺带把C语言重温了一次. 是发表博客的前一天开始写的,一共写了三个版本,第一天写了第一版,第 ...

  6. 微信小程序初体验,入门练手项目--通讯录,后台是阿里云服务器(一)

    内容: 一.前言 二.相关概念 三.开始工作 四.启动项目起来 五.项目结构 六.设计理念 七.路由 八.部署线上后端服务 同步交流学习社区: https://www.mwcxs.top/page/4 ...

  7. C语言实现简单计算器小项目

    昨天刚安装上devc++,半夜想着练练C语言吧 于是就看到实验楼有一个计算器的项目 之前做过一次,这次写的主要是思路 首先我们先从原理思考jia,实现简单的计算器就要具备加减乘除这些,看普通的计算器也 ...

  8. 【源码项目+解析】C语言/C++开发,打造一个小项目扫雷小游戏!

    一直说写个几百行的小项目,于是我写了一个控制台的扫雷,没有想到精简完了代码才200行左右,不过考虑到这是我精简过后的,浓缩才是精华嘛,我就发出来大家一起学习啦,看到程序跑起来能玩,感觉还是蛮有成就感的 ...

  9. Java小项目--坦克大战(version1.0)

    Java小项目--坦克大战<TankWar1.0> 这个小项目主要是练习j2se的基础内容和面向对象的思想.项目实现了基本的简单功能,我方一辆坦克,用上下左右键控制移动方向,按F键为发射炮 ...

随机推荐

  1. c# 坑人的发邮件组件

    System.Net.Mail 在服务器25端口被封禁的情况下,无法使用其它诸如SSL 465端口发送.用过时的System.Web.Mail却可以.是微软更新速度太快呢,还是标准不一致呢. Syst ...

  2. Linux----------mysql进阶

    目录 一.破解密码以及无密码登录 1.1 破解密码 1.2 无密码登录 1.3 定义不同的客户端 1.4 家目录下 二.视图 三.函数 3.1 系统函数 3.2 自定义函数 3.3 自定义函数中定义局 ...

  3. remove-weknow-ac from mac chrome

    refer:https://macreports.com/how-to-remove-weknow-ac-malware-macos/ 1-Remove the weknow.ac profile. ...

  4. 30天学会绘画 (Mark Kistler 著)

    第一课 球形 (已看) 第二课 重叠的球 (已看) 第三课 更多排列的球 (已看) 第四课 立方体 (已看) 第五课 空心立方体 (已看) 第六课 堆放的桌子 (已看) 第七课 堆放更多的立方体 (已 ...

  5. mysql用户管理及授权

    以mariadb5.5版本为例 新建用户 登录mariadb # mysql -uroot -p Enter password: Welcome to the MariaDB monitor. Com ...

  6. C# .NET XML 序列化为对象,反序列化

    如果遇到:   根级别上的数据无效. 行 1,位置 1   .:即无法反序列化(反序列失败),得到对象为null ,把 xml 文本 Trim一下. xml=xml.Trim(); 序列化完毕你可以看 ...

  7. SQL数据库日志清理

    USE [master] GO ALTER DATABASE HCPM_01_181230 SET RECOVERY SIMPLE WITH NO_WAIT GO ALTER DATABASE HCP ...

  8. python基础知识14---迭代器、生成器、面向过程编程

    阅读目录 一 迭代器 二 生成器 三 面向过程编程 一 迭代器 1 迭代的概念 #迭代器即迭代的工具,那什么是迭代呢? #迭代是一个重复的过程,每次重复即一次迭代,并且每次迭代的结果都是下一次迭代的初 ...

  9. activiti中的查询sql

    <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "- ...

  10. MSDE2008安装备忘

    MSDE2008安装备忘(适用于WIN7 8 10) 1.系统中必须要VC8.0,即VC2005运行库.2.系统中必须要有.net framework2.0.3.5.4.6运行库.3.windows防 ...