C语言的标准输入输出
欢迎探讨,如有错误敬请指正
如需转载,请注明出处 http://www.cnblogs.com/nullzx/
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字符串来转换并格式化数据,然后将结果写出到标准输出设备,直到出现字符串结束('\n')为止。
参数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读取字符串时,忽略前导的空白符,再次遇到空白符会结束输入,并将再次遇到的空白符留在缓冲区内,自动添加字符串数组的结束标志'\n'。
- #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:无缓冲类型
C语言的标准输入输出的更多相关文章
- C/C++ 标准输入输出重定向
转载自:http://www.cnblogs.com/hjslovewcl/archive/2011/01/10/2314356.html 这个对经常在OJ上做题的童鞋们很有用.OJ基本都是用标准输入 ...
- C++之标准输入输出
由于在公司,无法上传图片,往后补上. 关于C++的标准输入输出,其实就相当于C语言的scanf和printf,只不过C++用cin和cout这样称为流的机制. #include <iostrea ...
- Python基础笔记系列十一:标准输入输出、文件读写和指针等操作
本系列教程供个人学习笔记使用,如果您要浏览可能需要其它编程语言基础(如C语言),why?因为我写得烂啊,只有我自己看得懂!! 标准输入输出一.输入 在sublime中这个时候需要安装SublimeRE ...
- Linux学习--第十天--bash脚本、用户自定义变量、环境变量、位置参数变量、预定义变量、标准输入输出、wc、history、dd、PS1
shell简介 分为两种c shell 和b shell b shell:sh.ksh.Bash.psh.zsh: (Bash和sh兼容,linux基本shell是Bash) c shell:csh. ...
- C语言:标准IO_fopen( )、fclose() ①
思前想后一个月,我终于敲下了我的第一篇开山之作. 博客千千万,我的博客首先记录的是学习时候的理解,用于给自己翻阅查找,现在主要研究的是C语言和STM32.如果能帮到你,那是最好的,假如我写的东西有错误 ...
- C语言产生标准正态分布或高斯分布随机数
C语言 产生标准正态分布或高斯分布 随机数 产生正态分布或高斯分布的三种方法: 1. 运用中心极限定理(大数定理) #include #include #define NSUM 25 double g ...
- linux标准输入输出及错误输出
Linux Shell 环境中支持输入输出重定向,用符号"<"和">"来表示. 0.1和2分别表示标准输入.标准输出和标准错误信息输出,可以用来指定 ...
- C语言各种标准的
[K&R C] 1978 年,Dennis Ritchie 和 Brian Kernighan 合作推出了<The C Programming Language>的第一版(按照惯例 ...
- 【转载】标准输入输出重定向(Visual C++)
原文:标准输入输出重定向(Visual C++) 引言 本人偶得在 Visual C++ 中进行输入输出重定向的办法,比通常的做法“freopen”更加的灵活和方便,特在此共享.目前,代码正在不断地摸 ...
随机推荐
- iOS 图片文件格式判断、圆角图片
1.圆角图片 // 设置圆形图片(放到分类中使用) - (UIImage *)cutCircleImage { UIGraphicsBeginImageContextWithOptions(self. ...
- iOS 检测状态栏点击事件
当tableView.scrollsToTop=YES不管用时,可以使用以下方法实现点击状态栏使tableView滚动到顶部. - (void) touchesBegan:(NSSet *)touch ...
- java复习集合类之List接口
List 为有序可重复列表 实现List接口的类主要是ArrayList 下面为ArrayList的测试代码 import java.util.ArrayList; public class demo ...
- 【BZOJ3314】 [Usaco2013 Nov]Crowded Cows 单调队列
第一次写单调队列太垃圾... 左右各扫一遍即可. #include <iostream> #include <cstdio> #include <cstring> ...
- 我的前端故事----优美的编辑器GitHub Atom
很多前端的同学都在用sublime text,我之前也在使用,但是后来接触到了Atom,就被它的高颜值深深的吸引了~~不愧是GitHub的工程师哦~审美就是高 Atom 作为一个跨平台的编辑软件,安 ...
- BZOJ4597: [Shoi2016]随机序列
Description 你的面前有N个数排成一行.分别为A1, A2, … , An.你打算在每相邻的两个 Ai和 Ai+1 间都插入一个加号或者 减号或者乘号.那么一共有 3^(n-1) 种可能的表 ...
- C#详解format函数,各种格式化
一.String Format for Double Digits after decimal point This example formats double to string with fix ...
- 有关JVM配置参数含义
1.参数的含义-vmargs -Xms128M -Xmx512M -XX:PermSize=64M -XX:MaxPermSize=128M-vmargs 说明后面是VM的参数,所以后面的其实都是JV ...
- 移动端click时间延迟300
解决移动端click延迟事件方法,,引入fastclick.js 然后在script标签里面写上FastClick.attach(document.body); <!DOCTYPE html& ...
- 对session的理解
java Servlet API引入session 机制来跟踪客户的状态,session指的是在一段时间内,单个客户和web服务器之间一连串的交互过程,在一个session中,一个客户可能会多次请求同 ...