关闭

关闭

封号提示

内容

首页 Linux系统编程-1-ANSI文件管理.ppt

Linux系统编程-1-ANSI文件管理.ppt

Linux系统编程-1-ANSI文件管理.ppt

上传者: geek 2014-02-24 评分 5 0 108 15 493 暂无简介 简介 举报

简介:本文档为《Linux系统编程-1-ANSI文件管理ppt》,可适用于IT/计算机领域,主题内容包含Linux系统编程ANSI文件管理Linux系统编程ANSI文件管理main()函数传参main()函数传参有的时候需要在运行时向程序传递信息比如说符等。

Linux系统编程ANSI文件管理Linux系统编程ANSI文件管理main()函数传参main()函数传参有的时候需要在运行时向程序传递信息比如说我们用cat命令查看文件的时候需要在后面加一个具体的“文件名”来实现我们对某个文件的查看。实际上它是将“文件名”作为变量传递给main()函数。main函数原型:intmain(intargc,char*argv)intmain(intargc,char*argv,char*envp)在C语言中由三个特殊的内嵌变量argc,argv和envp用于接收命令行变量。main()函数传参main()函数传参argc是命令行参数的数目(包括命令本身)argv是指向参数的各种指针所构成的数组即argv表示命令本身argv表示第一个参数。envp存储进程运行的环境变量信息。main()函数传参举例main()函数传参举例#include<stdioh>#include<stdlibh>intmain(intargc,char*argv){if(argc!=){printf(“youforgottotypeyournamen”)exit()}printf(“Hellos”,argv)return}内存管理基本概念内存管理基本概念C程序内存分配栈和堆的区别Linux下数据类型的大小数据存储区域C程序内存分配C程序内存分配C程序结构C程序结构C程序结构可执行程序在存储的时候分为代码区(text)、数据区(data)和未初始化区(bss)三个部分。代码区(text):存放CPU执行的机器指令通常代码区是可共享的而且是只读的。数据区(data):全局初始化数据区静态数据区包括程序中被初始化的全局变量、静态变量和常量。未初始化区(bss):存储的是全局未初始化变量。#include<stdioh>intsummain(){…………}C程序结构C程序结构已初始化变量、静态变量和常量数据(数据区)未初始化全局变量(bss区用零初始化)堆区(向上增长)栈区(向下增长)已初始化全局变量、静态变量和常量数据(数据区)未初始化变量(bss区用零初始化)可执行代码(代码区)可执行代码(代码区)存储时的个区域(size)运行时的个区域高地址低地址C程序结构C程序结构代码区:顺序指令只会执行一次。如果是反复则需要跳转指令。如果进行递归则要借助栈来实现。全局初始化数据区静态数据区:只初始化一次。未初始化数据区:运行时改变其值。C程序结构C程序结构栈区:由编译器自动分配释放存放函数的参数值、局部变量的值。堆区:用于动态内存分配。C程序结构C程序结构一个进程在运行过程中。代码是根据流程一次执行的只需要访问一次当然跳转和递归有可能执行多次而数据一般需要访问多次因此单独开辟空间以方便访问和节省空间。临时数据及需要再次使用的代码在运行时放入栈区生命周期短。全局数据和静态数据有可能在整个程序执行过程中都需要访问因此单独存储。堆上的数据由用户自由分配以便管理。C程序结构C程序结构inta=char*pmain(){intbchars=“abc”char*p,*pchar*p=“”staticintc=p=(char*)malloc()p=(char*)malloc()free(p)free(p)}内存分配方式内存分配方式静态分配编译器在处理程序源代码时分配。动态分配程序在执行的时候调用malloc库函数分配。二者区别:静态对象是有名字的变量可以直接对其进行操作动态对象是没有名字的变量需要通过指针间接地对它进行操作静态对象的分配与释放由编译器自动处理动态对象的分配与释放必须由程序员分配通过malloc和free完成。p=(char*)malloc(*sizeof(int))栈和堆的区别栈和堆的区别管理方式不同栈由编译器自动管理无需程序员手工控制而堆空间的申请、释放工作由程序员控制容易产生内存泄露。空间大小不同栈是向低地址空间扩展的数据结构是一块连续的内存区域当申请的空间超过的栈的空间时会提示溢出因此从栈中获得的空间比较小。堆是向高地址扩展的数据结构是不连续的内存区域因为系统用链表存储空闲内存地址而且链表的遍历方向是从低地址到高地址堆获得的空间较灵活也比较大。栈和堆的区别栈和堆的区别是否产生碎片对于堆来说频繁的mallocfree会造成内存空间的不连续从而造成大量的碎片。使程序的效率变低栈没有这个问题。增长方向不同栈是向内存地址减少的方向增长堆向内存地址增加的方向增长。分配方式不同堆是由程序malloc()函数动态申请并由free()函数释放的栈的分配和释放是由编译器来完成的,栈动态分配由alloca()函数完成。栈和堆的区别栈和堆的区别分配效率不同栈是机器系统提供的数据结构计算机会在底层堆栈提供支持分配专门的寄存器存放栈的地址压栈和出栈都有专门的指令堆是由库函数提供的机制复杂。Linux数据类型的大小Linux数据类型的大小char数据类型位,有符号(~),无符号(~)。shortint数据类型位,有符号(~),无符号(~)。int数据类型位,有符号(~),无符号(~U)。Linux数据类型的大小Linux数据类型的大小longint数据类型位。随着宏WORDSIZE的值而改变。longlongint数据类型位。LL~LLULL数据存储区域数据存储区域bnbstackvarstackvarstackvarstackvarlevelvarbssvardatavarmainafunc栈区堆区BSS数据段代码段见程序memadd内存管理函数内存管理函数malloc()free()函数realloc()更改已经配置的内存空间其它内存管理函数calloc()和alloca()mallocfree函数mallocfree函数malloc()用于在堆中申请内存空间free()函数释放原先申请的空间。两个函数的头文件:#include<stdlibh>注意:、调用free()释放内存后不能再去访问被释放的空间。内存被释放后指针很有可能还指向这个内存单元但这块内存不在属于原来的应用程序此时的指针为悬挂指针(可以赋值为)。、不能两次释放相同的指针。、malloc()和free()需要配套使用。程序mallocexamplerealloc更改已经配置的内存空间realloc更改已经配置的内存空间realloc()函数用来更改以前在堆上分配的内存区长度(增加或减少)当需要扩大一块内存空间时realloc()试图直接从当前内存段后面的字节中获得更多的内存空间如果能够满足则返回原指针如果后面空间的字节不够就使用堆上第一个能满足这一要求内存块并将原数据复制到新的位置。如果内存不足分配失败返回。程序:realloccalloc()和alloca()calloc()和alloca()、calloc()是malloc()函数的简单封装优点是将动态分配的内存进行初始化全部清零。、alloca()函数用来在栈中分配size个字节的内存空间因此函数在返回的时候会自动释放空间。与malloc()函数的区别:、alloca()向栈中申请空间无需释放malloc申请的内存位于堆中最终要用函数来释放。、malloc()没有初始化申请的内存空间在使用malloc()之后要用memset()初始化这部分内存空间。alloca()将初始化这部分空间为零。calloc()和alloca()calloc()和alloca()、calloc()的用法ptr=(structdata*)calloc(count,sizeof(structdata))calloc()的实现:void*calloc(sizetnmemb,sizetsize){void*p=malloc(nmemb*size)intsizettotal=nmemb*sizeif(p!=)memset(p,’’,total)returnp}calloc和allocacalloc和allocaalloca函数:void*alloca(sizetsize)ANSIC文件管理ANSIC文件管理文件基本概念及文件指针文件和流文件指针ANSIC标准文件IO操作缓冲区类型打开关闭文件读写文件流文件流定位格式化输入输出函数库函数调用和系统调用库函数调用和系统调用用户模式内核模式什么是系统调用什么是系统调用系统调用发生在(比如emacs)通过调用特殊函数(例如open)以请求内核提供服务的时候。在这里用户进程被暂时挂起。内核检验用户请求尝试执行并把结果反馈给用户进程接着用户进程重新启动。系统调用负责保护对内核所管理的资源的访问系统调用中的几个大类主要有:处理IO请求(openclosereadwritepoll等等)进程(forkexecvekill等等)时间(timesettimeofday等等)以及内存(mmapbrk等等)的系统调用。几乎所有的系统调用都可以归入这几类中。中断、内核空间、用户空间中断、内核空间、用户空间中断:硬件中断:软件中断:软件中断是用户进程通知内核需要出发系统调用的基本方法(中断号x对于intelCPU:INT)。内核通过systemcall函数响应中断。内核空间(kernelspace)内核保留的内存。内核通过putuser和getuser宏和类似的宏访问用户空间用户空间(userspace)用户进程保留的内存任何一个用户进程使用的内存都称为用户空间用户进程不能直接访问内核空间。多用户进程也经常同时运行而且各个进程之间通常不会共享它们的内存但是内核在某一个时刻通常只和一个用户进程交互因此实际上不会引起任何混乱。syscallsyscall应用C库Read()wrapper系统调用处理程序sysread()文件基本概念文件基本概念文件和流文件是具有永久性存储及特定顺序的字节组成的一个有序、有名称的集合。流是一个抽象的概念是物质从一处向另一处流动的过程。在程序开发中流是指信息从外部输入设备向计算机内部输入或者是从内存向外部输出设备输出的过程。为了便于开发操作系统屏蔽了实际IO设备的物理细节当打开一个文件后即将该打开的文件与一个流联系在一起要对打开的文件操作只需对该文件流操作即可。文件分类文件分类按照数据的存储格式可分为以下两类:文本文件:如:ASCII文件。英文、数字等字符存储的是ASCII码而汉字存储的是机内码文本文件不能存储声音、动画、图像、视频等信息。二进制文件:如:图形文件及文字处理程序等计算这些文件含有特殊的格式及计算机代码机程序。文件缓冲区文件缓冲区根据应用程序对文件的访问方式可以将文件系统分成缓冲区的文件系统和非缓冲区的文件系统。缓冲区文件系统:高级文件系统系统自动为正在使用的文件开辟内存缓冲区ANSI的标准IO函数使用的就是缓冲文件系统。非缓冲文件系统:低级文件系统由用户在程序中为每个文件设定缓冲区。如遵循POSIX标准的文件系统调用IO函数使用的是非缓冲文件系统。文件缓冲区文件缓冲区a程序数据区输入文件缓冲区输入文件缓冲区磁盘文件指令区用户数据区缓冲区磁盘文件文件指针文件指针文件指针FILE在应用层对文件流的访问是通过文件指针FILE来实现FILE是一个结构体类型包含了IO库为管理该流需要的所有信息如实现IO的文件描述符、指向流缓冲区的指针缓冲区的长度、当前缓冲区中的字符数和出错标志等。`程序:filefileptr缓冲区类型缓冲区类型标准IO提供了三种类型的缓冲区全缓冲、行缓冲、无缓冲。全缓冲:这种缓冲区要求全部填满整个缓冲区才进行IO系统调用操作。对于磁盘文件通常使用全缓冲区访问。第一次执行IO操作时ANSI标准的文件管理函数通过调用malloc函数获得需使用的缓冲区。默认大小为。刷新(flush)操作即标准的IO缓冲区的写操作。它可以由系统自动完成或者调用函数fflush()或flush()实现。缓冲区类型缓冲区类型usrincludestdiohdefaultbuffersize#ifndefBUFSIZ#defineBUFSIZIOBUFSIZ#endifusrincludelibioh#defineIOBUFSIZGBUFSIZusrincludegconfigh#defineGBUFSIZ缓冲区类型缓冲区类型行缓冲:在输入和输出中遇到换行时标准IO库函数执行IO系统调用操作当涉及终端的操作时使用行缓冲区。无缓冲:标准IO库不对字符进行缓存。如标准出错流stderr是不带缓冲区的使得出错信息尽快的显示出来。缓冲区类型缓冲区类型ANSIC要求缓冲区有如下特征:、标准输入和标准输出设备:当且仅当不涉及交互设备时标准输入流和标准输出流才是全缓冲的。、标准错误输出设备:标准出错绝不会是全缓冲的。对于任何一个给定的流可以调用setbuf()和setvbuf()函数更改其缓冲区类型缓冲区类型缓冲区类型usrincludestdiohvoidsetbuf(FILE*stream,char*buf)intsetvbuf(FILE*stream,char*buf,intmodes,sizetn)#defineIOFBF#defineIOLBF#defineIONBF程序buf打开关闭文件打开关闭文件打开文件在对文件操作之前需要将它和流联系在一起。FILE*fopen(constchar*filename,constchar*modes)打开关闭文件打开关闭文件如果用一个打开的文件替换当前的一个流对象可以用freopen()函数:FILE*freopen(constchar*filename,constchar*modes,FILE*stream)完成对流对象的操作后需要关闭该流对象在关闭该流对象之前应将缓冲区的内容写会磁盘(由OS完成)关闭某个流使用fclose()函数。intfclose(FILE*stream)打开关闭文件打开关闭文件如果需要关闭打开的所有流对象使用fcloseall()函数。intfcloseall(void)即使缓冲区没有填满也可以刷新缓冲区内容可以使用fflush()函数。intfflush(FILE*stream)打开关闭文件#include<stdioh>intmain(intargc,char*argv){FILE*fp=fp=fopen("trytxt","r")以只读形式打开文件trytxtif(fp==)不成功则输出"failtoopenfile!n"{printf("failtoopenfile!n")return}printf("openfilesuccessfully!n")fclose(fp)关闭已打开的文件return}读写文件流读写文件流根据不同的需要ANSI标准提供了种类型的IO处理函数包括字符读写函数、行读写函数和块读写函数。、字符读写文件流()字符读操作:字符读操作是指每次IO调用只读出流中的一个字符。#include<stdioh>intfgetc(FILE*stream)intgetc(FILE*stream)读写文件流读写文件流对于fgetc的几点说明:在fgetc函数调用中读取的文件必须是以只读或读写方式打开的。读取字符的结果可以不向字符变量赋值如:fgetc(fp)但读出的数不能保存。在文件内部由一个位置指针用来指向文件的当前读写字节在文件打开时该指针总是指向文件的第一个字节使用fgetc函数后该位置指针将向后移动一个字节因此可连续多次使用fgetc函数读取多个字符。应注意文件指针和文件内部的位置指针不是一回事文件指针指向整个文件须在程序中定义说明只要不重新赋值文件指针的值是不变的。文件内部的位置:指针用以指示文件内部的当前读写位置每次读写一次该指针均向后移动它不需在程序中定义说明而是由系统自动设置。读写文件流读写文件流()字符写操作。字符写操作是指每次标准IO调用只写一个字符到流中。usrincludestdiohintfputc(intc,FILE*stream)intputc(intc,FILE*stream)intputchar(intc)读写文件流读写文件流对于fputc()函数使用的几点说明:intfputc(intc,FILE*stream)每写入一个字符文件内部位置指针向后移动一个字符。fputc函数有一个返回值如果写入成功则返回写入的字符否则返回一个EOF用此来判断写入是否成功。这里的c虽然是int型但是fputc函数中会强制转换为unsignedchar类型写入文件这里的int是为了保持跟fgetc函数接口一致。#include<stdioh>intmain(intargc,char*argv){FILE*fp=charchif(argc<=){printf("checkusageofsn",argv)return}if((fp=fopen(argv,"r"))==)以只读形式打开argv所指明的文件{printf("cannotopensn",argv)return}while((ch=fgetc(fp))!=EOF)把已打开的文件中的数据fputc(ch,stdout)逐字节的输出到标准输出stdoutfclose(fp)关闭文件return}行读写文件流行读写文件流()行读出操作。行读出操作是指每次IO调用只从标准流中读出一行字符。char*fgets(char*s,intn,FILE*stream)此函数将字符从stream读入s所指向的缓冲区(数组)直到读取n字符、换行符(传输到s)、或遇到文件结束标志为止字符串以空字符结束。成功完成后返回s从标准输入读取数据还可以用gets()函数char*gets(char*s)从标准输入流stdin读入s所指向的数组直到遇到换行符或文件结束标志为止同时换行符被忽略字符串以空字符结束。成功完成后返回s。调用者在使用gets时不能指定缓冲区长度可能造成缓冲区溢出。不建议使用。行读写文件流行读写文件流()行写入操作。行写入操作是指每次标准IO调用只写一行字符到标准流中。intfputs(constchar*s,FILE*stream)intputs(constchar*s)puts()将s指向的以空字符结尾的字符串(后接换行符)写入标准输出流stdout。fputs()将s指向的以空字符结尾的字符串写入指定输出stream但不追加换行符。两个函数都不写入终止空字符。返回值:成功:返回非负数表示实际写入的字节数。失败:返回EOF。行读写文件流行读写文件流#include<stdioh>intmain(intargc,char*argv){FILE*fp=charstrif((fp=fopen("aatxt","r"))==){printf("cannotopen!n")return}fgets(str,sizeof(str),fp)fputs(str,stdout)fclose(fp)return}块读写文件流块读写文件流块读写文件流是指每次读出与写入的数据量可以由自己设定。()块读出操作。typedefsizetintsizetfread(void*ptr,sizetsize,sizetn,FILE*stream)此函数从标准流中读取n个大小为size的对象其第一个参数为指向欲存放读取的对象空间指针即读取的对象的存放位置第二个参数为读取对象的大小(sizeof(structbuf))第三个参数可以为读取对象的个数第四个参数为读取的流。返回值为实际读取的n数目。块读写文件流块读写文件流()块写入操作sizetfwrite(constvoid*ptr,sizetsize,sizetn,FILE*stream)此函数将向标准的的流中写入n个大小为size的对象其第一个参数为指向欲写入的对象的数据空间指针即写入的对象的存放位置第二个参数为写入对象的大小第三个参数为写入的个数第四个参数为写入的数据流。说明:写入成功则返回实际写入的对象个数否则返回#include<stdioh>intmain(intargc,char*argv){structstudent{charnameintnumber}FILE*fp=intistructstudentboya,boyb,*pp,*qqif((fp=fopen("aatxt","w"))==)以可读写的方式打开文件若该文件存在则清空若不存在就创建{printf("cannotopen!n")return}pp=boyaqq=boybprintf(“pleaseinputtwostudents‘nameandnumber:n")for(i=i<i,pp)scanf("sd",pp>name,pp>number)pp=boyafwrite(pp,sizeof(structstudent),,fp)将从键盘输入的信息写入到文件流fp中rewind(fp)将读写位置定位到文件头fread(qq,sizeof(structstudent),,fp)从文件流fp中读两个结构体到qqprintf("namettnumbern")for(i=i<i,qq)输出qq中的内容printf("sttdn",qq>name,qq>number)fclose(fp)return}块读写文件块读写文件文件流检查:对于ASCII文件其内容均大于因此通过判断时候==EOF来确定时候读到了流的结束。(如:)但对于二进制文件流则需要使用feof来判断。intfeof(FILE*stream)使用feof或ferror进行判断后如果出现错误将设置错误标示符执行错误处理后清除该错误标示符。voidclearerr(FILE*stream)#include<stdioh>intmain(intargc,char*argv){structstudent{charnameintnumber}FILE*fp=intiintrcstructstudentstudent,*qqif((fp=fopen("aatxt","r"))==){printf("cannotopenfile!n")return}rc=fread(student,sizeof(structstudent),,fp)printf("rc=dn",rc)if(rc!=)判断是否读了个字节{if(feof(fp))判断是否读到文件尾printf("readendoffile!n")elseprintf("readfileerror!n")}qq=studentfor(i=i<rci,qq)printf("sttdn",qq>name,qq>number)fclose(fp)return}块读写文件块读写文件文件流定位对文件流进行操作的时候有一个指针指向流的当前读写位置如果希望从特殊位置读写需要通过函数修改当前读写位置。()返回当前读写位置。ftell返回流的当前读写位置。longftell(FILE*stream)块读写文件块读写文件()修改当前读写位置。fseek修改当前读写位置。intfseek(FILE*stream,longoffset,intwhence)函数第一个参数为操作的流对象第二参数为指针对第三个参数(修改基准)的偏移量第三个参数为修改位置的基准。#defineSEEKSET从文件开头移动offset个字节#defineSEEKCUR从当前位置移动offset个字节#defineSEEKEND从文件末尾移动offset个字节块读写文件块读写文件关于fseek函数:offset可正可负负表示向文件开头的方向移动正表示向文件结束的方向移动如果向前移动的字节数超过的文件开头则置指针停在文件开头如果向后移动的字节数超过了文件末尾则将增大文件尺寸从原来的文件末尾到现在的位置指针直接的字节都是fseek调用成功则返回失败返回非零。注:当文件以“a”模式打开时写数据始终写到文件末尾即使移动了文件内部指针也不受影响。当文件以“a”模式打开时写数据始终写到文件末尾移动了文件内部指针只影响读数据的位置以其它模式打开读写的位置都取决于文件内部位置指针。块读写文件块读写文件()重置当前读写位置。当执行完一次操作为了实现第二次操作时需要调用rewind函数将读写指针重置到文件开始位置。参数stream为已打开的文件指针。voidrewind(FILE*stream)等同于fseek(stream,,SEEKSET)#include<stdioh>intmain(intargc,char*argv){structstudent{charnameintnumber}FILE*fp=structstudentstudent,*qqif((fp=fopen("aatxt","r"))==){printf("cannotopenfile!n")return}fseek(fp,sizeof(structstudent),)定位到第二个结构体fread(student,sizeof(structstudent),,fp)printf("namettnumbern")qq=studentprintf("sttdn",qq>name,qq>number)fclose(fp)return}格式化输入输出函数格式化输入输出函数ANSI提供了多个格式化输入输出函数如:scanfprintf和fscanffprintf格式化输入输出文件、格式化输入函数intfscanf(FILE*stream,constchar*format,…)从执行的输入流中按指定格式读取数据。intsscanf(constchar*str,constchar*format,…)将参数str的字符串根据参数format字符串来转换并格式化数据。格式化输入输出函数格式化输入输出函数、格式化输出函数intfprintf(FILE*stream,constchar*format,…)fprintf将输出按指定的格式放置到指定的输出流。intsprintf(char*str,constchar*format,…)sprintf()函数将后接空字符’’输出放置在以*str为开始的连续空间中。#include<stdioh>#include<stdlibh>intmain(intargc,char*argv){charabuf,bbufFILE*fpif((fp=fopen("tmp","w"))==){perror("fopen")exit(EXITFAILURE)}printf("inputastring(<):n")scanf("s",abuf)fprintf(fp,"s",abuf)rewind(fp)fscanf(fp,"s",bbuf)printf("sn",bbuf)fclose(fp)return}

精彩专题

职业精品

上传我的资料

热门资料

资料评价:

/ 67
所需积分:2 立即下载

意见
反馈

返回
顶部

Q