C语⾔的标准输⼊输出
欢迎探讨,如有错误敬请指正
如需转载,请注明出处 wwwblogs/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
spring festival作文6句话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);case语句后面什么都不写
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, ...);
whose umbrella is this是什么意思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);putchar函数
}
设置流缓冲
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:⽆缓冲类型
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论