Linux 标准IO

应用层

一、介绍

1.标准IO库的所有操作都是围绕流(strem)来实现的;
FILE * 流指针,文件指针
2./dev 目录下

stderr  2 //标准出错文件
stdout  1 //标准输出文件
stdin   0 //标准输入文件

二、库函数使用

1.printf() 家族,调用 stdio.h头文件

stdio.h

#include <stdio.h>

       int printf(const char *format, ...);
       int fprintf(FILE *stream, const char *format, ...);//把字符输出到流
			例如:
			fprintf(stdout,"hello world\n");
			fprintf(stderr,"hello world\n"):
			fprintf(stdout,"a=%d\n",a);//带参数
			
       int dprintf(int fd, const char *format, ...);
       int sprintf(char *str, const char *format, ...);//向字符串中写入,
       		例:
       		sprintf(buf,"hello world  %f\n",3.14);
       
       int snprintf(char *str, size_t size, const char *format, ...);

       #include <stdarg.h>

       int vprintf(const char *format, va_list ap);
       int vfprintf(FILE *stream, const char *format, va_list ap);
       int vdprintf(int fd, const char *format, va_list ap);
       int vsprintf(char *str, const char *format, va_list ap);
       int vsnprintf(char *str, size_t size, const char *format, va_list ap);

//返回值
成功返回后,这些函数返回打印的字符数(不包括用于结束输出到字符串的空字节)。
输出错误,则返回负值

2.fclose();关闭流,可以是标准输入输出、出错流,也可以是打开的文件流

   int fclose(FILE *stream);
//返回值
RETURN VALUE
       Upon  successful  completion  0 is returned.  Otherwise, EOF is returned and errno is
       set to indicate the error.  In either case any further access (including another call
       to fclose()) to the stream results in undefined behavior.
       成功完成后返回O。否则,将返回EOF并设置errno以指示错误。在这两种情况下,对流的任何进一步访问(包括对fclose()的另一个调用)都会导致未定义的行为。

关闭输出流,则无法输出

fclose(stdout);
fprintf(stdout,"hello world\n");//

2.标准IO 中的缓冲机制

scanf();函数在缓冲区读取字符,当输入字符最后一个回车键(\n)没有输入,依然保存在缓冲区,需要使用getchar();取走回车键的字符,不然会在下一次输入时,上次留下的回车键读入。
解决这个问题,在多个scanf()函数中间添加getchar();

(1)在内存空间中预留了一定的存储空间,这用来缓冲输入或输出的数据。

FILE *fp=stdin;//大小为1024字节

char a=getchar();//需要设置输入
fp->IO_buf_end //输入缓冲区尾部指针
fp->IO_buf_base //输入患处区头部指针

(2)缓冲区的分类
1)全缓存[4096字节],输入输出是对文件操作;

./a.out >log.txt//当输出的字符少于4096时,无法输出,大于该值则输出

2)行缓存【1024字节】,输入输出是对屏幕操作;
特点:
遇到\n会刷新,缓冲满了会刷新,程序正常结束会刷新【调用exit或从main函数返回】
调用fflush()会强制刷新缓存;遇到\n会刷新缓存。

main()
{
	for(i=1;i<=200;i++)
	{
		printf("A");
	}
	while(1);
}
//执行该程序,未能在输出栏看到输出数据,以为输出的内容在缓冲区,并且未达到刷新缓冲区的要求,所以看不到,当设置i<1024时就可以输出,或者最后输出地方添加\n,fflush()函数。
fflush(stdout);
或者使用 putchuar('\n');

3. int main(int argc,const char *argc[])函数参数

int main(int argc,const char * argv[])
{

}
argc :输入参数的个数
argv[]: 输入参数的数组
		argv[0]  :执行文件的名字
		argv[1]  :执行文件 后第一参数
		

4. fopen()函数,打开文件,返回一个文件指针

FILE *fopen(const char *path,const char *mode);
//返回值为一个文件指针,
	返回NULL则表示打开出错
//const char *path  文件地址,是一个字符串
//const char *mode  打开文件的方式
		打开文件方式
		"r"  :只读打开,不能修改文件
		"r+" :读写方式打开,没有文件报错
		"w"  :只写打开,没有文件创造文件,有内容则清空重写
		"w+" :读写打开,没有文件创造文件,有内容则清空重写;
		"a"  :追加方式打开,没有文件创造文件;
		"a+" :追加读写方式打开,没有文件创造文件,读从文件开头开始读,写从文件结尾的位置写

5. errno 错误码

vim -t EIO //查看错误码
errno //全局错误码使用errno.h 
man 3 perror
打印错误码
printf("%d",errno);

perror("Fail to open");自动把系统错误打印在后面
自动添加  :错误信息

5.strerror();//返回值是错误信息的字符串

打印错误信息
printf("%s",strerror(errno));//函数内传入错误码,打印错误信息

使用标准IO把字符写入文件(1)

#include<stdio.h>
#include<error.h>
#include<string.h>

int main(int argc,const char* argv[])
{
	FILE *fp=NULL;
	if(artc!=2)
	{
		fprintf(stderr,"usage: %s log.txt\n",argv[0]);//如果没有给文件名,则报错
		return -1;
	}
	//读写打开
	fp=fopen(argv[1],"r+);
	if(NULL==fp)
	{
		fprintf(stderr,"Fail to fopen %s\n",strerror(errno));
		return -1;
	}
	fprintf(fp,"hello world!\n");//把字符串写入文件指针中
	
	//关闭文件
	fclose(fp);
	return 0;
}

6.fputc(FILE *stream); //单字符输入输出

 #include <stdio.h>

       int fputc(int c, FILE *stream);

       int fputs(const char *s, FILE *stream);

       int putc(int c, FILE *stream);

       int putchar(int c);

       int puts(const char *s);
       

int fgetc(FILE *stream);//从流读出字符

       char *fgets(char *s, int size, FILE *stream);

       int getc(FILE *stream);

       int getchar(void);

       int ungetc(int c, FILE *stream);


读取文件,把文件内容打印在终端。(类似cat命令)

#include<stdio.h>

int main(int argc,const char * argv[])
{
	FILE *fp=NULL;
	int ch;
	if(artc!=2)
	{
		fprintf(stderr,"usage: %s log.txt\n",argv[0]);//如果没有给文件名,则报错
		return -1;
	}
	//读写打开
	fp=fopen(argv[1],"r+");
	if(NULL==fp)
	{
		fprintf(stderr,"Fail to fopen %s\n",strerror(errno));
		return -1;
	}
	
	while(1)
	{
		ch=fgetc(fp);
		if(ch==EOF)
		{
			break;
		}
		fputc(ch,stdout);
	}
	fclose(fp);
	return 0;
		
}

7.char *fgets(char *s, int size, FILE *stream);//最多获取字符数比size少一个,最后要加一个\0 //按行读取

从流中读取size-1个字符,写入指针s所指地址,在EOF 或者换行符后停止读取,如果读取了换行符,则将其存储到缓冲区。
返回值:成功返回s的地址,失败或者读到文件末尾返回NULL;

  #include <stdio.h>

       int fgetc(FILE *stream);

       char *fgets(char *s, int size, FILE *stream);//最多获取字符数比size少一个,最后要加一个\0

       int getc(FILE *stream);

       int getchar(void);

       int ungetc(int c, FILE *stream);

8. int fputs(const char *s, FILE *stream); //把字符串输入流中,遇到’\0’就结束。

  #include <stdio.h>

       int fputc(int c, FILE *stream);

       int fputs(const char *s, FILE *stream);

       int putc(int c, FILE *stream);

       int putchar(int c);

       int puts(const char *s);

//示例:向文件中输入

FILE *fp=NULL;
char buf{100]={0};

fp=fopen("log.txt","w");
if(fp==NULL)
{
	perror("Fail to fopen!");
	return -1
}
strcpy(buf,"hello world");

int ret=fputs(buf,fp);
if(ret<0)//EOF=-1
{
	perror("Fail to fputs");
	return -1;
}
close(fp);

//return value:返回值

		//fputc(), putc() and putchar() return the character written as an unsigned char cast to an int or EOF on error. EOF 在 /usr/include/stdio.h  宏定义为-1
		

    //   puts() and fputs() return a nonnegative number on success, or EOF on error.

在这里插入图片描述
//示例:当输入 quit 时退出

#include<stdio.h>
#include<strings.h>
#include<string.h>

int main(int argc,const char *argv[])
{
	char buf[120]={0}while(1)
	{
		bzero(buf,sizeof(buf));
		putchar('>');
		fgets(buf,sizeof(buf),stdin);
		if(strncmp(buf,"quit",4)==0)
		{
			break;
		}
		fputs(buf,stdout);
		
	}
	return 0;
}

9.统计行数 命令行【 wc -l 文件名 获得文件的行数,-w 单词个数 -c 大小 】

//

#include<stdio.h>

int getLine(FILE *fp)
{
	char buf[1024]={0};
	int line=0;
	while(fgets(buf,sizeof(buf),fp)!=NULL)//当没有读到文件尾部的时候,继续读
	{
		if(buf[strlen(buf)-1]=='\n')
		{
			line++; 
		}
		memset(buf,0,sizeof(buf));
		
	}
	return line;
}
int main(int argc,const char *argv[])
{
	FILE *fp;
	int line=0;
	if(argc!=2)
	{
		perror(stderr,"Usage: %s log.txt",argv[0]);
		return -1;
	}
	fp=fopen(argv[1],"r");
	if(NULL==fp)
	{
		perror("Fail to fopen");
		return -1;
	}
	line=getLine(fp);
	printf("%s:%d\n",argv[1],line);
	fclose();
	return 0;
}

10. size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);//从文件流指针读,写入ptr指向的数据缓冲区

size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);从ptr指向的缓冲区写入文件流指针。

//返回值:成功返回读取的个数

//示例:把结构体写入文件[od -c 文件名 //可以查看文件的结构]

#include<stdio.h>

struct student
{
	char name[20];
	int id;
	int score;
};
int main(int argc,const char *argv[])
{
	FILE *fp;
	struct student stu={"jack",1,100);//给结构体赋值
	
	if(argc!=2)
	{
		perror(stderr,"Usage: %s log.txt",argv[0]);
		return -1;
	}
	fp=fopen(argv[1],"w");
	if(fp==NULL)
	{
		perror("Fail to fopen");
		return -1;
	}
	fwrite(&stu,sizeof(stu),1,fp);//1是写入数据的个数
	fclose(fp);
	return 0;
}

11. int fseek(FILE *stream, long offset, int whence);//定位读文件光标的位置

//参数:whence 光标相对偏移起点:SEEK_SET 以文件开头为起点;SEEK_CUR 当前位置为偏移起点;SEEK_END 文件结尾为偏移起点;
//参数:offset >0 则向后偏移,<0 向前偏移
//返回值:成功返回0,失败返回-1,置errno

 #include <stdio.h>

       int fseek(FILE *stream, long offset, int whence);

       long ftell(FILE *stream);//返回当前光标的位置

       void rewind(FILE *stream);//将光标定位到文件开头

       int fgetpos(FILE *stream, fpos_t *pos);
       int fsetpos(FILE *stream, const fpos_t *pos);

//示例:移动文件光标//文件开头为0

fseek(fp,4,SEEK_SET);//定位到文件开头往后数4bytes的位置
fseek(fp,-4,SEEK_END);//定位到文件末尾往前数4bytes的位置
fseek(fp,10,SEEK_END);//将文件的大小扩充10bytes

把光标定位到开头

fseek(fp,0,SEEK_SET);//和rewind 等价
rewind(fp);//该函数和上个函数等价
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jun8086

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值