我们已经熟悉了通过键盘和显示器进行输入输出的一些函数,如scanf(),printf()等等,这些通过控制台(键盘、显示器等)进行I/O的 *** 作,可以看作标准文件输入输出系统的一些特例,实际上在标准输入输出系统中的一些函数,有关文件的参数(文件结构指针或称流指针),只要用标准设备的流指针代替,这些标准输入输出函数即成为控制台I/O函数。在任何程序执行时,C系统都定义了5个标准设备文件可供使用。自动打开的5个标准设备文件的文件结构指针(在标准I/O系统中)和文件代号将有一个规定值:
设备 标准文件I/O系统中的流指针名 非标准文件……
键盘(标准输入) stdin 0
显示器(标准输出) stdout1
显示器(标准错误) stderr2
串行口(标准辅助) stdoux3
打印机(标准打印) stdprn4
这样,不论在标准文件系统还是非标准文件系统中,文件结构只要用上述的流指针或文件代号代替,则这些函数也均适用于控制台设备。
一、文本流和二进制流
在C中引入了流(stream)的概念。它将数据的输入输出看作是数据的流入和流出,这样不管是磁盘文件或者是物理设备(打印机、显示器、键盘等),都可看作一种流的源和目的,视他们为同一种东西,而不管其具体的物理结构,即对他们的 *** 作,就是数据的流入和流出。这种把数据的输入输出 *** 作对象,抽象化为一种流,而不管它的具体结构的方法很有利于编程,而涉及流的输出 *** 作函数可用于各种对象,与其具体的实体无关,即具有通用性。
在C中流可分为两大类,即文本流(text stream)和二进制流(binary stream)。所谓文本流是指在流中流动的数据是以字符形式出现。在文本流中,\'\\n\'被换成回车CR和换行LF的代码0DH和0AH。而当输出时,则0DH和0AH本换成\'\\n\'。
二进制流是指流动的是二进制数字序列,若流中有字符,则用一个字节的二进制ASCII码表示,若是数字,则用一个字节的二进制数表示。在流入流出时,对\\n符号不进行变换。例如2001这个数,在文本流中用其ASCII码表示为:
\'2\' \'0\' \'0\' \'1\'
| | | |
50 48 48 49
共占4字节。而在二进制流中则表示为:00000111 11010001 用十六进制就是07D1。只占两字节。
由此看出,二进制流比文本流节省空间,且不用进行对\\n的转换,这样可以大谈或大加快流的速度,提高效率。因而,对于含有大量数字信息的数字流,可以采用二进制流的方式;对于含有大量字符信息的流,则采用文本流的方式。
二、流和文件
在C语言中流就是一种文件形式,它实际上就表示一个文件或设备(从广义上讲,设备也是一种文件)。把流当作文件总觉得不习惯,因而有人称这种和流等同的文件为流式文件,流的输入输出也称为含镇伍文件的输入输出 *** 作。当流到磁盘而成为文件时,意味着要启动磁盘写入 *** 作,这样流入一个字符(文本流)或流入一个字节(二进制流)均要启动磁盘 *** 作,将大大降低传输效率(磁盘是慢速设备),且降低磁盘的使用寿命。为此,C语言在输入输出的使用使用了缓冲技术,即在内存为输入的磁盘文件开辟了一个缓冲区(缺省为512字节),当流到该缓冲区装满后,再启动磁盘一次,将缓冲区内容装到磁盘文件中去。读取文件也是类似。
在C语言中将此种文件输入输出 *** 作称为标准输入输出,或称流式输入输出(因这种输入输出 *** 作是ANSI C推荐的标准)。还有一种是不带缓冲文件输入输出,称为非标准文件输入输出或低级输入输出,它将由DOS直接管理。关于这两种输入输出文件系统下节将会介绍。
三、文件FILE的数据结构
typedef struct
{
short level
unsigned flags
char fd
unsigned char hold
short bsize
unsigned char *buffer
unsigned char *curp
unsigned istemp
short token
}FILE
这是Turbo C中使用的定义(在stdio.h文件中),不同的C编译器,可能使用不同的定义,但基本含义变化不会太大。
flags: 是一个10位的标志字,其具体含义如下:
位 代表符号 含义
0 _F_READ读
1 _F_WRIT写
2 _F_BUF 由fclose释放缓冲区
3 _F_LBUF行缓冲
4 _F_ERR 出错标志
5 _F_EOF EOF文件尾标志
6 _F_BIN 二进制方式
7 _F_IN 在进行输入
8 _F_OUT 在进行输出
9 _F_TERM文件是一个终端
其他各字段内容以及flags字段内各位所的功能,请参照其他一些资料。这里不多说了,它目前并不是我们要求的内容。
应该注意,不要把文件指针和FILE结构指针混为一谈,它们代表两个不同的地址。文件指针指出了对文件当前读写的数据位置,而FILE结构指针是指出了打开文件所对应的FILE结构在内存中的地址,这个指针它实际本身也包含了文件指针的信息。流指针中的各字段是供C语言内部使用的,用户不应该存取它的任何字段。
第二个问题:1、gets(str)
是从缓冲区中读取字符串,然后保存到数组str中直到遇到回车符,换行符不作为字符串的内容,读取的换行符会转换为NULL值,由此标志程序的结束。
2、cin.getline(char*line,int size,char ='"n')是读入一行字符,第二个参数是本次读取的最大字符个数,第三个参数是分隔字符,作为读取一行结束的标志,默认是\n。
3、cin.get()第一个用法,是读入一个字符。 cin.get()第二个用法,也是输入一行(同cin.getline()),但是区别就是,不输出分隔符
补充一下:
cin.getline() 与 cin>>str 的一个不同是,前者输入一行,行中可以包含空格,后者却以空格或回车作为字串结束,不包含空格。
补充:get() 和getline()的异同
1)相同点:
要获取一行的输入,标准流类的成员函数getline(),get()都有三个参数,比如getline(char*line,int size,char ='\n')。其中第一个参数指向存储结果字符的缓冲区指针,第二个表示缓冲区大小(本次读取的最大字符个数,不能够超过其限度),第三个表示知道什么时候停止读输入的终止符(读取一行结束的标志)。终止符有一个经常用到的缺省值"\n"。两个函数遇到输入终止符时,都把零储存在结果缓冲区里。
2)不同点:
1.一般来讲,get()一次读入一个字符,getline()一次读入一行字符
2.在处理字符串时,get()遇到输入流的分隔符时就停止,而不从输入流中提取分隔符。比如用cin.get(myarray1,20,'*')处理字符串1111*2222,碰到*就停止。cout<<myarray1会输出1111。然后再调用cin.get(ch1),cout<<ch1输出的还是这个分隔符*。getline()与其相反,它从输入流中提取分隔符,但仍没有把它储存在结果缓冲区里。如果用cin.getline(myarray2,20,'*')处理上面同样的字符串1111*2222,碰到*停止。 cout<<myarray2会输出1111。然后再调用cin.get(ch2),cout<<ch2输出的是分隔符后面的2。
3)代码演示:
#include <iostream>
#include <iomanip>
using namespace std
void main()
{
char myarray1[20],myarray2[20]
cin.get(myarray1,20,'*')
cout<<myarray1
char ch1
cin.get(ch1)
cout<<ch1
cin.getline(myarray2,20,'*')
cout<<myarray2
cin.get(ch1)
cout<<ch1
}
4)read 函数和 write函数
最近开始从事搜索引擎的工作,所以又重新开始了c/c++的旅程,时隔4年
不得不复习一下c/c++其中的内容,以下内容有网上别的朋友发表的,也有我自己总结的.
1. read
#include
ssize_t read(int filedes, void *buf, size_t nbytes)
返回值:读取到的字节数;0(读到 EOF);-1(出错)
read 函数从 filedes 指定的已打开文件中读取 nbytes 字节到 buf 中。以下几种情况会导致读取到的字节数小于 nbytes :
A. 读取普通文件时,读到文件末尾还不够 nbytes 字节。例如:如果文件只有 30 字节,而我们想读取 100
字节,那么实际读到的只有 30 字节,read 函数返回 30 。此时再使罩旦用 read 函数作用于这个文件会导致 read 返回 0 。
B. 从终端设备(terminal device)读取时,一般情况下每次只能读取一行。
C. 从网络读取时,网络缓存可能导致读取的字节数小于 nbytes 字节。
D. 读取 pipe 或者拿闷野 FIFO 时,pipe 或 FIFO 里的字节数可能小于 nbytes 。
E. 从面向记录(record-oriented)的设备读取时消喊,某些面向记录的设备(如磁带)每次最多只能返回一个记录。
F. 在读取了部分数据时被信号中断。
读 *** 作始于 cfo 。在成功返回之前,cfo 增加,增量为实际读取到的字节数。
2. write
#include
ssize_t write(int filedes, const void *buf, size_t nbytes)
返回值:写入文件的字节数(成功);-1(出错)
write 函数向 filedes 中写入 nbytes 字节数据,数据来源为 buf 。返回值一般总是等于 nbytes,否则就是出错了。常见的出错原因是磁盘空间满了或者超过了文件大小限制。
对于普通文件,写 *** 作始于 cfo 。如果打开文件时使用了 O_APPEND,则每次写 *** 作都将数据写入文件末尾。成功写入后,cfo 增加,增量为实际写入的字节数。
From : antigloss
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)