在学习到C语言的缓冲区的时候,本来是一切顺利的,结果看到了说是stdin、stdout、stderr三个标准流是一个文件指针,可以当作像普通文件指针fp那样进行函数的操作,这让我想起了有关文件指针相关的fgetc、fputc、fgets、fputs、fscanf、fprintf以及puts和gets这一系列的函数,还有最基础的scanf和getchar函数,给我彻底搞懵圈了,然后我就针对其中的scanf、getchar、fgets、fputs、puts做了一些研究,下面是代码:
#include <stdio.h>
#include <stdlib.h>
void main()
{
int i;
int ch_int;
char ch_char, ch_string[50];
printf("========测试scanf与stdin关系========\n");
printf("开始:stdin位置标识符:%d\n", ftell(stdin));
printf("输入三个整数(每个整数之间用空格隔开):");
while (scanf("%d", &ch_int) == 1)
{
printf("ch_int = %d\n", ch_int);
printf("中间:stdin位置标识符:%d\n", ftell(stdin));
if ((ch_int = getchar()) == '\n')
{
// 为了实验的严谨性,使用getchar提取到的换行符'\n'在达到跳出循环的目的之前,要先重新归还给stdin里
printf("返回回车键:%d(ascii = 10为换行符'\\n')\n", ungetc(ch_int, stdin));
printf("结束:stdin位置标识符:%d\n", ftell(stdin));
break;
}
}
// 所以如果要连续使用多次scanf函数接收int、char型数据的时候,相隔两次中要添加一个getchar()函数用来接收stdin中剩余的换行符'\n'
printf("检测本次getchar会不会接收到键盘输入的换行符:%d(ascii = 10为换行符'\\n')\n", getchar());
printf("\n重置之前:stdin位置标识符:%d\n", ftell(stdin));
printf("将stdin的位置标识符重置...\n");
rewind(stdin);
// 由此可知,一经scanf等函数从stdin中读出完数据的时候,其数据也被一并从中移除
printf("重置之后:stdin位置标识符:%d\n", ftell(stdin));
printf("检测经过scanf函数扫描之后stdin中是否保存有之前的数据...\n");
// 本行的getchar()要另外从键盘中读取数据
printf("getchar() = %d(ascii = 10为换行符'\\n')\n", getchar());
printf("检测之后:stdin位置标识符:%d\n", ftell(stdin));
printf("\n输入三个字符(每个字符之间用空格隔开):");
// 通过实践得知,当调用新的scanf函数,stdin的位置标识符会被重置成0
while (scanf("%c", &ch_char) == 1)
{
printf("ch_char = %c\n", ch_char);
printf("中间:stdin位置标识符:%d\n", ftell(stdin));
if ((ch_char = getchar()) == '\n')
{
printf("返回回车键:%d(ascii = 10为换行符'\\n')\n", ungetc(ch_char, stdin));
printf("结束:stdin位置标识符:%d\n", ftell(stdin));
break;
}
}
printf("检测本次getchar会不会接收到键盘输入的换行符:%d(ascii = 10为换行符'\\n')\n", getchar());
printf("\n输入三个字符串(每个字符串之间用空格隔开):");
while (scanf("%s", ch_string) == 1)
{
printf("ch_string = %s\n", ch_string);
printf("中间:stdin位置标识符:%d\n", ftell(stdin));
if ((ch_char = getchar()) == '\n')
{
printf("返回回车键:%d(ascii = 10为换行符'\\n')\n", ungetc(ch_char, stdin));
printf("结束:stdin位置标识符:%d\n", ftell(stdin));
break;
}
}
printf("检测本次getchar会不会接收到键盘输入的换行符:%d(ascii = 10为换行符'\\n')\n", getchar());
printf("\n========测试fputs、fgets、gets与stdin关系========\n");
rewind(stdin);
printf("开始:stdin位置标识符:%d\n", ftell(stdin));
printf("将字符串'abcdefg\\n'利用fputs函数写入stdin中...");
// 通过结果得知无法使用fputs函数对stdin人为写入数据
if (fputs("abcdefg\n", stdin) >= 0)
printf("执行成功!\n");
else
printf("执行失败!\n");
printf("执行fputs之后:stdin位置标识符:%d\n", ftell(stdin));
// 这里只能是利用gets函数另外从键盘中读取新的字符串
printf("尝试利用gets函数能否提取出刚刚写入的字符串...:");
printf("该字符串为%s\n", gets(ch_string));
printf("执行gets之后:stdin位置标识符:%d\n", ftell(stdin));
// stdin可以利用fgets函数从键盘中读取一个字符串
printf("利用fgets函数读取stdin...:");
if (fgets(ch_string, 50, stdin) != NULL)
printf("执行成功!,字符串为:%s\n", ch_string);
else
perror("执行失败!原因是");
printf("执行fgets之后:stdin位置标识符:%d\n", ftell(stdin));
}
以下是执行结果:
========测试scanf与stdin关系========
开始:stdin位置标识符:0
输入三个整数(每个整数之间用空格隔开):11 22 33
ch_int = 11
中间:stdin位置标识符:2
ch_int = 22
中间:stdin位置标识符:5
ch_int = 33
中间:stdin位置标识符:8
返回回车键:10(ascii = 10为换行符'\n')
结束:stdin位置标识符:8
检测本次getchar会不会接收到键盘输入的换行符:10(ascii = 10为换行符'\n')
重置之前:stdin位置标识符:10
将stdin的位置标识符重置...
重置之后:stdin位置标识符:0
检测经过scanf函数扫描之后stdin中是否保存有之前的数据...
getchar() = 10(ascii = 10为换行符'\n')
检测之后:stdin位置标识符:2
输入三个字符(每个字符之间用空格隔开):a b c
ch_char = a
中间:stdin位置标识符:1
ch_char = b
中间:stdin位置标识符:3
ch_char = c
中间:stdin位置标识符:5
返回回车键:10(ascii = 10为换行符'\n')
结束:stdin位置标识符:5
检测本次getchar会不会接收到键盘输入的换行符:10(ascii = 10为换行符'\n')
输入三个字符串(每个字符串之间用空格隔开):aaa bbb ccc
ch_string = aaa
中间:stdin位置标识符:3
ch_string = bbb
中间:stdin位置标识符:7
ch_string = ccc
中间:stdin位置标识符:11
返回回车键:10(ascii = 10为换行符'\n')
结束:stdin位置标识符:11
检测本次getchar会不会接收到键盘输入的换行符:10(ascii = 10为换行符'\n')
========测试fputs、fgets、gets与stdin关系========
开始:stdin位置标识符:0
将字符串'abcdefg\n'利用fputs函数写入stdin中...执行失败!
执行fputs之后:stdin位置标识符:0
尝试利用gets函数能否提取出刚刚写入的字符串...:lalala
该字符串为lalala
执行gets之后:stdin位置标识符:8
利用fgets函数读取stdin...:1234567
执行成功!,字符串为:1234567
执行fgets之后:stdin位置标识符:9
望大佬斧正!