Heim  >  Artikel  >  Backend-Entwicklung  >  Wie lösche ich den Eingabepuffer mit der Sprache C? Es gibt viele Methoden, von denen es sich zu lernen lohnt

Wie lösche ich den Eingabepuffer mit der Sprache C? Es gibt viele Methoden, von denen es sich zu lernen lohnt

php是最好的语言
php是最好的语言Original
2018-08-01 11:46:593079Durchsuche

Es gibt mehrere grundlegende Eingabefunktionen in der C-Sprache:

<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, …);

Hier diskutieren wir nur die Verwendung von Eingabefunktionen im Fall der Standardeingabe (stdin). Betrachtet man die obigen Eingabefunktionen, erhält <br>

  • die ersten drei Funktionen fgetc, getc und getchar der Zeichenreihe . Am Beispiel von getchar: Wenn der Standardpuffer leer ist, wartet er auf die Eingabe, bis die Funktion zurückkehrt, wenn Wagenrücklauf und Zeilenvorschub erfolgen. Wenn der Standardpuffer nicht leer ist, gibt getchar direkt zurück. Wenn getchar zurückkehrt, nimmt es ein Zeichen aus dem Puffer, wandelt es in einen int-Wert um und gibt diesen int-Wert zurück.

Quellcode der FILE-Struktur in MINGW 4.4.3:

  _iobuf
{
	char*	_ptr;//指向当前缓冲区读取位置
	int	_cnt;//缓冲区中剩余数据长度
	char*	_base;
	int	_flag;
	int	_file;
	int	_charbuf;
	int	_bufsiz;
	char*	_tmpfname;

Die Implementierung jedes Compilers kann unterschiedlich sein Funktion wird nur für _ptr und _cnt verwendet. <br>

Getchar()-Implementierung in MINGW 4.4.3:

} FILE;
__CRT_INLINE int __cdecl __MINGW_NOTHROW getchar (void)
{
  return (--stdin->_cnt >= 0)
    ?  (int) (unsigned char) *stdin->_ptr++
    : _filbuf (stdin);

wobei stdin der FILE-Zeigertyp ist, in MINGW 4.4.3 getc() und getchar() ist als Inline-Funktion implementiert und fgetc() ist als Funktion implementiert. Übrigens wurde der C99-Standard um Unterstützung für Inline-Funktionen erweitert.

  • Gets und Gets von Zeilenserien Da Gets die Puffergröße nicht bestimmen können, führt dies häufig zu einem Überlauf. Die Gets-Funktion wird hier nicht empfohlen oder besprochen. Für die Funktion fgets kehrt fgets jedes Mal zurück, wenn Sie die Eingabetaste drücken. Wenn fgets erfolgreich zurückkehrt, werden die Daten im Eingabepuffer und das Zeilenumbruchzeichen „n“ in den Bereich kopiert, auf den der erste Parameter zeigt. Wenn die Eingabedaten die Pufferlänge überschreiten, fängt fgets die Daten bis zum ersten n-1 ab (n ist der zweite Parameter von fgets, also die Länge des Raums, auf den der erste Parameter zeigt) und fügt dann „n“ hinzu. Am Ende. Daher ist fgets sicher. Normalerweise wird fgets(buf, BUF_LEN, stdin); anstelle von gets(buf); verwendet.

  • In der formatierten Eingabeserie ist fscanf beim Formatieren von Eingaben aus einem Dateistream schwierig zu verwenden. Die am häufigsten verwendete ist scanf. Die formatierten Eingabereihenfunktionen verwerfen die Leerzeichen (Leerzeichen, Tabulatoren, Zeilenumbruchzeichen), bis ein Nicht-Leerzeichen auftritt, und versuchen dann, das Nicht-Leerzeichen zu analysieren und Folgezeichen gemäß den Formatparametern. Diese Funktionsreihe gibt die Anzahl der erfolgreich analysierten und zugewiesenen Variablen zurück. Wenn ein Dateiende oder ein Fehler auftritt, wird EOF zurückgegeben.

=================Trennlinie=================

Wenn es um Puffer geht, müssen wir die beiden Puffereinstellungsfunktionen setbuf und setvbuf erwähnen, die wie folgt deklariert sind:

}
 setbuf(FILE * restrict stream,  * restrict buf);

setvbuf Die Modusparameter von sind:

  • _IOFBF (voller Puffer): Daten lesen, wenn der Puffer leer ist; Daten in den Stream schreiben, wenn der Puffer voll ist.

  • _IOLBF (Zeilenpuffer): Lesen Sie jeweils eine Datenzeile aus dem Stream oder schreiben Sie Daten in den Stream. Zum Beispiel: stdio,stdout

  • _IONBF (keine Pufferung): Daten direkt aus dem Stream lesen oder Daten direkt in den Stream schreiben , Und es gibt keinen Puffer. Zum Beispiel: stderr

setbuf(stream, buf); in:

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

  • buf zeigt auf einen Puffer mit der Länge BUFSIZ: Entspricht ( void)setvbuf(stream, buf, _IOFBF, BUFSIZ);

Hinweis: Das Makro BUFSIZ ist in stdio.h definiert.

Ich möchte auch den legendären setbuf 's klassischem Fehler erwähnen, der in "C -Fallen und Defekten" erwähnt wird:

Das Problem ist folgendes:

Die C-Laufzeitbibliothek muss bereinigt werden, bevor das Programm die Kontrolle an das Betriebssystem zurückgibt. Ein Teil davon besteht darin, den Ausgabepuffer zu aktualisieren, aber zu diesem Zeitpunkt ist die Ausführung der Hauptfunktion abgeschlossen Der Buf-Pufferbereich befindet sich in main In der Funktion wurde das Buf-Zeichenarray zu diesem Zeitpunkt freigegeben, was zu einer seltsamen und verstümmelten Ausgabe führt.

Lösung:

Sie können buf auf static oder eine globale Variable setzen oder malloc aufrufen, um dynamisch Speicher zu beantragen. ==================Trennlinie=================

Komm on Werfen Sie einen Blick auf mehrere beliebte Puffer-Flush-Methoden:

    flush(stdin); die Formel
  • aus dem C99-Standarddokument:
int setvbuf(FILE * restrict stream, char * restrict buf, int mode, size_t size);
 main()
{
    int c;

Es ist ersichtlich, dass

ffflush das Verhalten des Eingabestreams nicht als Parameter definiert

. Aber aus der Definition von fflush auf MSDN:

    char buf[BUFSIZ];
<br>
    setbuf(stdout,buf);

Es ist ersichtlich, dass fflush (stdin) auf VC immer noch gültig ist! Da jeder Compiler das undefinierte Verhalten von fflush unterschiedlich implementiert, wird die Verwendung von fflush(stdin) zum Aktualisieren des Eingabepuffers nicht empfohlen.

  • setbuf(stdin, NULL); Formel

由前面对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 语言教程

Das obige ist der detaillierte Inhalt vonWie lösche ich den Eingabepuffer mit der Sprache C? Es gibt viele Methoden, von denen es sich zu lernen lohnt. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn