C语言编程学习——标准I/O(标准输入输出)

标准I/O:

1.I/O(Input/Output)就是输入与输出的简称.

2.标准I/O是ANSI C标准(C库)中定义的一系列用于I/O操作的函数.编程中,我们只要包含了相对应的头文件(.h)就可以调用我们要使用的标准输入输出函数.

3.标准I/O一般用于终端的输出与输出.

系统调用:

操作系统的主要功能是为管理硬件资源和并且为应用程序和硬件资源之间提供一个既用于阻隔又用于连接的桥梁.为了达到这个目的,操作系统的内核(操作系统的核心部分)提供一系列具备预定功能的内核函数,通过被称为"系统调用"的"编程接口API"供应用程序使用.应用程序将数据通过"系统调用"传递给内核函数,内核函数再将数据传递给硬件处理后,数据通过内核最后返回给应用程序.

"流":

当用标准I/O打开一个文件时,系统会创建一个FILE结构体来描述该文件,我们称这个FILE结构体为"流".之后,所有的I/O操作都围绕这个"流"进行(操作这个流(FILE结构体)就等于直接操作文件本身).

创建"流"的同时,系统会在用户空间创建一个缓存区,在进行实际的I/O操作之前,我们先将数据存储到这个缓存区中,直到达到某个条件,我们才对缓存区中的数据进行实际的I/O读写操作.

因为每一次实际的I/O操作都要使用系统调用,如果不使用标准I/O,系统缓存区也就不存在,那么每读写一个数据就要使用一次系统同调用.这样的话系统使用效率将会大大降低.而如果使用了标准I/O,多个数据首先是保存在系统缓存区中,当条件满足是,我们才一次性的对缓存区中的数据进行实际的I/O读写操作,从而减少了使用系统调用的次数,大幅提升了系统的使用效率.

标准I/O的缓冲类型:

缓存区:

在进行标准输入与输出时,数据并不是直接被函数获取(输入)或者打印显示到终端(输出),而是先保存在一个系统自动分配的缓存区内.当满足一定的条件时,数据才进行实际的I/O(输入输出)操作.

缓冲类型:

全缓冲: 填满缓冲区后才进行实际的I/O操作.

行缓冲: 当输入和输出中遇到换行符时,进行实际的I/O操作.

无缓冲: 不进行数据缓存,直接进行实际的I/O操作.

"流"的打开(创建FILE结构体):

#include <stdio.h> //头文件

FILE *fopen(const char *path,const char *mode); //函数原型

参数 : path : 实参传递的是文件的路径(包括文件名),用一个字符串表示: "****".

这里形参是一个指针常量,指针指向的存储空间中的值不能改变.

mode : 实参传递的是文件的打开方式,用一个字符串表示: "**".

"r" : 以只读方式打开文件,文件必须存在.

"r+" : 以可读写的方式打开文件,文件必须存在.

"w" : 以只写方式打开文件,文件不存在则创建;文件存在则擦除文件中的内容.

"w+" : 以可读写的方式打开文件,文件不存在则创建;文件存在则擦除文件中的内容.

"a" : 以只写方式打开文件,文件不存在则创建;文件存在则新内容从文件内容末尾开始写入.

"a+" : 以可读写方式打开文件,文件不存在则创建,文件存在则新内容从文件内容末尾开始写入.

返回值 : 执行成功返回FILE结构体指针(流指针);出错返回NULL.

编程操作 : FILE *fp; //定义FILE结构体指针变量,这个指针指向的FILE结构体的内存空间是系统自动分配的.

fp = fopen("文件路径","文件打开方式");

注 :操作系统启动时,系统会自动打开三个流: 标准输入流 : stdin ,默认键盘.

标准输出流 : stdout,默认当前终端.

标准错误流 : stderr,默认向当前终端输出错误信息.

流的关闭:

流打开后,如果我们不再使用它,就一定要将其关闭(释放FILE结构体指针变量指向的内存空间).

#include <stdio.h> //头文件

int fclose(FILE *fp); //函数原型

参数 : 打开的流指针fp.

返回值 : 执行成功返回0;出错返回EOF(数值上等于-1).

使用这几个标准I/O时流的打开和关闭都是系统自动完成的.

常用标准输出函数:

按字节输出:向终端输出一个字节(字节).

#include <stdio.h> //头文件

int putchar(int c); //函数原型,在系统头文件中定义.

参数 : c :传递给形参c的实参是一个整型常量\字符型常量\整型变量\字符型变量.;

返回值 : 成功返回输出的字符;出错返回-1.

格式化输出 :

格式化输出就是将数据按照一定的格式输出.

#include <stdio.h> //头文件

int printf(const char *format, ...); //函数原型

参数: format :是一个字符串,用"*****"的形式编写.这个字符串可以同时包含自定义输出信息和格式转换符,如

果没有数据需要格式化输出时,我们就可以只输出自定义信息;反之,我们也可以只格式化输出数据,

而不带自定义输出信息.

... :形参表,传递的实参是与参数format中格式转换符对应的常量或变量.格式转换符与传递的实参是一

一对应的: 实参是何种数据类型,format中就要使用对应的格式转换符;传递的实参有多少个,format

中就要有对应的多少个格式转换符.多个实参之间用','隔开.

返回值 : 成功返回输出的数据字节数;出错返回负数.

缓冲类型: 行缓冲,遇到换行符'\n'才进行实际的I/O操作.我们使用printf函数进行实际数据的输出时,一定不要漏写换行符'\n',不然可能造成数据读写错误.

格式转换符: %d : 格式化输入输出十进制整数.

%u : 格式化输入输出无符号十进制整数.

%o : 格式化输入输出八进制整数.

%x : 格式化输入输出十六进制整数.

%c : 格式化输入输出单个字符.

%s : 格式化输入输出一个字符串.

%f : 格式化输入输出小数形式的十进制浮点数.

%e : 格式化输入输出指数形式的十进制浮点数.

%p : 格式化输入输出十六进制表示形式的指针数据.

格式转换修饰符: 在格式转换符的%右边使用(%ld),对数据的输出格式作进一步的修饰.

n : 整型数n,指定输出整型数据的域宽.实际域宽大于n按实际域宽输出;实际域宽小于n则在数据的左

边补空格,右对齐.

比如: 要输出数据134,若指定域宽n为2,则输出格式为"134";若指定域宽为6,则输出为" 134".

-n: 使用方法跟第一条一样.区别在于若实际域宽小于n,则在数据的右边补空格,左对齐.

0n: 使用方法跟第一条一样.区别在于若实际域宽小于n,则在数据的左边补0,右对齐.

.n: 若输出数据为浮点数,则是指定小数点后的显示位数(四舍五入);若输出数据为字符串,则是指定

实际输出的字符的个数.

l : 不是数字1,是小写字母l.若输出数据是整型数,则是指定输出长整数数据;若输出数据是浮点型,

则是指定输入输出双精度浮点型数据

+ : 在有符号整数前显示正号'+'.

# : 在输出数据前显示前缀: %#o,显示八进制前缀0.%#x,显示十六进制前缀0x

常用标准输入函数:

按字节输入:从终端中获取一个字节(字符).

#include <stdio.h> //头文件

int getchar(void); //函数原型

返回值: 成功返回读取到的字符,出错返回-1.

注: getchar函数一般用于阻塞程序执行(防止程序闪退)或者消除在格式化输入整型数据后,回车符对数据的影响.

格式化输入: 将数据按照一定的格式输入.

#include <stdio.h> //头文件

int scanf(const char *format, ...); //函数原型

参数: format : 是一个字符串,但跟printf函数不同的是,format中只包含格式转换符,不包括自定信息.

... : 形参表,传递的实参是用于接收输入数据的自定义缓存区的地址.其它使用特性(格式)跟printf函数一致.

注: 1.地址涉及到以后要学习的指针部分知识,暂时不做介绍.

2.scanf函数跟printf函数一样,一次可以操作多个数据.但scanf函数操作多个数据使用起来稍微复杂,容易出错.而且操作多个数据的情况也特别少,故我们重点学习如何通过scanf函数进行单个数据的输入.

返回值: 成功返回与指定格式相匹配的数据的个数,当匹配不成功返回值为0;出错返回-1.

缓冲类型: 行缓冲,遇到空格或回车则认为当前数据输入结束.

注: scanf函数对格式转换符和格式转换修饰符的使用与printf函数一样,但scanf函数一般只使用格式转换符,不使用格式转换修饰符.

标准出错函数:

当程序中某个函数执行出错,我们可以通过标准出错函数向终端输出错误信息:

#include <stdio.h> //头文件

#include <errno.h> //头文件

void perror(const char *s); //函数原型

参数: s : 实参是一个自定义字符串,一般填写出错的函数的函数名.

注 : 标准出错函数是无缓冲类型,出错信息直接输出到终端显示.

头文件 : #inlcude <stdio.h>

----------------------------------------------------------------------------------------------

char *gets(char *s); //从标准输入流中读取一行字符,遇到换行符\n才结束读取.

遇到空格继续读取,容易造成自定义缓存区buffer的溢出,不建议使用.

参数 : s : 自定义的用于存储接收到的数据的缓存区buffer.

返回值 : 成功返回自定义缓存区buffer的地址;出错或者标准输入流中没有数据返回NULL.

编程方法 : char *p = NULL;

char a[n]; //自定义缓存区buffer.

p = gets(a);

----------------------------------------------------------------------------------------------

char *fgets(char *s, int size, FILE *stream); //从标准输入流"stream"中读取一行字符,

达到读取的限制大小或者遇到换行符结束读取.

参数 : s : 自定义的用于存储接收到的数据的缓存区buffer.

size : 指定一次获取的字符的个数

stream : 标准输入流stdin.

返回值 : 成功返回自定义缓存区buffer的地址;出错或者标准输入流中没有数据返回NULL.

注 : fgets函数比gets函数要安全.因为不会造成自定义缓存区buffer的溢出.

-----------------------------------------------------------------------------------------------

int puts(const char *s); //向标准输出流中输出一个字符串.

参数 : s : 自定义的用于存储待输出的数据的缓存区buffer.

返回值 : 成功返回非负整数;出错返回EOF.

-----------------------------------------------------------------------------------------------

int fputs(const char *s, FILE *stream); //向标准输出流stream(stdout)中输出一个字符串.

参数 : s : 自定义的用于存储待输出的数据的缓存区buffer.

返回值 : 成功返回非负整数;出错返回EOF.

-----------------------------------------------------------------------------------------------

int fprintf(FILE *stream, const char *format, ...); //实现与printf函数一样的功能.

新增参数 : stream : 标准输出流stdout.

其它属性跟printf函数一样.

-----------------------------------------------------------------------------------------------

int fscanf(FILE *stream, const char *format, ...); //实现与scanf函数一样的功能.

新增参数 : stream : 标准输入流stdin.

其它属性跟scanf函数一样.

-----------------------------------------------------------------------------------------------

使用标准I/O进行文件操作:

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

参数 : ptr : 用于保存从文件流中读取的数据的自定义缓存区buffer.

size : 每个数据的大小.

nmemb : 读取数据的个数.

stream : 打开的文件流指针,数据从流中读取.

返回值 : 成功返回读取到的数据的个数;出错或者到达文件末尾返回0.

-----------------------------------------------------------------------------------------------

size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);

参数 : ptr : 保存了要写入文件流中的数据的自定义缓存区buffer.

size : 每个数据的大小.

nmemb : 写入数据的个数.

stream : 打开的文件流指针,数据写入流中.

返回值 : 成功返回写入的数据的个数;出错返回0.

这些是C/C++能做的 

服务器开发工程师、人工智能、云计算工程师、信息安全(黑客反黑客)、大数据 、数据平台、嵌入式工程师、流媒体服务器、数据控解、图像处理、音频视频开发工程师、游戏服务器、分布式系统、游戏辅助等

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335