C语言——低级I/O

C语言低级I/O主要是指read、write、open、creat这些函数,这些函数和其它语言的IO用法差不多,只有creat这个函数很少见,用法也不容易弄明白。下面还是以《C程序设计语言》里面的例子来说明。

#include <stdio.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdlib.h>

#define PERMS 0666

void error(char *,...);

int main(int argc,char *argv[]){
	int f1,f2,n;
	char buf[BUFSIZ];
	
	if(argc != 3){
		error("Usage: cp from to");
	}
    /* O_RDONLY来自fcntl.h */ 
	if((f1 = open(argv[1],O_RDONLY,0)) == -1){
		error("cp: can't open %s",argv[1]);
	}
	if((f2 = creat(argv[2], PERMS)) == -1){
		error("cp: can't create %s,mode %03o",argv[2],PERMS);
	}
	
	while((n = read(f1,buf,BUFSIZ)) > 0){
		if(write(f2,buf,n) != n){
			error("cp: write error on file %s",argv[2]);
		}
	}
	return 0;
}

void error(char *fmt,...){
	va_list args; /* 来自stdarg.h */
	va_start(args,fmt);
	fprintf(stderr,"error: ");
	vfprintf(stderr,fmt,args);
	fprintf(stderr,"\n");
	va_end(args);
	exit(1); /* 来自stdlib.h */
}

此程序在dev c++下运行通过,与书上的代码略有出入,有几点稍作说明:

1,这个程序的作用是从命令行输入两个参数,这两个参数分别代表,需要复制的文件名、复制到新创建的文件名。

2,BUFSIZ,来自stdio.h,代表每次读取到缓冲区数据的大小。

3,creat的格式申明如下:

int creat(char *name,int perms);

这个第一个参数比较好理解,代表文件名。

perms则比较复杂,代表创建文件权限。每个文件对应一个9比特位的权限信息(读,写和执行访问),前三位代表文件所有者的对该文件的操作权限,中间三位代表所有者组的权限,后三位代表其他成员的权限。而八进制1位正好代表二进制3位,所以0755这个数字中,0代表八进制,7代表二进制111,5代表101,列个表出来。

    读   写   执行
7   1    1    1
5   1    0    1
5   1    0    1

1代表有权限,0代表没得该项权限。这种方式的权限设计是unix的特色,其实也可以应用于现在的企业应用系统之中。

4,va_list,va_start,va_end,vfprintf函数。前面三个函数都是为vfprintf服务的,而vfprintf函数与fprintf函数类似,只是参数形式不同,它按照字符串fmt要求的格式,把args的值挨个赋进去。要理清va_list,va_start,va_arg,va_end的关系,可以参看下面的代码:

void minprintf(char *fmt,...){
	va_list ap;
	char *p,*sval;
	int ival;
	double dval;
	
	va_start(ap,fmt);
	for(p = fmt;*p;p++){
		if(*p != '%'){
			putchar(*p);
			continue;
		}
		switch(* ++p){
			case 'd':
				ival = va_arg(ap,int);
				printf("%d",ival);
				break;
			case 'f':
				dval = va_arg(ap,int);
				printf("%d",dval);
				break;
			case 's':
				for(sval = va_arg(ap,char *); *sval;sval++){
					putchar(*sval);
				}
				break;
			default:
				putchar(*p);
				break;
		}
	}
	va_end(ap);
}

这个代码是简略版的printf。

va_list用于声明一个变量,该变量将依次引用各参数,本质上它一是指向字符的指针。

typedef char * va_list; 

va_start将使va_list变量指向第一个无名参数。

va_arg,每次调用该函数,都将返回一个相应类型(根据第二个参数而定)的值,并将va_list指向下一个参数。

va_end,清理回收,其实就是将va_list定义的变量值为0(NULL)。

转载于:https://my.oschina.net/moluyingxing/blog/832075

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值