编程杂谈

单链表单链表是一种链式存取的数据结构,链表中的数据是以结点来表示的.每个结点的构成:元素(数据元素的映象)+指针(指示后继元素存储位置)元素就是存储数据的存储单元指针就是连接每个结点的地址数据。以“结点的序列”表示的线性表称作线性链表(单链表),单链表是链式存取的结构。单链表插入数据在链表头部插入以下代码有BUG,不能用于实际场景,只是例子这样写,没有释放空间#include<stdio.h>#include<stdlib.h>//定义一个结构体structInfo{charname[255];structInfo*next;//指向下一个Info结构体};//申请链表节点structInfo*applyNode(){structInfo*node;node=(structInfo*)malloc(sizeof(structInfo));if(node==NULL)exit(0);//空间申请失败returnnode;}//输出单链表的值voidprintInfo(structInfo*head){//传入的链表头部,通过头部链表找后面的链表structInfo*info;info=head->next;while(info!=NULL){printf("%s",info->name);info=info->next;};printf("\n");}intmain(void){//申请一个空间创建链表的头部structInfo*head;head=applyNode();head->next=NULL;//初始化头部链表charname[255];while(1){//申请新的节点structInfo*node=applyNode();//用户输入printf("输入姓名(n退出):");scanf("%s",node->name);if(*(node->name)=='n')exit(0);//n退出//改变指针指向地址node->next=head->next;head->next=node;//输出单链表的值printInfo(head);}return0;}在链表尾部插入以下代码有BUG,不能用于实际场景,只是例子这样写,没有释放空间#include<stdio.h>#include<stdlib.h>//定义一个结构体structInfo{charname[255];structInfo*next;//指向下一个Info结构体};//申请链表节点structInfo*applyNode(){structInfo*node;node=(structInfo*)malloc(sizeof(structInfo));if(node==NULL)exit(0);//空间申请失败returnnode;}//输出单链表的值voidprintInfo(structInfo*head){//传入的链表头部,通过头部链表找后面的链表structInfo*info;info=head->next;while(info!=NULL){printf("%s",info->name);info=info->next;};printf("\n");}intmain(void){//申请一个空间创建链表的头部保存链表头部地址structInfo*head;head=applyNode();head->next=NULL;//初始化头部链表structInfo*tail=head;//一直表示链表尾部,第一次就是链表头部charname[255];while(1){structInfo*node=applyNode();//用户输入printf("输入姓名(n退出):");scanf("%s",node->name);if(*(node->name)=='n')exit(0);//n退出//改变指针指向地址tail->next=node;tail=node;tail->next=NULL;//输出单链表的值printInfo(head);}return0;}综合应用-在单链表中间插入链(完整代码)新输入的值,自动插入到适合大小位置相应函数//数组结构体structIntList{intnum;structIntList*next;};structIntList*applyNode();//新节点申请空间voidaddNum(structIntList*head,structIntList*node);//插入值voidprintIntList(structIntList*head);//输出单链表的内容voidclearNode(structIntList*head);//释放空间完整代码代码的难点:在于需要兼顾第一次、在头部、中间、尾部这些不同位置的插入。#include<stdio.h>#include<stdlib.h>//数组结构体structIntList{intnum;structIntList*next;};structIntList*applyNode();//新节点申请空间voidaddNum(structIntList*head,structIntList*node);//插入值voidprintIntList(structIntList*head);//输出单链表的内容voidclearNode(structIntList*head);//释放空间//申请空间structIntList*applyNode(){structIntList*node;node=(structIntList*)malloc(sizeof(structIntList));node->next=NULL;returnnode;}//插入值voidaddNum(structIntList*head,structIntList*node){structIntList*lastNode;//插入节点的前一个structIntList*now;//当前节点structIntList*nextNode;//插入节点的前一个now=head->next;//第一次插入,直接加在头部后面if(now==NULL){head->next=node;return;}//处理最小值,直接再头部插入if(node->num<=now->num){node->next=now;head->next=node;return;}//插入在中间的链while(now!=NULL){lastNode=now;nextNode=now->next;//遍历到最后,认为是最大值,插入在尾部if(nextNode==NULL){now->next=node;return;}//比前一个大,比后一个小,然后中间插入if(lastNode->num<=node->num&&node->num<=nextNode->num){lastNode->next=node;node->next=nextNode;return;//插入完成退出函数}now=nextNode;}};//输出单链表值voidprintIntList(structIntList*head){structIntList*node;node=head->next;while(node!=NULL){printf("%d",node->num);node=node->next;}printf("\n");};//清理空间voidclearNode(structIntList*head){structIntList*node;//循环清理所有空间while(head!=NULL){node=head->next;//记录下一个node地址free(head);//清理headhead=node;//node变成新的head}printf("空间清理完成!!!");};intmain(){structIntList*head=applyNode();//申请链表头部intnum=0;while(1){printf("输入一个数字(-1退出并清理空间):");scanf("%d",&num);if(num==-1){//清理空间并退出clearNode(head);exit(0);}//申请节点空间structIntList*node=applyNode();node->num=num;//把值插入链表addNum(head,node);//输出链表的内容printIntList(head);}

2021-1-6 649 0
编程杂谈

结构体变量之间的传递直接把结构体赋值给另一个结构体变量#include<stdio.h>structDate{intyear;intmonth;intday;}date={.year=2021,.month=1,.day=5};intmain(void){structDated;d=date;printf("d的值:%d-%d-%d",d.year,d.month,d.day);return0;}结构体作为函数参数传递把结构体变量作为函数的参数传递给函数#include<stdio.h>//定义结构体structDate{intyear;intmonth;intday;};//定义函数structDategetDate(structDatedate){//给结构体赋值date.year=2021;date.month=1;date.day=5;//返回结构体returndate;}intmain(void){structDatedate,d;d=getDate(date);printf("日期为:%d-%d-%d",d.year,d.month,d.day);return0;}结构体指针作为函数参数传递函数直接传入结构体会降低性能,传入结构体指针能提高程序效率#include<stdio.h>structDate{intyear;intmonth;intday;};//传入指针不需要返回值voidgetDate(structDate*date){//给结构体赋值date->year=2021;date->month=1;date->day=5;}intmain(void){structDatedate;getDate(&date);//传入地址printf("日期为:%d-%d-%d",date.year,date.month,date.day);return0;}动态申请结构体空间动态申请,存储在堆空间,用完记得释放#include<stdio.h>#include<stdlib.h>structDate{intyear;intmonth;intday;};//传入指针不需要返回值voidgetDate(structDate*date){//给结构体赋值date->year=2021;date->month=1;date->day=5;}intmain(void){structDate*date;//申请空间date=(structDate*)malloc(sizeof(structDate));getDate(date);//传入地址printf("日期为:%d-%d-%d",date->year,date->month,date->day);//释放空间free(date);return0;}

编程杂谈

结构体定义方式关键字:structstruct结构体名称{基本类型变量名;基本类型变量名;...};//注意这有分号structBoy{charname[20];chargender;floatage;};structBoy{charname[20];chargender;floatage;}boy;//这样定义不用初始化boy为全局变量structBoy{charname[20];chargender;floatage;}boy={"大数据男孩",//可以不指定但顺序要对.gender='A',.age=18.5,};//初始化并设置默认值初始化结构体//基本初始化struct结构体名称变量名;structBoyboy;//初始化全部值值的类型需要对应struct结构体名称变量名={内容,""}structBoyboy={"大数据男孩","A",18.2}//初始化部分值struct结构体名称变量名={.定义结构=值,...}structBoyboy={.name="大数据男孩",.gender="A",}结构体使用结构体赋值结构体变量名.值=变量;boy.name="大数据男孩";获取结构体的值变量=结构体变量名.值floatage=boy.age;结构体的内存占用原因:C语言的内存对齐结构体使用#include<stdio.h>//定义结构体structBoy{charname[20];chargender;floatage;};//注意这里有分号intmain(){structBoyboy;//初始化结构体printf("输入姓名:");scanf("%s",boy.name);//数组不用取址符printf("输入性别:");scanf("%s",&boy.gender);printf("输入年龄:");scanf("%f",&boy.age);printf("--------信息录入完毕---------\n\n");printf("基本信息:\n");printf("姓名:%s\n",boy.name);printf("性别:%s\n",&boy.gender);printf("年龄:%.2f\n",boy.age);return0;}结构体嵌套//日期结构体structDate{intyear;intmonth;intday;};//男孩结构体structBoy{charname[20];chargender;structDatedate;//嵌套的日期结构体}boy={.name="大数据男孩",.gender='A',.date={2020,12,15},};访问嵌套结构体#include<stdio.h>//日期结构体structDate{intyear;intmonth;intday;};//男孩结构体structBoy{charname[20];chargender;structDatedate;//嵌套的日期结构体}boy={.name="大数据男孩",.gender='A',.date={2020,12,15},};intmain(){printf("姓名:%s\n",boy.name);printf("性别:%c\n",boy.gender);//嵌套的结构体一层一层的访问printf("日期:%d-%d-%d",boy.date.year,boy.date.month,boy.date.day);return0;}结构体数组structDate{intyear;intmonth;intday;}date[2]={{2020,12,15},{2020,12,16},};访问结构体数组#include<stdio.h>structDate{intyear;intmonth;intday;}date[2]={{2020,12,15},{2020,12,16},};intmain(){//结构体数组//structDatedate[2]={//{2020,12,15},//{2020,12,16},//};//访问结构体数组的内容printf("date[0]:%d-%d-%d\n",date[0].year,date[0].month,date[0].day);printf("date[1]:%d-%d-%d\n",date[1].year,date[1].month,date[1].day);return0;}结构体指针结构体指针本质是指针,作用是指向一个结构体structDatedate={2020,12,15};//定义一个结构体structDate*pt;//定义结构体指针pt=&date;//指针指向结构体通过结构体指针访问结构体#include<stdio.h>structDate{intyear;intmonth;intday;};intmain(){//先定义该结构体structDatedate={2020,12,15};//定义该结构体指针structDate*pt;//结构体指针指向结构体pt=&date;//获取结构体值printf("year:%d",date.year);//结构体直接访问printf("month:%d",(*pt).month);//通过结构体指针访问,括号必须的(优先级问题)printf("day:%d\n",pt->day);//结构体指针箭头访问return0;}

2020-12-27 784 0
编程杂谈

更灵活的内存管理方式在C语言中不存在其他高级语言的垃圾回收机制,在平常方式直接的声明变量,C语言不知道什么时候回收它,所以会一直占用内存空间.而更灵活的管理就是我们能在不使用该变量时就主动释放它。申请的空间不在使用,一定要释放(free(),虽然不是一定释放,但这是一个好习惯使用的库需要引入#include<stdlib.h>void*malloc(size_tsize);申请动态内存空间voidfree(void*ptr);释放动态内存空间void*calloc(size_tnmemb,size_tsize);申请并初始化内存空间为0void*realloc(void*ptr,size_tsize);重新分配内存空间申请空间&释放空间void*malloc(size_tsize);申请成功:返回一个指向申请的内存空间的指针,返回值是void所以可以转化成其他类型申请失败:返回NULL如果size参数设置为0,返回值也可能是NULL,但这并不意味着函数调用失败。voidfree(void*ptr);只能释放由malloc、calloc、realloc函数申请的空间,释放后该地址变为非法地址。参数指向将要释放的内存空间的地址没有返回值#include<stdio.h>#include<stdlib.h>//引入intmain(){//申明变量int*ptr,num=520;//申请内存空间ptr=(int*)malloc(sizeof(int));if(ptr==NULL){exit(1);}//内存申请失败//内存空间存入变量ptr=&num;//输出值printf("prt->%d",*ptr);//释放内存空间free(ptr);return0;}内存泄漏内存泄漏是程序一直占用内存,不释放,造成内存达到很高的使用量,严重造成计算机卡死,所以在不使用该空间时尽量释放掉。有两种情况会导致:隐式内存泄漏(即用完内存块没有及时使用free函数释放)丢失内存块地址申请并初始化&重新分配申请并初始化void*calloc(size_tnmemb,size_tsize);nmemb:指定分配的内存块个数size:指定每个内存块的大小,以字节为单位。#include<stdio.h>#include<stdlib.h>intmain(){//初始化变量int*ptr=NULL;//申请并初始化变量ptr=(int*)calloc(10,sizeof(int));if(ptr==NULL){exit(1);}//查看内容for(inti=0;i<10;++i){printf("%d",ptr[i]);};printf("\n");return0;}重新分配内存空间只能重新分配malloc()函数申请的空间void*realloc(void*ptr,size_tsize);重新分配内存空间参数*ptr:指向由先前调用malloc、calloc或realloc函数返回的内存空间如果传入NULL,相当于调用malloc(size)函数参数size:指定新的内存块空间大小,以字节为单位该函数将移动内存空间的数据并返回新的指针如果新分配的内存空间比原来的大,则旧内存块的数据不会发生改变;如果新的内存空间大小小于旧的内存空间,可能会导致数据丢失,慎用!#include<stdio.h>#include<stdlib.h>intmain(){//初始化变量int*ptr=NULL;//申请并初始化变量ptr=(int*)malloc(10*sizeof(int));if(ptr==NULL){exit(1);}//重新分配内存空间ptr=(int*)realloc(ptr,20*sizeof(int));printf("%llu",sizeof(ptr));ptr[12]=66666666;//赋值//查看内容for(inti=0;i<20;++i){printf("%d",ptr[i]);}return0;}

编程杂谈

指针函数格式:返回类型*函数名(参数列表);不要返回局部变量的指针举个例子#include<stdio.h>char*get_Word(chars);char*get_Word(chars){charstr[]="Apple";//函数内的局部变量switch(s){case'A':returnstr;//无法返回这个strcase'B':return"Bad";case'C':return"Cat";default:return"None";}}intmain(){chari;printf("请输入一个字母:");scanf("%s",&i);printf("%s\n",get_Word(i));return0;}函数指针定义格式:返回值(*名称)(参数类型);#include<stdio.h>intsquare(intnum);intsquare(intnum){returnnum*num;}intmain(){intnum;int(*fp)(int);//定义函数指针printf("输入一个数字:");scanf("%d",&num);fp=square;printf("%d*%d=%d\n",num,num,(*fp)(num));printf("%d*%d=%d\n",num,num,*fp(num));return0;}头脑风暴涉及知识&实现功能涉及知识把函数指针作为函数的返回值。实现功能用户输入一个式子(1+5),自动判断符号,进行相应的运算。代码说明声明函数intadd(int,int);//加法函数intsub(int,int);//减法函数int(*select(char))(int,int);//符号选择,返回相应的计算函数intcalc(int(*)(int,int),int,int);//计算函数,传入一个函数指针,以及两个数字函数方法//加法函数intadd(intnum1,intnum2){returnnum1+num2;}//减法函数intsub(intnum1,intnum2){returnnum1-num2;}//符号选择int(*select(charop))(int,int){switch(op){case'+':returnadd;case'-':returnsub;}}//计算函数intcalc(int(*fp)(int,int),intnum1,intnum2){return(*fp)(num1,num2);}使用#include<stdio.h>intmain(){intnum1=0,num2=0;charop;int(*fp)(int,int);//接收函数指针printf("输入一个式子(1+1):");scanf("%d%c%d",&num1,&op,&num2);fp=select(op);//符号选择,返回函数指针printf("%d%c%d=%d",num1,op,num2,calc(fp,num1,num2));return0;}

编程杂谈

爬虫目标爬虫字段:职位名称、职位URL、职位要求(逗号分隔csv文件)完整代码:https://github.com/bigdataboy2020/job51_spider爬虫结构分层结构模块化结构,减少耦合使用模块:gevent、lxml、typing、requests项目说明操作类(job51.py)主要包含发送请求的方法defget_data():请求获取一页所有的职位名称和职位的URLdefget_job_explain():获取一个职业的要求classJob51(object):#总页数。第一次获取会设置真实页数all_page=9999#正在获取的页数page_num=1#Job_name和url列表job_url_data:List[Tuple[str,str]]=list()#职位详情页列表[name,url,说明]job_explain:Tuple[str,str,List[str]]=Nonesession=requests.session()defget_data(self,page_num:str,city:List[str],search:str)->bool:"""#获取该关键词所有的职位名称与链接:parampage_num:当前页数:paramcity:城市列表:paramsearch:搜索词:return:"""returnTruedefget_job_explain(self,job_name:str,url:str)->bool:"""#获取一个职业的要求:paramjob_name:职位名称:paramurl:职位的详情页:return:"""returnTrue中间处理函数(handle.py)主要包含对请求的数据进行处理的函数及相应错误提示defget_data():获取所有页数的职位名称及职位URLdefget_job_explain():获取单个职位的详细信息msg={1:"获取成功",-1:"获取职位链接获取失败",-2:"获取职位详情失败"}classHandle(object):job=Job51()job_num=0#job总个数job_explain:Tuple[str,str,List[str]]=None#Job_name和url列表job_url_data:List[Tuple[str,str]]=list()def__init__(self,city:List[str],search:str):self.get_data(city,search)defget_data(self,city:List[str],search:str):"""#获取所有页数的职位名称及URL:paramcity:城市列表:paramsearch:搜索词:return:"""#获取职位详情链接whileself.job.page_num<=self.job.all_page:ifnotself.job.get_data(str(self.job.page_num),city,search):return-1self.job.page_num+=1#总Job个数self.job_num=self.job.job_url_data.__len__()self.job_url_data=self.job.job_url_datadefget_job_explain(self,job_name:str,job_url:str):"""#获取单个职位的详细信息:paramjob_name:城市名称:paramjob_url:城市url:return:"""job_url_data=self.job.job_url_dataself.job_len=job_url_data.__len__()ifnotself.job.get_job_explain(job_name,job_url):return-2self.job_explain=self.job.job_explainreturn1工具类模块(utils.py)只有一个写入结果的函数#文件写入deflog(msg:Tuple[str,str,List[str]]):withopen("msg.csv","a",encoding="utf-8")asf:f.write(f"{msg[0]},{msg[1]},{msg[2]}\n")主文件(main.py)主要启动文件,协程在这支持

2020-11-12 707 0