Research on the Correlation Between C Language Standard Input Stream stdin and Stream-related Functions

    When I learned the buffer of the C language, everything went smoothly, but I saw that the three standard streams of stdin, stdout, and stderr are a file pointer, which can be used as a function operation like the ordinary file pointer fp. This reminds me of the fgetc, fputc, fgets, fputs, fscanf, fprintf, puts and gets series of functions related to file pointers, as well as the most basic scanf and getchar functions, which completely confused me, and then I did some research on scanf, getchar, fgets, fputs, puts , the following is the code:

#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));
}

The following is the execution result:

======== Test the relationship between scanf and stdin ========
Start: stdin Position identifier: 0
Enter three integers (each integer is separated by a space): 11 22 33
ch_int = 11
middle: stdin location identifier: 2
ch_int = 22
middle: stdin location identifier: 5
ch_int = 33
middle: stdin location identifier: 8
return carriage return: 10 (ascii=10 for newline '\n')
end : stdin position identifier: 8
Detect whether this getchar will receive the newline character input by the keyboard: 10 (ascii = 10 is the newline character '\n')

Before reset: stdin location identifier: 10
Reset the location identifier of stdin...
After reset: stdin location identifier: 0
Check whether the previous data is saved in stdin after scanning by the scanf function... 

getchar() = 10 (ascii = 10 is newline character '\n')
after detection: stdin position identifier: 2

Enter three characters (each separated by a space): abc
ch_char = a
middle: stdin position identifier: 1
ch_char = b
middle: stdin position identifier: 3
ch_char = c
middle: stdin position identifier: 5
Return Enter key: 10 (ascii = 10 is a newline character '\n')
End: stdin position identifier: 5
Check whether this getchar will receive a newline character entered by the keyboard: 10 (ascii = 10 is a newline character' \n')

Enter three strings (each separated by a space): aaa bbb ccc
ch_string = aaa
middle: stdin position identifier: 3
ch_string = bbb
middle: stdin position identifier: 7
ch_string = ccc
middle: stdin position Identifier: 11
Return Enter key: 10 (ascii = 10 is the newline character '\n')
End: stdin Position identifier: 11
Check whether this getchar will receive the newline character entered by the keyboard: 10 (ascii = 10 for newline '\n')

======== Test the relationship between fputs, fgets, gets and stdin ========
Start: stdin position identifier: 0
Write the string 'abcdefg\n' to stdin using the fputs function.. .Execution failed!
After executing fputs: stdin position identifier: 0
Try to use the gets function to extract the string just written...: lalala
The string is lalala
After executing gets: stdin position identifier: 8
Use the fgets function to read stdin ...:1234567
Execution succeeded! , the string is: 1234567

After executing fgets: stdin position identifier: 9

Hope the boss is right! 

Guess you like

Origin blog.csdn.net/weixin_48896613/article/details/119873865