进进出出的I/O
上次介绍完流与文件的相关概念后,这次我们来介绍一些I/O操作相关的一些标准库函数。注意包含头文件stdio.h
数据类型 | 输入 | 输出 | 描述 |
---|
字符 | getchar() | putchar() | 读取(写入)的单个字符 |
文本行 | [gets()] scanf() | [puts()] printf() | [文本行未格式化的输入(输出)]文本行格式化的输入(输出) |
getchar()
- 1.函数原型 int getchar(void)
- 2.函数说明
- getchar()的功能是从stdin中读取单个字符。当调用getchar()时,程序首先等待用户从键盘输入,用户输入的字符将被暂存到键盘缓冲区中,直到用户按下回车键为止(回车键也被放在缓冲区中)。用户键入回车之后 getchar()才开始从stdio流中每次读入一个字符,并将用户输入的字符回显到屏幕,保留在键盘缓冲区的剩余字符将等待后续getchar()的调用,也就是后续的getchar()调用不会等待用户按键,而是直接从键盘缓冲区中读取字符,直到缓冲区的字符读完才等待用户输入。getchar()函数有一个int型的返回值,若出错该返回值返回为-1,否则为用户第一个输入字符的ASCII码
- 3.应用举例
#include<stdio.h>
int main(void)
{
char ch=getchar();
putchar(ch);
return 0;
}
gets()
- 1.函数原型:char *gets(char *buffer)
- 2.函数说明
- 函数的功能是从stdin中读取字符串,并将读取的结果存放在buffer指针所指向的字符数组中,直到遇到换行符或EOF(’\0’:字符串结束符)之后就不在读取,换行符不作为读取串的内容,读取的换行符为’\0’,并由此来结束字符串。下一次调用gets()将从流的下一个字符开始读取。如果在任何字符读取前就遇到了字符串结尾,缓冲区就未进行修改,此时gets()函数返回一个NULL指针。否则gets()函数返回指向缓冲区的指针。这个返回值通常只是用于检测是否查到了字符串的结尾。
- 在使用gets()时需要注意,gets()无法判断缓冲区的长度,因此在申明缓冲区的时候要确保它足够大,防止缓冲区溢出。
- 3.应用举例:这里比较一下fgets()函数,这是我以前尝试的时候打的代码,这里正好照搬一下
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
/*
注意:
1、gets函数不对接受字符串的数组进行边界检查,会造成越界,从而产生bug
2、可以使用fgets(words1,20,stdin);代替gets,20表示最多读入20-1个字符,多余的字符留在缓冲区
*/
void main()
{
char words1[20];
char words2[20];
printf("请输入字符串:");
gets(words1);
gets(words2);
puts("*******使用gets函数的结果********\n");
puts(words1);
puts(words2);
printf("请输入字符串:");
fgets(words1,5,stdin);
fgets(words2,4,stdin);
puts("*******使用fgets函数的结果********\n");
puts(words1);
puts(words2);
}
scanf()
- 1.函数原型:int scanf(char const *format,…);
一般形式:scanf(格式控制,参数地址表列); - 2.函数说明
- 由于经常用到的,就不详细说明了。这里表格列出常用格式控制字符串
格式转换说明符 | 说明 |
---|
%d或%i | 输入有符号十进制整数 |
%u | 输入无符号十进制整数 |
%x或%X | 输入无符号十六进制整数(大小写相同) |
%o | 输入无符号八进制整数 |
%f或%e,%g | 输入实数,以小数或指数形式输入均可,e与f,g可互相替换 |
%c | 输入单个字符 |
%s | 输入字符串,将字符串送到一个字符数组中 |
- 这里需要说明一下:scanf()函数不做类型匹配检查,因此,在当输入的数据类型与格式字符不匹配时程序不会提示出错的信息,这种情况可能导致不能正确的读入数据。
- 在输入数据时,scanf()函数遇到以下情况就认为数据输入结束。
- 1.遇到空格或按回车或者tab键
- 2.按指定的宽度结束,如""%2d",只区2列
- 3.遇到非法字符
- 注意,这里的结束指的是当前格式符匹配的数据输入结束,如果用多余一个的格式匹配符,则scanf()会等待继续输入。
- 我们来看一下下面这段代码
char ch1,ch2,ch3;
scanf("%c%c%c",&ch1,&ch2,&ch3);
//这时候我们想要把abc这三个字符输入然后分别赋值给ch1,ch2,ch3
- 但是当我们输入的时候我们会有一个习惯就是每输入一个字符,我们就会输入一个空格,也就是下面的输入习惯:“a_b_c”;(注意这里使用下划线来充当空格字符)
- 我们来分析一下ch1,ch2,ch3这三个字符变量接受到的具体的值。
- 首先我们输入字符 a ,然后这个时候ch1接收到了a的值,即ch1=‘a’;
- 第二步我们这时候输入了空格,这时候这个空格也会被当做有效字符来赋给ch2,即ch2=’_’;(这里使用下划线来充当空格字符)
- 第三步我们输入了 b 这时候ch3=‘b’;
- 最后输入的空格子符和’c’,会留在键盘缓冲区,因为这时候格式控制符已经被匹配完。所以我们在输入字符的时候一定要注意这个细节。最后是使用空格来隔开。即下面的代码:
char ch1,ch2,ch3;
scanf("%c %c %c",&ch1,&ch2,&ch3);
//这时候我们把格式控制符用空格来隔开,当然也可以替换成你想要的字符来隔开。
putchar()
- 1.函数原型:int putchar(int character);
- 2.函数说明
- 函数的功能是将单个字符写入stdout中(标准输出),即向终端输出一个字符
#include<stdio.h>
void main()
{
putchar('c');//输出字符C
printf("\n");
putchar('\101');//输出字符A,八进制表示十进制数字65
printf("\n");
putchar('abc');//只输出一个字符,输出值因编译器的不同而不同
printf("\n");
putchar('-1');//将'-1'转换为无符号字符型的一个值。
putchar('\n');//输出回车符
}
}
- putchar()函数有一个int型的返回值,若出错则返回EOF(值为-1),否则输出到stdout的字符是ASCII码。该函数的参数是需要输出的字符,在输出前函数把这个整形参数裁剪为一个无符号的字符型的值,然后再进行输出。
puts()
- 1.函数原型:int puts(char const *buffer)
- 2.函数说明
- 函数的功能是向标准输出文件(stdout)写入字符串,即向标准输出设备(屏幕)输出字符串并换行
- 如果出错,则返回-1,否则返回一个非负值
- 在函数里面可以直接传入一个指向字符串的指针,也可以直接传入一个字符串变量。或者是一个字符数组。
- 3.应用举例
#include<stdio.h>
int main(void)
{
char *exp="Hello Wrold!";
puts(exp);
return 0;
}
printf()
- 1.函数原型:int printf(char const *fromat,…);
- 2.一般形式:printf(格式控制,输出参数表列);
-
- 函数说明
- 应用举例
- 输出一个字符串
printf("%s\n","Hello World!")
- 格式化字符串
- %ms,输出字符串占m列,若字符串大于m全部输出,字符串小于m左补空格。
printf("%15s\n","Hello World!")
//结果为:_ _ _Hello World!
- 另一种方式
- %ms,输出字符串占m列,若字符串大于m全部输出,字符串小于m左补空格。
printf("%15s\n","Hello World!")
//结果为:Hello World!_ _ _
- 再学一点
- %m.ns,输出占m列,只取字符串中左端n个字符,字符串靠右,左补空格;n>m字符串全部输出。
printf("%-10.5s\n","hello world");
//结果为:_ _ _ _ _hello
- 更进一步
- %-m.ns,输出占m列,只取字符串中左端n个字符,字符串靠左,右补空格;n>m字符串全部输出。
printf("%-10.5s\n","hello world");
//结果为:hello_ _ _ _ _
总结
- gets()函数无法判断缓冲区的长度,因此要申明足够大的缓冲区,防止缓冲区溢出。
- 函数scanf()不做类型匹配检查,使用时要注意避免输入非法字符。
- 函数scanf()的格式控制符后面应该是变量的地址,不是变量名。
- 函数scanf()的格式控制字符串中除了格式转换说明符还用了其他字符,输入时应注意在对应的位置输入与这些字符相同的字符。