程序相关概念
1.缓冲区
- 缓冲区又称为缓存,它是内存空间的一部分。也就是说,在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或输出的数据,这部分预留的空间就叫做缓冲区。
- 它用在输入输出设备和CPU之间,用来缓存数据。它使得低速的输入输出设备和高速的CPU能够协调工作,避免低速的输入输出设备占用CPU,解放出CPU,使其能够高效率工作。
- 通常从磁盘里取信息,我们先把读出的数据放在缓冲区,计算机再直接从缓冲区中取数据,等缓冲区的数据取完后再去磁盘中读取,这样就可以减少磁盘的读写次数,再加上计算机对缓冲区的操作大大快于对磁盘的操作,故应用缓冲区可大大提高计算机的运行速度。
2.文件
- 文件通常是在磁盘或固态硬盘上的一段已命名的存储区
- C把文件看作是一系列连续的字符,每个字节都能被单独读取,这与UNIX环境中的文件结构相对应,因其他环境无法完全对应这个模型,
- 为了规范文本文件的处理,C提供两种文件模式进行访问文件:文本模式和二进制模式
- 所有文件的内容都以二进制形式存储
-
- 如果文件最初使用二进制编码的字符(ASCII、Unicode)表示文本,该文件就是文本文件,其中包含文本内容,文本模式中,程序所见的内容和文件的实际内容不同,程序以文本模式读取文件时,把本地环境表示的行末尾或文件结尾映射为C语言模式;
- 如果文件中的二进制值代表机器语言代码或数值数据或图片或音乐编码,该文件就是二进制文件,其中包含二进制内容,二进制模式中,程序可以访问文件的每个字节;
1 //UNIX系统只有一种文件模式 2 //MS-DOS系统中文本文件以\r\n表示换行 3 4 //程序读文件时要能检测文件的末尾才能知道应在何处停止,文件末尾放一个特殊的字符标记文件结尾,现在一般大部分使用Ctrl+Z字符来标记。 5 一文本内容:Reboot the loader 6 7
8 若以二进制模式打开,所看到的内容为:
Reboot the loader\r\n //程序读取的字符是Ctrl+Z时返回EOF(end-of-file) ^z
9 10
11 12 若以文本模式打开,所看到的内容为:
Reboot the loader\n //C的输入函数内置了文件结尾检测器
3.流
文件本质上是磁盘上一段已命名的存储区,通过I/O设备(键盘/显示屏)输入/输出的内容也是存储区(缓存)中一段字符数据,故相对计算机操作系统而言,也可以视为文件,我们称对输入输出的数据的处理过程成为流;
一个流就是一个字符序列,随着时间的推移,字符是顺序生成或消耗的。
注意,流是从I/O设备读出或写入IO设备,从概念上来说,打开文件的过程就是把字符数据和流关联起来,利用流来完成读写操作;
4.标准库
标准C/C++语言没有提供调用无缓冲输入的标准方式,没有定义任何输入输出语句,取而代之的是包含了一个全面的标准库来提供IO机制(及很多其他设施);
5.头文件
5.1概念
是一种包含功能函数、数据接口声明的载体文件,主要用于保存程序的声明,对各个功能函数/接口给出具体描述信息,保证了各函数/接口定义的冲突,也保证程序所调用的功能接口/函数能够复用;
头文件是用户应用程序和函数库之间的桥梁和纽带。在整个软件中,头文件不是最重要的部分,但它是C/C++语言中不可缺少的组成部分。编译时,编译器通过头文件找到对应的函数库,进而把已引用函数的实际内容导出来代替原有函数。进而在硬件层面实现功能。
5.2组成
C/C++程序的头文件以“.h”为后缀,用预处理指令 #include 来引用库的头文件。有些函数的使用不需要提供头文件,但是在ISO/ANSI C已经对有些函数的使用必须提供哪些头文件制定了标准。
头文件最常用的形式:
- 明示常量
- 宏函数
- 函数声明
- 结构模板定义
- 类型定义
5.3语法
1 #include <stdio.h> //文件名在尖括号中,告诉预处理器在标准系统目录中查找该文件 2 #include "mystuff.h" //文件名在双引号中,告诉预处理器在当前工作目录中查找该文件
C语言:
- stdio.h头文件和C库的标准包定义了标准高级I/O,C标准建立了可移植的I/O模型
- C程序会自动打开3个文件,分别称为标准输入、标准输出、标准错误输出
- 默认情况下标准输入(stdin)是系统的普通输入设备,通常是键盘
- 标准输出(stdout)和标准错误(stderr)输出是系统普通的输出设备,通常是显示屏
- 标准错误输出是指一个在逻辑上由不同地方发送过来的消息(逻辑错误)
- C语言的输入输出通过调用函数scanf()和printf()实现;
1 #include <stdio.h> 2 int main() 3 { 4 printf("%s\n", "Hello World!"); 5 return 0; 6 }
C++:
- 标准C++库的iostream库,包含了两个基础类型:istream和ostream,分别表示输入流和输出流
- 标准库定义了4个IO对象:
- 为了处理输入,使用cin的istream类型的对象,称为标准输入;用于读取输入的数据到流中,使用输入运算符 >> ;
- 对于输出,使用cout的ostream类型对象,称为标准输出;用于从流中读取数据输出到显示设备中,使用输出运算符号 << ;
- 对于输出警告和错误消息,使用cerr,称为标准错误,使用clog输出程序运行时的一般性信息
1 #include <iostream> 2 int main() 3 { 4 std::cout << "Hello World!" << std::endl; 5 return 0; 6 }
6.演示缓冲区
6.1缓冲区的类型
缓冲区根据其对应的是输入设备还是输出设备,分为输入缓冲区和输出缓冲区。
- 全缓冲:在这种情况下,当填满标准I/O缓存后才进行实际I/O操作。全缓冲的典型代表是对磁盘文件的读写。
- 行缓冲:在这种情况下,当在输入和输出中遇到换行符时,执行真正的I/O操作。这时,我们输入的字符先存放在缓冲区,等按下回车键换行时才进行实际的I/O操作。典型代表是键盘输入数据。
- 不带缓冲:也就是不进行缓冲,标准出错情况stderr是典型代表,这使得出错信息可以直接尽快地显示出来。
6.2缓冲区的刷新
由6.1可知,下列情况发生之一会引发缓冲区的刷新:
- 缓冲区满时;
- 执行flush语句;
- 执行endl语句;
- 关闭文件。
可见,缓冲区满或关闭文件时都会刷新缓冲区,进行真正的I/O操作。另外,在C++中,我们可以使用flush函数来刷新缓冲区(执行I/O操作并清空缓冲区)
1 //读取输入并输出的缓冲区数据并一直持续到输入端模拟文件结尾 2 //每次按下Enter键系统会处理缓冲区中存储的字符并在下一行打印输入行的副本 3 #include <stdio.h> 4 int main(void) 5 { 6 int ch; 7 while ((ch = getchar()) != EOF) 8 { 9 putchar(ch); 10 } 11 return 0; 12 } 13 // UNIX/Linux系统EOF标识符输入 :Ctrl+D 14 // MS-DOS/Windows系统EOF输入 :Ctrl+Z
Written at : 2018.06.15 -Modified : 2018.06.16 重新排版,增加缓冲区的示例代码;