[C language] Correct use of getchar function


1. getchar function

insert image description hereFrom the above introduction, if we want to use the getchar function correctly, we must first understand what a buffer is.


2. Buffer

1. What is a buffer

A buffer, also known as a cache, is part of the memory space.

That is to say, a certain amount of storage space is reserved in the memory space, and these storage spaces are used to buffer input or output data , and this part of the reserved space is called a buffer.

Buffers are divided into input buffers and output buffers according to their corresponding input devices and output devices .


2. Why there is a buffer

Why do we introduce buffers?

For example, when we fetch information from the disk, we first put the read data in the buffer, and then the computer directly fetches the data from the buffer, and then reads it from the disk after the data in the buffer is fetched, which can reduce the number of disks. The number of reads and writes, coupled with the computer's operation on the buffer is much faster than the operation on the disk, so the application of the buffer can greatly improve the running speed of the computer.

For another example, we use a printer to print documents. Since the printing speed of the printer is relatively slow, we first output the document to the corresponding buffer of the printer, and then the printer prints it step by step. At this time, our CPU can handle other things. Now you basically understand that a buffer is a memory area that is used between the input and output devices and the CPU to cache data. It enables the low-speed input and output devices and the high-speed CPU to work in coordination, avoids the low-speed input and output devices occupying the CPU, liberates the CPU, and enables it to work efficiently.


3, the type of buffer

There are three types of buffers: fully buffered, line buffered, and unbuffered.

1. Full buffering
In this case, the actual I/O operation is performed when the standard I/O buffer is filled. A typical representation of full buffering is reading and writing to disk files.

2. Line buffering
In this case, the real I/O operation is performed when a newline character is encountered in input and output . At this time, the characters we input are first stored in the buffer, and the actual I/O operation is performed when the Enter key is pressed to change the line. The typical representative is keyboard input data .

3. Without buffering ,
that is, without buffering, the standard error condition stderr is a typical representative , which makes the error information can be displayed directly and as soon as possible.


4. Refresh the buffer

The following four situations can trigger a buffer flush:

  1. When the buffer is full;
  2. Execute the flush statement;
  3. execute the endl statement;
  4. Close the file.

3. Correct use of getchar function

1. The newline problem of getchar

Let's look at the following code

#include<stdio.h>
int main()
{
    
    
	int ch = 0;
	while ((ch = (getchar())) != EOF)
	{
    
    
		putchar(ch);
	}
	return 0;
}

insert image description hereWe can see that every time we enter a character from the keyboard and enter a carriage return, the putchar output will automatically wrap the line, because every time we type a carriage return in addition to the input character, and this carriage return will be stored in the buffer . In the area, when we use getchar to read characters, all characters (including newlines, spaces, and tabs) will be read one by one from the buffer until there is no data in the buffer, and each character will be printed with putchar. , so it will automatically wrap here.
insert image description here^Z: Ctrl+Z, after input, it will be recognized as EOF, thus ending the loop (sometimes in VS, you need to press it three times to end the loop, and other compilers press it once).


2. Mixed use of getchar and scanf

Let's look at the following code:

#include<stdio.h>
int main()
{
    
    
	char password[20] = {
    
     0 };
	printf("请输入密码:>");
	scanf("%s", password);
	printf("请确认密码(Y/N):>");
	int ch = getchar();
	if (ch == 'Y')
	{
    
    
		printf("确认成功\n");
	}
	else
	{
    
    
		printf("确认失败\n");
	}
	return 0;
}

insert image description hereWe can see that the program does not wait for us to enter Y/N to confirm the password, but ends directly. The reason is that what is stored in our buffer is abcdef\n, and the scanf function encounters spaces, newlines (\n), Tab ends, so \n is not read away, but continues to stay in the buffer, and when getchar reads the data, it is found that the buffer is not empty, so it directly reads \n, and then judges if condition, end the program without waiting for us to enter Y/N.


So how to avoid this from happening? There are two methods:
Method 1: Add a getchar after scanf (not recommended)

#include<stdio.h>
int main()
{
    
    
	char password[20] = {
    
     0 };
	printf("请输入密码:>");
	scanf("%s", password);
	getchar();  //读取剩下的\n
	printf("请确认密码(Y/N):>");
	int ch = getchar();
	if (ch == 'Y')
	{
    
    
		printf("确认成功\n");
	}
	else
	{
    
    
		printf("确认失败\n");
	}
	return 0;
}

insert image description hereWe add a getchar function after the scanf function to clear the excess \n in the buffer , but this method has disadvantages and is not recommended. The specific disadvantages are as follows: As shown in insert image description here
the figure: We enter abcd ef from the keyboard, we can see At this point, the program does not wait for us to enter Y/N, but directly executes the if statement. This is because the scanf function stops reading when it encounters spaces, newlines (\n), and Tabs, so the remaining characters in the buffer is _ef\n, a getchar cannot empty the buffer . Therefore, the first method can only solve a part of the situation. To completely solve the problem of the residual scanf buffer, you need to use the second method.


Method 2: Add a while( getchar() != '\n') statement after scanf (recommended)

#include<stdio.h>
int main()
{
    
    
	char password[20] = {
    
     0 };
	printf("请输入密码:>");
	scanf("%s", password);
	getchar();  //读取剩下的\n
	printf("请确认密码(Y/N):>");
	while (getchar() != '\n')
	{
    
    
		;
	}
	int ch = getchar();
	if (ch == 'Y')
	{
    
    
		printf("确认成功\n");
	}
	else
	{
    
    
		printf("确认失败\n");
	}
	return 0;
}

insert image description hereinsert image description hereThe while( getchar() != '\n') statement in the program will continuously read the characters in the buffer until the \n is read away, so as to achieve the purpose of emptying the buffer.

Guess you like

Origin blog.csdn.net/m0_62391199/article/details/124228001