Home  >  Article  >  Backend Development  >  How to clear the input buffer using C language? There are many methods worth learning from

How to clear the input buffer using C language? There are many methods worth learning from

php是最好的语言
php是最好的语言Original
2018-08-01 11:46:593057browse

There are several basic input functions in the C language:

<span style="color:#008000;">//获取字符系列</span><br>
int fgetc(FILE *stream);
int getc(FILE *stream);
int getchar(void);
//获取行系列
char *fgets(char * restrict s, int n, FILE * restrict stream);
char *gets(char *s);//可能导致溢出,用fgets代替之。
//格式化输入系列
int fscanf(FILE * restrict stream, const char * restrict format, …);
int scanf(const char * restrict format, …);
int sscanf(const char * restrict str, const char * restrict format, …);

Here we only discuss the use of input functions in the case of standard input (stdin). Looking at the above input functions, <br>

  • obtains the first three functions fgetc, getc, and getchar of the character series . Taking getchar as an example, when the stdin buffer is empty, it will wait for input until the function returns when the carriage return and line feed occur. If the stdin buffer is not empty, getchar returns directly. When getchar returns, it takes a character from the buffer, converts it to an int, and returns this int value.

##Source code of FILE structure in MINGW 4.4.3:

  _iobuf
{
	char*	_ptr;//指向当前缓冲区读取位置
	int	_cnt;//缓冲区中剩余数据长度
	char*	_base;
	int	_flag;
	int	_file;
	int	_charbuf;
	int	_bufsiz;
	char*	_tmpfname;
} FILE;
The implementation of each compiler may be different. Here, the character series function is only used to _ptr and _cnt.

<br>

Getchar() implementation in MINGW 4.4.3:

__CRT_INLINE int __cdecl __MINGW_NOTHROW getchar (void)
{
  return (--stdin->_cnt >= 0)
    ?  (int) (unsigned char) *stdin->_ptr++
    : _filbuf (stdin);
}
stdin is the FILE pointer type. In MINGW 4.4.3, getc() and getchar() is implemented as an inline function, and fgetc() is implemented as a function. By the way, support for inline functions has been added to the C99 standard.

  • Get fgets and gets of line series . Because gets cannot determine the buffer size, it often leads to overflow. The gets function is not recommended or discussed here. For the fgets function, fgets returns every time you press Enter. When fgets returns successfully, the data in the input buffer will be copied to the space pointed to by the first parameter together with the newline character '\n'. If the input data exceeds the buffer length, fgets will intercept the data to the first n-1 (n is the second parameter of fgets, which is the length of the space pointed to by the first parameter), and then add '\n' at the end. Therefore fgets is safe. Usually fgets(buf, BUF_LEN, stdin); is used instead of gets(buf);.

  • In the formatted input series, fscanf is difficult to use when formatting input from a file stream. The most commonly used one is scanf. The formatted input series functions discard the whitespace characters (spaces, tabs, newline character) until a non-whitespace character is encountered, and then attempts to parse the non-whitespace character and subsequent characters according to the format parameters. This series of functions returns the number of variables successfully parsed and assigned. If it encounters the end of file or an error, it returns EOF.

==================Separating line==================

When it comes to buffers, we have to mention the two buffer setting functions

setbuf and setvbuf, which are declared as follows:

 setbuf(FILE * restrict stream,  * restrict buf);
int setvbuf(FILE * restrict stream, char * restrict buf, int mode, size_t size);

setvbuf The mode parameters of are:

  • _IOFBF (full buffer): read data when the buffer is empty; write data to the stream when the buffer is full.

  • _IOLBF (line buffer): Read one line of data from or write data to the stream at a time. For example:

    stdio,stdout

  • _IONBF (unbuffered): read data directly from the stream, or write data directly to the stream, And there is no buffer. Such as:

    stderr

setbuf(stream, buf); in:

  • buf = = NULL: Equivalent to (void)setvbuf(stream, NULL, _IONBF, 0);

  • buf points to a buffer with length

    BUFSIZ: Equivalent to (void)setvbuf(stream, buf, _IOFBF, BUFSIZ);

Note: The

BUFSIZ macro is defined in stdio.h.

I would also like to mention the

classic mistake of the legendary setbuf, which is mentioned in "C Traps and Defects":

 main()
{
    int c;
    char buf[BUFSIZ];
<br>
    setbuf(stdout,buf);
    while((c = getchar()) != EOF)
        putchar(c);
    <br>
    return 0;

The problem is this: The C runtime library must perform cleanup work before the program returns control to the operating system, part of which is to refresh the output buffer, but at this time the main function has finished running, and the buf buffer scope is in main In the function, the buf character array has been released at this time, causing the output to be strange and garbled.

Solution: You can set buf to static, or a global variable, or call malloc to dynamically apply for memory.

==================Separating line=================

Come on Take a look at several popular buffer flushing methods:

    ##fflush(stdin);Formula
  • From the C99 standard document:
}
If stream points to an output stream or an update stream in which the most recent
operation was not input, the fflush function causes any unwritten data for that stream
to be delivered to the host environment to be written to the file; otherwise, the behavior is

It can be seen that

fflush does not define the behavior of the input stream as a parameter

. But from the definition of fflush on MSDN:

undefined.
If the file associated with stream is open for output, fflush writes to that file the
contents of the buffer associated with the stream. If the stream is open for input,

, we can see that fflush (stdin) is still valid on VC! Since each compiler implements fflush's undefined behavior differently, it is not recommended to use fflush(stdin) to refresh the input buffer.

  • setbuf(stdin, NULL);Formula

由前面对setbuf函数的介绍,可以得知,setbuf(stdin, NULL);是使stdin输入流由默认缓冲区转为无缓冲区。都没有缓冲区了,当然缓冲区数据残留问题会解决。但这并不是我们想要的。

  • scanf("%*[^\n]");式(《C语言程序设计 现代方法 第二版》中提到)

这里用到了scanf格式化符中的“*”,即赋值屏蔽;“%[^集合]”,匹配不在集合中的任意字符序列。这也带来个问题,缓冲区中的换行符’\n’会留下来,需要额外操作来单独丢弃换行符。

  • 经典式

 c;
while((c = getchar()) != '\n' && c != EOF);

由代码知,不停地使用getchar()获取缓冲区中字符,直到获取的字符c是换行符’\n’或者是文件结尾符EOF为止。这个方法可以完美清除输入缓冲区,并且具备可移植性。<br>

相关文章:

禁止页面缓存的方法 多语言下禁止页面缓存

如何批量清理系统临时文件(语言:C#、 C/C++、 php 、python 、java )

相关视频:

C 语言教程

The above is the detailed content of How to clear the input buffer using C language? There are many methods worth learning from. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn