- 393.50 KB
- 2022-04-22 11:51:32 发布
- 1、本文档共5页,可阅读全部内容。
- 2、本文档内容版权归属内容提供方,所产生的收益全部归内容提供方所有。如果您对本文有版权争议,可选择认领,认领后既往收益都归您。
- 3、本文档由用户上传,本站不保证质量和数量令人满意,可能有诸多瑕疵,付费之前,请仔细先通过免费阅读内容等途径辨别内容交易风险。如存在严重挂羊头卖狗肉之情形,可联系本站下载客服投诉处理。
- 文档侵权举报电话:19940600175。
'通过一周多的学习,大体看完了《C程序设计语言》这本书,这是我的笔记。(一)读这本书的目标是什么?(1)、读完后必须深入了解C的语法以及内涵,并且达到熟练应用。(2)、通过练习习惯一种编程风格,深入理解指针,数组,结构体以及内存分配。(3)、通过练习锻炼逻辑思维能力(4)、学完后编程要上一个层次,自己能够编写出有用的C代码。(二)这本书哪个部分是我要重点看的?(1)、指针、数组、结构体(2)、内存分配(3)、输入输出及接口问题(三)读这本书我有什么收获?3、1对于本书的感受这是一本经典的C语言书籍,与其他语法书不同的是所有语法都是用例题来讲的,通过例子理解并练习语法,另外这本书的习题比较难做,不是简单的考语法,而是一些有意义的习题。通过做练习发现还是有所收获的。本书中与Linux联系密切,用C重写了许多简化版的Shell命令如:grep,ls,cat,sort,tail,cp等等。3、2收获:因为本来就有C语言的基础知识,所以对于语法问题基本没有多学新的知识,但是仍然对以下几点有了新的了解:1)、位字段,不管是通过直接设置位字段还是用以前的位计算,都有新的了解与认识。2)、指针。建立了“指针为大”的思想,对于应用指针进行类型转换以及运算都有了新的认识。比如:inta=5,char*p,p=(char)&a,*p=‘c’;建立这样的过程对于更加复杂的指针转换就理解了。3)、结构体。通过第六章对于二叉树以及哈希表的应用深入了解结构体,并且通过调试程序观察递归过程,同时对递归有了一定的理解。4)、内存分配malloc函数,通过第八章的学习对malloc函数的内部进行分析,理解了动态内存管理机制。3.3学习的程度以及那些地方存在不足:对于C的基本语法已经差不多了,但是否达到了当初的目标即在编程方面上一个层次,这我并不敢确定,因为到现在为止这本书上的习题有些我都没有搞定,又看了一下以前的有关C的东西是觉得已经好了许多了,最起码对于很麻烦的程序不再感到畏惧了。另外觉得自己对于某些问题还是没有理解透彻,比如说输入输出时的缓冲机制,比如说指针与结构体的灵活运用,比如说如何能够运用模块化的思想把一个大的问题逐步细分,通过一个一个的小模块(函数)逐步解决,这些有的是与逻辑思维有关,有些是与某方面的专业知识有关,有些是单纯与C有关,比如说有关缓冲与内存的知识要了解操作系统,另外编译原理也要知道,这些我以前都没有学过,以后会找机会补一补。当然随着进一步的学习与应用,会逐渐的熟练或理解某一些知识点。另外因为时间的原因,对于许多练习没有真正的从各个方面去思考,只是做出来就完了,也没有返回去再仔细考虑每一道习题的意义以及对于我的收获。所以还有待以后有时间在对某些知识点进行学习。习题是本书的重点,也用了不少时间,其中有些是通过对章节内容的学习后自己做出来的(S),有些是参考别人的,参考的原因主要有:(A)对题目不理解,不明白具体要做到什么程度。
(B)自己写了但是不知道对不对参考后发现自己的程序有问题或是不如别人的好又修改的。(C)虽知道题意但自己没有思路或是思路不清晰。在每一道习题的前面都用(S)(A)(B)(C)来表明是属于那一种。另外因为时间问题程序大都没有注释,只是在开始的时候稍加说明并插入了日期。这里整理一下这几天做的练习,这些代码除了少数几个标注的外都是在Linux上调试成功的,当然虽然调试成功了但是有些程序并不完美,许多情况没有考虑,简化了代码但都能达到习题的要求。另外,有几个没有整理出来,原因如下:(1)代码段太小(2)到现在为止没有能够解决。属于后种情况的我在每一章最后都加以说明。第八章:Test8-1.c(S)(cat程序)用read,write,open,close系统调用代替标准库中功能等价的函数,重写第七章的cat程序,并比较相对执行速度。1./*thecatfunction2.WedAug1118:34:43CST2010*/3.#include"stdio.h"4.#include"stdlib.h"5.#include"fcntl.h"6.voidmain(intargc,char*argv[])7.{8.intfd;9.voidfilecopy(int,int);10.char*prog=argv[0];11.if(argc==1)12.filecopy(0,1);13.else14.while(--argc>0)15.{16.if((fd=open(*++argv,O_RDONLY,"r"))==-1)17.{18.fprintf(stderr,"%scan"topen%sn",prog,*argv);19.exit(1);20.}21.else22.{23.filecopy(fd,1);24.close(fd);25.}26.}27.exit(0);28.}29.voidfilecopy(intfd1,intfd2)30.{31.intn;32.staticcharbuf[BUFSIZ];33.while((n=read(fd1,buf,BUFSIZ))>0)34.if(write(1,buf,n)!=n)35.fprintf(stderr,"writeerror");36.}Test8-3.c(?)//本程序未调试通过设计编写fflush、_flush、fclose函数1./*thefopenfunction2.WedAug1119:23:51CST2010*/
1.//#include"stdio.h"2.#include"fcntl.h"3.#include"mystdio2.h"4.#include"sys/file.h"5.#include"unistd.h"6.#include"stdlib.h"7.#definePERMS06668.FILE_iob[OPEN_MAX]={9.{0,(char*)0,(char*)0,_READ,0},10.{0,(char*)0,(char*)0,_WRITE,1},11.{0,(char*)0,(char*)0,_WRITE|_UNBUF,2}12.};13.FILE*fopen(char*name,char*mode)14.{15.FILE*fp;16.intfd;17.if(*mode!="r"||*mode!="w"||*mode!="a")18.returnNULL;19.for(fp=_iob;fp<_iob+OPEN_MAX;fp++)20.{21.if((fp->flag&(_READ|_WRITE))==0)22.break;23.}24.if(fp>=_iob+OPEN_MAX)25.returnNULL;26.if(*mode=="w")27.fd=creat(name,PERMS);28.elseif(*mode=="a")29.{30.if((fd=open(name,O_WRONLY,0))==-1)31.fd=creat(name,PERMS);32.lseek(fd,0L,2);33.}34.else35.fd=open(name,O_RDONLY,0);36.if(fd==-1)37.returnNULL;38.fp->fd=fd;39.fp->ptr=NULL;40.fp->base=NULL;41.fp->cnt=0;42.fp->flag=(*mode=="w")?_WRITE:_READ;43.returnfp;44.}45.int_fillbuf(FILE*fp)46.{47.intbufsize;48.if((fp->flag&(_READ|_EOF|_ERR))!=_READ)49.returnEOF;50.bufsize=(fp->flag&_UNBUF)?1:BUFSIZ;51.if(fp->base==NULL)52.{53.if((fp->base=(char*)malloc(bufsize))==NULL)54.returnEOF;55.}56.fp->ptr=fp->base;57.fp->cnt=read(fp->fd,fp->base,bufsize);58.if(--fp->cnt<0)59.{60.if(fp->cnt=-1)61.fp->flag|=_EOF;62.else63.fp->flag|=_ERR;64.fp->cnt=0;65.returnEOF;66.}67.return(unsignedchar)*fp->ptr++;68.}69.int_flushbuf(intx,FILE*fp)70.{71.unsignednc;72.intbufsize;73.if(fp<_iob||fp>_iob+OPEN_MAX)74.returnEOF;
1.if((fp->flag&(_WRITE|_EOF|_ERR))!=_WRITE)2.returnEOF;3.bufsize=(fp->flag&_UNBUF)?1:BUFSIZ;4.if(fp->base==NULL)5.{6.if((fp->base=(char*)malloc(BUFSIZ))==NULL)7.fp->flag|=_ERR;8.returnEOF;9.}10.else11.{12.nc=fp->ptr-fp->base;13.if(write(fp->fd,fp->base,nc)!=nc)14.fp->flag|=_ERR;15.returnEOF;16.}17.fp->ptr=fp->base;18.*fp->ptr++=(char)x;19.fp->cnt=bufsize-1;20.returnx;21.}22.intfflush(FILE*fp)23.{24.intrc=0;25.if(fp<_iob||fp>_iob+OPEN_MAX)26.returnEOF;27.if(fp->flag&_WRITE)28.rc=_flushbuf(0,fp);29.//fp->ptr=fp->base;30.fp->cnt=(fp->flag&_UNBUF)?1:BUFSIZ;31.returnrc;32.}33.intfclose(FILE*fp)34.{35.intrc;36.if((rc=fflush(fp))!=EOF)37.{38.free((void*)fp->base);39.fp->cnt=0;40.fp->ptr=NULL;41.fp->base=NULL;42.fp->flag&=~(_READ|_WRITE);43.}44.returnrc;45.}46.main()47.{48.unsignedcharc;49.FILE*fp;50.fp=fopen("mystdio2.h","r");51.getc(fp);52.putc(c,fp);53.}54./mystdio2.h55.#defineNULL056.#defineEOF(-1)57.#defineOPEN_MAX2058.#defineBUFSIZ102459.typedefstruct_iobuf{60.intcnt;61.char*ptr;62.char*base;63.intflag;64.intfd;65.}FILE;66.externFILE_ioba[OPEN_MAX];67.#definestdin(&_iob[0])68.#definestdout(&_iob[1])69.#definestderr(&_iob[2])70.enum_flags{71._READ=01,72._WRITE=02,73._UNBUF=04,74._EOF=010,75._ERR=02076.};
1.int_fillbuf(FILE*);2.int_flushbuf(int,FILE*);3.//FILE*fopen(char*,char*);4.intfclose(FILE*);5.intfflush(FILE*);6.#definefeof(p)(((p)->flag&_EOF)!=0)7.#definegetc(p)(--(p)->cnt>=08.?(unsignedchar)*(p)->ptr++:_fillbuf(p))??宏定义但这不是个函数,如何应用,用一个变量接受他的结果呢?9.#defineputc(x,p)(--(p)->cnt>=010.?*(p)->ptr++=(x):_flushbuf((x),p))11.#definegetchar()getc(stdin)12.#defineputchar(x)putc((x),stdout)这段代码是原书上的内容,我添加了练习中的_flushfflush以及fclose函数,程序的从思路上走没什么问题,但是因为重写了stdio.h所以编译老是出错,而且对于我标出的哪一点我还是有些疑问的。Test8-4.c(?)//有疑问的程序(fseek程序)设计编写fseek(FILE*fp,longoffset,intorigin)函数1.#include"stdio.h"2.#include"stdlib.h"3.intfseek(FILE*fp,longoffset,intorigin)4.{5.unsignednc;6.longrc=0;7.if(fp->flag&_READ)8.{9.if(origin==1)10.offset-=fp->cnt;??为什么要这样做呢?11.rc=lseek(fp->fd,offset,origin);12.fp->cnt=0;13.}14.elseif(fp->flag&_WRITE)15.{16.if((nc=fp->ptr-fp->base)>0)17.if(write(fp->fd,fp->base,nc)!=nc)18.rc=-1;19.if(rc!=-1)20.rc=lseek(fp->fd,offset,origin);21.}22.return(rc==-1)?-1:0;23.}这是本题的一个答案,但是我并不怎么明白,Fseek的实现是调用了系统函数lseek但是lseek除了在第一个参数不同外难道offset这个参数也是不同的吗?书上并没有深入讲解lseek函数,所以对于这个问题我还是不太明白,我在网上了解了一些信息,并做了个跟踪fseek的程序,但是结果还是没有弄明白,假设fseek中所谓的移动的那个指针是系统管理的,但是那个FILE结构中的用于缓冲的指针让我对他的运算移动不了解,以下是跟踪程序:1.#include"stdio.h"2.#include"stdlib.h"3.#defineBUF_LEN34.Printbuf(char*buf,intlen)5.{6.inti;7.for(i=0;i_IO_read_ptr,ftell(fp));7.for(i=0;i<2;++i)8.{9.fgetc(fp);10.Printbuf(mybuf,BUF_LEN);11.printf("curp=%ptpos=%ldn",fp->_IO_read_ptr,ftell(fp));12.}13.fseek(fp,5L,1);14.Printbuf(mybuf,BUF_LEN);15.printf("curp=%ptpos=%ldn",fp->_IO_read_ptr,ftell(fp));16.fgetc(fp);17.Printbuf(mybuf,BUF_LEN);18.printf("curp=%ptpos=%ldn",fp->_IO_read_ptr,ftell(fp));19./*fgetc(fp);20.Printbuf(mybuf,BUF_LEN);21.printf("curp=%ptpos=%ldn",fp->_IO_read_ptr,ftell(fp));22.fgetc(fp);23.Printbuf(mybuf,BUF_LEN);24.printf("curp=%ptpos=%ldn",fp->_IO_read_ptr,ftell(fp));25.fgetc(fp);26.Printbuf(mybuf,BUF_LEN);27.printf("curp=%ptpos=%ldn",fp->_IO_read_ptr,ftell(fp));*/28.fclose(fp);29.//getchar();30.}这是当fseek(fp,2L,1)的时候:mybuf=0xbff05c15curp=0xbff05c15pos=0ABCcurp=0xbff05c16pos=1ABCcurp=0xbff05c17pos=2ABCcurp=0xbff05c15pos=4EFGcurp=0xbff05c16pos=5curp就是FILE结构体中的缓冲区指针,当执行fseek的时候他是怎样移动的?这是当fseek(fp,1L,1)的时候mybuf=0xbfcefe15curp=0xbfcefe15pos=0ABCcurp=0xbfcefe16pos=1ABCcurp=0xbfcefe17pos=2BCDcurp=0xbfcefe17pos=3BCDcurp=0xbfcefe18pos=4
这是当fseek(fp,5L,1)的时候mybuf=0xbfee6ce5curp=0xbfee6ce5pos=0ABCcurp=0xbfee6ce6pos=1ABCcurp=0xbfee6ce7pos=2FGHcurp=0xbfee6ce7pos=7FGHcurp=0xbfee6ce8pos=8这是fseek(fp,-3L,1)并且当for(i=0;i<4;++i)的时候mybuf=0xbfb199d5curp=0xbfb199d5pos=0ABCcurp=0xbfb199d6pos=1ABCcurp=0xbfb199d7pos=2ABCcurp=0xbfb199d8pos=3DEFcurp=0xbfb199d6pos=4DEFcurp=0xbfb199d5pos=3DEFcurp=0xbfb199d6pos=4Test8-5.c(?)(ls程序)1./*2.WedAug1106:24:34CST2010*/3.#include4.#include5.#include6.//#include"syscalls.h"7.#include8.#include9.#include"sys/dir.h"10.#include"stdlib.h"11.//#defineNAME_MAX1412.#defineMAX_PATH102413.#defineDIRSIZ1414.typedefstruct{15.longino;16.charname[NAME_MAX+1];17.}Dirent;18.typedefstruct{19.intfd;20.Direntd;21.}MYDIR;??不用MYDIR结构不行吗?用到fd的时候直接设个变量代替不行吗?22.structmydirect{23.ino_td_ino;24.chard_name[DIRSIZ];25.};26.MYDIR*myopendir(char*dirname);27.Dirent*myreaddir(MYDIR*dfd);28.voidmyclosedir(MYDIR*dfd);29.//intstat(char*,structstat*);
1.voiddirwalk(char*,void(*fcn)(char*));2.voidfsize(char*);3.voidmain(intargc,char*argv[])4.{5.if(argc==1)6.fsize(".");7.else8.while(--argc>0)9.fsize(*++argv);10.}11.voidfsize(char*name)12.{13.structstatstbuf;14.if(stat(name,&stbuf)==-1)15.{16.fprintf(stderr,"fsize:can"taccess%sn",name);17.return;18.}19.if((stbuf.st_mode&S_IFMT)==S_IFDIR)20.dirwalk(name,fsize);21.printf("%5u%6o%8ld%sn",(unsigned)stbuf.st_ino,stbuf.st_mode,stbuf.st_size,name);22.}23.voiddirwalk(char*dir,void(*fcn)(char*))24.{25.charname[MAX_PATH];26.Dirent*dp;27.MYDIR*dfd;28.if((dfd=myopendir(dir))==NULL)29.{30.fprintf(stderr,"dirwalk:can"topen%sn",dir);31.return;32.}33.while((dp=myreaddir(dfd))!=NULL)34.{35.if(strcmp(dp->name,".")==0||strcmp(dp->name,"..")==0)36.continue;37.if(strlen(dir)+strlen(dp->name)+2>sizeof(name))38.fprintf(stderr,"dirwalk:name%s%stoolongn",dir,dp->name);39.else40.{41.sprintf(name,"%s/%s",dir,dp->name);42.(*fcn)(name);43.}44.}45.myclosedir(dfd);46.}47.intfstat(intfd,structstat*);48.MYDIR*myopendir(char*dirname)49.{50.intfd;51.structstatstbuf;52.MYDIR*dp;53.if((fd=open(dirname,O_RDONLY,0))==-154.||fstat(fd,&stbuf)==-155.||(stbuf.st_mode&S_IFMT)!=S_IFDIR56.||(dp=(MYDIR*)malloc(sizeof(MYDIR)))==NULL)57.returnNULL;58.dp->fd=fd;59.returndp;60.}61.voidmyclosedir(MYDIR*dp)62.{63.if(dp)64.{65.close(dp->fd);66.free((void*)dp);67.}
1.}2.Dirent*myreaddir(MYDIR*dp)3.{4.structmydirectdirbuf;??为什么要借用这个结构?5.staticDirentd;??直接用Dirent不行吗?6.while(read(dp->fd,(char*)&dirbuf,sizeof(dirbuf))==sizeof(dirbuf))??出错,直接返回了NULL,7.{//读会有什么问题?8.if(dirbuf.d_ino==0)9.continue;10.d.ino=dirbuf.d_ino;11.strncpy(d.name,dirbuf.d_name,DIRSIZ);12.d.name[DIRSIZ]=" ";13.return&d;14.}15.returnNULL;16.}本题的代码仍然是原书上的代码,是一个Linux中经典命令ls的简化版本,习题只是让修改一点,但是这段代码一直在机器上实现不了功能,我跟踪了一下过程发现总是在我标出的地方直接返回NULL了,但是程序在逻辑上我觉得没什么错误呀,还有为什么要设计MYDIR结构呢,我怎么觉得只要一个Dirent结构就够了呢?具体用到文件描述符时定义一个int型的不就行了吗?要让opendir,readdir等用MYDIR结构操作我怎么感到多此一举呢?还有在readdir函数中借用了系统中的structdirect结构这又是为什么呢?直接用一个Dirent结构难道不行吗?这也就不用来回在转换再赋值了不是吗?Test8-6(S)Test8-7(C)Test8-8(S)(malloc、calloc、free程序)1./*themallocfunction:2.WedAug1103:29:19CST2010*/3.#include"stdio.h"4.#include"string.h"5.#defineNALLOC10246.#defineMAXNBYTES102407.typedeflongAlign;8.unionheader9.{10.struct11.{12.unionheader*next;13.unsignedsize;14.}s;15.Alignx;16.};17.typedefunionheaderHeader;18.staticunsignedmaxalloc;19.staticHeaderbase;20.staticHeader*freeptr=NULL;21.void*malloc(unsignednbytes)22.{23.Header*ptr;24.Header*prevptr;25.Header*morecore(unsigned);26.unsignednunits;27.if(nbytes>MAXNBYTES)28.{29.fprintf(stderr,"can"tallocmorethan%ubytesn",MAXNBYTES);30.returnNULL;31.}32.nunits=(nbytes+sizeof(Header)-1)/(sizeof(Header))+1;33.printf("thenunitsis%dn",nunits);34.if((prevptr=freeptr)==NULL)35.{36.base.s.next=prevptr=freeptr=&base;
1.base.s.size=0;2.}3.for(ptr=prevptr->s.next;;prevptr=ptr,ptr=ptr->s.next)4.{5.if(ptr->s.size>=nunits)6.{7.if(ptr->s.size==nunits)8.prevptr->s.next=ptr->s.next;9.else10.{11.ptr->s.size-=nunits;12.ptr=ptr+ptr->s.size;13.ptr->s.size=nunits;14.}15.freeptr=prevptr;16.return(void*)(ptr+1);17.}18.if(ptr==freeptr)19.{20.if((ptr=morecore(nunits))==NULL)21.returnNULL;22.}23.}24.}25.Header*morecore(unsignednu)26.{27.char*cp,*sbrk(int);28.Header*hp;29.voidfree(void*);30.if(nus.size=nu;37.maxalloc=(hp->s.size>maxalloc)?nu:maxalloc;38.free((void*)(hp+1));39.returnfreeptr;40.}41.voidfree(void*ap)42.{43.Header*bp;44.Header*p;45.bp=(Header*)ap-1;46.if(bp->s.size==0||bp->s.size>maxalloc)47.{48.fprintf(stderr,"free,can"tfree%uunitsn",bp->s.size);49.return;50.}51.for(p=freeptr;bp>p&&bps.next;p=p->s.next)52.{53.if(p>p->s.next&&(bp>p||bps.next))54.break;55.}56.if(bp+bp->s.size==p->s.next)57.{58.bp->s.size+=p->s.next->s.size;59.bp->s.next=p->s.next->s.next;60.}61.else62.bp->s.next=p->s.next;63.//p->s.next=bp;64.if(p+p->s.size==bp)65.{66.p->s.size+=bp->s.size;67.p->s.next=bp->s.next;68.}69.else70.p->s.next=bp;71.freeptr=p;72.}73.unsignedbfree(char*p,unsignedn)74.{
1.Header*hp;2.hp=(Header*)p;3.if(ns.size=(n+sizeof(Header)-1)/sizeof(Header);6.free((void*)(hp+1));7.returnhp->s.size;8.}9.void*calloc(unsignedn,unsignedsize)10.{11.unsignednb;12.char*p,*q;13.inti;14.nb=n*size;15.if((p=q=(char*)malloc(nb))!=NULL)16.for(i=0;i