自从上次通讯录项目被字符串项目整的自闭了之后,用了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. C51单片机_day_01(定时器和中断系统)

                c51单片机 51单片机是控制电路系统的开关,当然芯片就是51芯片,现在随着科技的发展,也是出了很多,功能更多,更全的芯片. 51是用c语言做为程序编程的语言 ——我对基本基础 ...

  2. ionic上拉加载组件 ion-infinite-scroll自动调用多次的问题

    参考文章地址:http://www.cnblogs.com/luleixia/p/6402418.html ionic 一个上拉刷新的组件 ion-infinite-scroll,如果页面未填充满页面 ...

  3. Merging one UE4 project into another.

    Merging can be done by right clicking on folder in the content directory in the editor and selecting ...

  4. 一键部署office的工具——OTool

    OTool可用于office的下载.安装和激活,其激活方式是调用kmspico服务器进行的,官方网站是https://otp.landian.vip/zh-cn/,最新版本5.9.3.6在2019/4 ...

  5. Django之 静态模板渲染

    既可以简单的 django.http.HttpResponse 来把内容显示到网页上,也可以使用渲染模板的方法来显示内容. 说明:代码是基于 Django 1.8,但 Django 1.4 - Dja ...

  6. conda使用技巧

    https://www.cnblogs.com/Sinte-Beuve/p/8597429.html https://www.cnblogs.com/xiaotongtt/p/8909844.html ...

  7. PHP数组和XML相互转换的函数

    //数组转xml function ArrToXml($arr) { if(!is_array($arr) || count($arr) == 0) return ''; $xml = "& ...

  8. 转 一个oracle11g 使用exp导出空表丢失的问题分析及解决办法

    用exp无法导出空表解决方法 最早的一次使用oracle 11g导出数据发现有的表丢失了,感觉莫名其妙的,后来终于找到原因了. 找到问题以后,再看看解决方案.11GR2中有个新特性,当表无数据时,不分 ...

  9. django中form页面刷新后自动提交的解决方案

    如果一个页面包含了form,同时这个form中的提交按钮是type=submit的input的时候,你刷新该页面,就会有弹窗提示是否重新提交表单,这个特性不胜其烦,常见解决方法有两个: 第一种是前端的 ...

  10. MVC Action 返回类型

    https://www.cnblogs.com/xielong/p/5940535.html https://blog.csdn.net/WuLex/article/details/79008515 ...