C语言的输入、输出流

1. 标准输入输出

标准输入、输出主要由缓冲区和操作方法两部分组。缓冲区实际上可以看做内存中的字符串数组,而操作方法主要是指printf、scanf、puts、gets,getcha、putcahr等操作缓冲区的方法。在C++以及Java等面向对象的编程语言中,将缓冲区以及操作缓冲区的方法封装成一类对象,这类对象就称为流。

缓冲区最大的特点主要体现在数据的一次性,即数据被printf、scanf从缓冲区中取出后就被使用了,或者说消耗了。可以把缓冲区比喻成管道,缓冲区中的数据比喻成水流,printf、scanf等方法比喻成开关,当打开开关,水就会慢慢流逝,而流出去的水就再也收不回来了。

由于不同系统,不的硬件底层实现输入输出的具体方法可能不一样,C语言要求系统为每个程序提供两个指针,这两个指针分别指向两个结构体,这两个结构体分别表示了键盘和屏幕在内存中的抽象表示(缓冲区的地址值被记录在这个结构体中),并将指向这两个结构体的指针命名为stdin和 stdout.这两个指针就是所谓的标准输入和标准输出。

还有一点应该始终铭记,标准输入和输出缓冲区中存储的是字符的ASCII码值。比如你想从键盘上输入了123给一个变量,那么在缓冲区中存储是三个字节,分别是字符‘1’的ASCII码值,字符‘2’的ASCII码值,字符‘3’的ASCII码值,然后将这个这三个ASCII值序列转换为一个数值给这个变量。同理,从屏幕输出“123”,计算机并不认为它输出的是一个数值,计算机实际上仅仅是描绘了一个‘1’的ASCII码值对应的图形,‘2’的ASCII的值对应的图形,‘3’的ASCII码值对应的图形。

2. getchar、putchar

putchar的作用主要是向输出缓冲区中写入一个字符。

getchar的作用主要是向输入缓冲区中读取一个字符。如果碰到文件结尾,返回-1

getchar源代码

int getchar(void){
	static char buf[BUFSIZ];
	static char* bb = buf;
	static int n = 0;
	if (n == 0)
	{
		n = read(0, buf, BUFSIZ);
		bb = buf;
	}
	return(--n >= 0) ? (unsigned char)*bb++ : EOF;
}

OEF是一个宏,表示-1。getchar的返回值是int,对于文件来说-1表示了文件的结尾。我们可以在键盘上利用Ctrl+Z来实现类似的效果

从getchar的源代码中可以看出,如果发现字符数组buf已空(n==0),则调用read方法从键盘读取数据(该方法会导致阻塞),并让指针指向数组的首地址。如果缓冲区还有字符没有被读取(n > 0),则读取它,同时n-1,指针(bb)向后移动一位。当缓冲区已空(n==0),且read函数读取失败时(读取到了文件末尾),返回EOF。

从scanf的源代码中可以看出getchar可以读入任何字符,包括空白符(空白符包括:空格、换行符、制表符等)。

3. gets、puts

puts函数主要向输出缓冲区写入一个字符串,并再字符串输出结束以后,再额外输出一个换行符’\n’

gets用于从输入流的缓冲区中读取字符到指定的数组。读取过程中会忽略所有的前导空白符,读入的第一个字符为非空白符,直到遇到换行符才停止读入,结束的换行符(’\n’)被gets函数读从缓冲区读取走了,存于数组中,然后被替换成’\0’

gets 源代码,只需要看for循环这部分代码,FLOCKFILE(stdin)表示对输入缓冲区加锁对;FUNLOCKFILE(stdin) 表示对输入缓冲区解锁。

char* gets(char *buf){
	int c;
	char *s;
	static int warned;
	static const char w[] =
	"warning: this program uses gets(), which is unsafe.\n";

	FLOCKFILE(stdin);
	ORIENT(stdin, -1);
	if (!warned) {
		(void)_write(STDERR_FILENO, w, sizeof(w) - 1);
		warned = 1;
	}
	for (s = buf; (c = __sgetc(stdin)) != ‘\n‘;)
		if (c == EOF)
			if (s == buf) {
				FUNLOCKFILE(stdin);
				return (NULL);
			}
			else
				break;
		else
			*s++ = c;
	*s = 0;
	FUNLOCKFILE(stdin);
	return (buf);
}

从源代码可以看出,如果读入了‘\n’则停止,并替换成‘\0’

4. printf的使用

定义函数 int printf(const char * format,...);

函数说明 printf()会根据参数format字符串来转换并格式化数据,然后将结果写出到标准输出设备,直到出现字符串结束(‘\0‘)为止。

参数format字符串可包含下列三种字符类型:

(1)一般文本,伴随直接输出。

(2)转义字符,如\t、\n等。

(3)格式转换字符,格式转换为一个百分比符号(%)及其后的格式字符所组成。一般而言,每个%符号在其后都必需有一printf的参数与之相呼应(只有当%%转换字符出现时会直接输出%字符)

格式转换字符详解 “%[符号][宽度][.精度]类型”

[宽度]:表示最少输出的字符个数

[符号]:“-”表示对齐方式

(1)%-8,左对齐,当显示字符不足8时,右补空格

(2)%08,右对齐,当显示字符不足8时,左补0

[.精度]对于浮点数表示小数点后的位数

数值小数点后的位数大于显示精度,则只能显示[.精度]个小树位数(四舍五入),如果数值小数点后的位数小于显示精度,则补零。

%.5 小数点后显示5位

类型

(1)%d:用于显示十进制有符号数,char,short,int,long long

(2)%u:用于显示十进制无符号数,unsinged short,unsigned int,

unsigned long long

(3)%x: 用于显示十六进制整数,所有有符号及无符号整型

(4)%f:用于显示十进制浮点数,float,double

(5)%c:显示字符

(6)%s:显示字符串

printf(“%s”,xxx)puts(xxx)的区别:puts函数会自动添加换行,而printf(“%s”,……)不会。

5. scanf的使用

定义函数 int scanf(const char * format,...);

函数说明 scanf()会将输入的数据根据参数format字符串来转换并格式化数据。Scanf()格式转换的一般形式如下:

“%[宽度][数据所占字节数]输入类型”

[宽度]:最多输入的字符个数

[数据类型]:

h表示两字节,short

l表示八字节,用于long long和 double

什么都没有表示四字节

[数据类型]输入类型

(1)%d:int

(2)%f:float

(3)%lf:double

(4)%hd:short

scanf(“%c”,&x) 等价于 x = getchar()

//虽然getchar的返回值是int类型,但不影响使用

(5)%s:字符串

用scanf读取字符串时,忽略前导的空白符,再次遇到空白符会结束输入,并将再次遇到的空白符留在缓冲区内,自动添加字符串数组的结束标志 ‘\0’。

#include <stdio.h>
void main(int argc, char* argv[]){
	char a[20];
	int ch;
	scanf_s("%s",a,20);
	printf("%s\n", a);
	while ((ch = getchar()) != EOF ){
		putchar(ch);
	}
}

我们输入i love you(ctrl+z)

scanf_s 读取字符i以后结束(i后是空格),通过getchar函数第一个读取的字符就是空格,getchar会一直读取缓冲区中,直到缓冲区为空。

6. fgets、fputs、fscanf、fprintf、fgetchar、fputchar

上述方法只是多了个参数FILE * stream,表示这时的输入以stream指定的文件作为输入或者输出

char* fgets(char* _Buf, int _MaxCount, FILE* _File);

int fputs(const char * _Str,FILE* _File);

int fprintf(FILE* _File, const char * _Format, ...);

int fscanf(FILE* _File, const char * _Format, ...);

int fgetc (FILE* _File) ;

int fputc(int _Ch, FILE* _File);

7. 其它相关函数

int sprintf( char *_Dest, const char * format,...);

函数说明sprintf和printf函数很类似,printf是将结果写入到标准输出流中,而sprintf是将结果写入到字符串数组_Dest中。返回值返回值返回参数str字符串长度,失败则返回-1。

#include<stdio.h>
void main(){
	char* a = "This is string A!";
	char buf[80];
	sprintf_s(buf,"begin %s end\n", a);
	printf("%s",buf);
}

int sscanf_s(const char * _Src, const char * _Format, ...);

sscanf函数与scanf类似,只不过scanf是从输入流中读取数据,而sscanf是从字符串数组_Src中读取数据

#include<stdio.h>
void main(int argc, char* args[]){
	int i;
	double n;
	char str[20] = "123 3.1415";
	sscanf_s(str, "%d%lf", &i, &n);
	printf("%d\n%f\n", i, n);
}

设置流缓冲

int fflush(FILE* stream);

void setbuf(FILE* stream, char* buf);

int setvbuf(FILE* stream, char* buf, int mode);

数据总是先写入(或者读取)到流中,当缓冲区满了后,在将其写入到设备(或者获取读取到程序中),这样的工作方式效率更高。但是有时候我们可能需要更快的相应速度,我们可以调用fflush方法来冲刷缓冲区,注意这里冲刷的意思不是将缓冲区的内容删除,而是将还未满的缓冲区中的内容写入到设备(或者读取到程序中)

setbuf中可以由参数buf自己设定缓冲区的位置和大小(大小由buf数组的大小决定)。

setvbuf中的第三个参数决mode定了缓冲区的缓冲类型。它由三种取值

_IOFBU:全满缓冲类型

_IOLBU:行满缓冲类型

_IONBU:无缓冲类型

时间: 2024-10-13 15:59:17

C语言的输入、输出流的相关文章

c++语言的输入输出流库

1.c++语言标准输入输出流 <1>控制符的用法 #include <iostream> #include <iomanip> using namespace std; int main(){ int x=30,y=300,z=1024; cout<<"Decimal:"<<x<<" "<<y<<" "<<z<<endl;//按

输入输出流

1.什么是IO Java中I/O操作主要是指使用Java进行输入,输出操作. Java所有的I/O机制都是基于数据流进行输入输出,这些数据流表示了字符或者字节数据的流动序列.Java的I/O流提供了读写数据的标准方法.任何Java中表示数据源的对象都会提供以数据流的方式读写它的数据的方法. Java.io是大多数面向数据流的输入/输出类的主要软件包.此外,Java也对块传输提供支持,在核心库 java.nio中采用的便是块IO. 流IO的好处是简单易用,缺点是效率较低.块IO效率很高,但编程比较

Java输入输出流

1.什么是IO Java中I/O操作主要是指使用Java进行输入,输出操作. Java所有的I/O机制都是基于数据流进行输入输出,这些数据流表示了字符或者字节数据的流动序列.Java的I/O流提供了读写数据的标准方法.任何Java中表示数据源的对象都会提供以数据流的方式读写它的数据的方法. Java.io是大多数面向数据流的输入/输出类的主要软件包.此外,Java也对块传输提供支持,在核心库 java.nio中采用的便是块IO. 流IO的好处是简单易用,缺点是效率较低.块IO效率很高,但编程比较

java输入输出流总结 转载

一.基本概念 1.1 什么是IO?     IO(Input/Output)是计算机输入/输出的接口.Java中I/O操作主要是指使用Java进行输入,输出操作.     Java所有的I/O机制都是基于数据流进行输入输出,这些数据流表示了字符或者字节数据的流动序列.      任何Java中表示数据源的对象都会提供以数据流的方式读写它的数据的方法.Java.io是大多数面向数据流的输入/输出类的主要软件包.此外,Java也对块传输提供支持,在核心库 java.nio中采用的便是块IO.    

【转载】Java输入输出流-IO

转自:http://blog.csdn.net/hguisu/article/details/7418161 1.什么是IO Java中I/O操作主要是指使用Java进行输入,输出操作. Java所有的I/O机制都是基于数据流进行输入输出,这些数据流表示了字符或者字节数据的流动序列.Java的I/O流提供了读写数据的标准方法.任何Java中表示数据源的对象都会提供以数据流的方式读写它的数据的方法. Java.io是大多数面向数据流的输入/输出类的主要软件包.此外,Java也对块传输提供支持,在核

输入输出流(I/O)

一.流概述 流是一组有序的数据序列,根据操作的类型,可分为输入流和输出流两种.I/O流提供了―条通道程序,可以使用这条通道把源中的字节序列送到目的地,虽然I/O流经常与磁盘文件存取有关,但是程序的源和目的地也可以是键盘鼠标.内存或显示器窗口等. Java由数据流处理输入输出模式,程序从指向源的输入流中读取源中的数据.源可以是文件.网络.压缩包或者其他数据源. 输出流的指向是数据要到达的目的地,程序通过向输出流中写入数据把信息传递到目的地.输出流的目标可以是文件.网络.压缩包.控制台和其他数据输出

Java中IO流,输入输出流概述与总结

总结的很粗糙,以后时间富裕了好好修改一下. 1:Java语言定义了许多类专门负责各种方式的输入或者输出,这些类都被放在java.io包中.其中, 所有输入流类都是抽象类InputStream(字节输入流),或者抽象类Reader(字符输入流)的子类: 而所有输出流都是抽象类OutputStream(字节输出流)或者Writer(字符输出流)的子类. [首先需要明白的是:流是干什么的???(为了永久性的保存数据)   根据数据流向的不同分为输入流和输出流:   根据处理数据类型的不同分为字符流和字

Java输入输出流的使用详细介绍

出处:http://www.jb51.net/article/36138.htm 1.什么是IO Java中I/O操作主要是指使用Java进行输入,输出操作. Java所有的I/O机制都是基于数据流进行输入输出,这些数据流表示了字符或者字节数据的流动序列.Java的I/O流提供了读写数据的标准方法.任何Java中表示数据源的对象都会提供以数据流的方式读写它的数据的方法. Java.io是大多数面向数据流的输入/输出类的主要软件包.此外,Java也对块传输提供支持,在核心库 java.nio中采用

Java 输入输出流

1.什么是IO Java中I/O操作主要是指使用Java进行输入,输出操作. Java所有的I/O机制都是基于数据流进行输入输出,这些数据流表示了字符或者字节数据的流动序列.Java的I/O流提供了读写数据的标准方法.任何Java中表示数据源的对象都会提供以数据流的方式读写它的数据的方法. Java.io是大多数面向数据流的输入/输出类的主要软件包.此外,Java也对块传输提供支持,在核心库 java.nio中采用的便是块IO. 流IO的好处是简单易用,缺点是效率较低.块IO效率很高,但编程比较

C++输入输出流

输入输出流 1. 用控制符输出格式,例: 1 #include <iostream> 2 #include <iomanip>//利用控制符输出必须包含iomanip头文件 3 using namespace std; 4 int main() 5 {int a; 6 cout<<"input a:"; 7 cin>>a; 8 cout<<"dec:"<<dec<<a<<