Maison  >  Article  >  développement back-end  >  Comment vider le tampon d’entrée en utilisant le langage C ? Il existe de nombreuses méthodes qui méritent d'être apprises

Comment vider le tampon d’entrée en utilisant le langage C ? Il existe de nombreuses méthodes qui méritent d'être apprises

php是最好的语言
php是最好的语言original
2018-08-01 11:46:593057parcourir

Il existe plusieurs fonctions de saisie de base en langage C :

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

Ici, nous discutons uniquement de l'utilisation des fonctions d'entrée dans le cas d'une entrée standard (stdin). En regardant les fonctions d'entrée ci-dessus, <br>

  • obtient les trois premières fonctions fgetc, getc et getchar de la série de caractères . En prenant getchar comme exemple, lorsque le tampon stdin est vide, il attendra l'entrée jusqu'à ce que la fonction revienne lorsque le retour chariot et le saut de ligne se produisent. Si le tampon stdin n'est pas vide, getchar renvoie directement. Lorsque getchar revient, il prend un caractère du tampon, le convertit en int et renvoie cette valeur int.

Code source de la structure FILE dans MINGW 4.4.3  :

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

L'implémentation de chaque compilateur peut être différente Ici, seuls _ptr et _cnt sont utilisés pour obtenir la fonction de série de caractères. <br>

Implémentation de Getchar() dans MINGW 4.4.3 :

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

où stdin est un type de pointeur FILE Dans MINGW 4.4.3, getc() et getchar() sont implémentés en tant que fonctions en ligne, et fgetc() est implémenté en tant que fonction. À propos, la prise en charge des fonctions en ligne a été ajoutée à la norme C99.

  • Obtenez les fgets et les get de la série de lignes Étant donné que les get ne peuvent pas déterminer la taille du tampon, cela conduit souvent à un débordement. La fonction gets n'est pas recommandée ou discutée. ici. Pour la fonction fgets, fgets revient à chaque fois que vous appuyez sur Entrée. Lorsque fgets revient avec succès, les données dans le tampon d'entrée et le caractère de nouvelle ligne « n » seront copiés dans l'espace pointé par le premier paramètre. Si les données d'entrée dépassent la longueur du tampon, fgets interceptera les données jusqu'au premier n-1 (n est le deuxième paramètre de fgets, qui est la longueur de l'espace pointé par le premier paramètre), puis ajoutera 'n' à la fin. Par conséquent, fgets est sûr. Habituellement, fgets(buf, BUF_LEN, stdin); est utilisé à la place de gets(buf);.

  • Dans la série d'entrées formatées , fscanf est difficile à utiliser lors du formatage de l'entrée d'un flux de fichiers. La plus couramment utilisée est scanf. Les fonctions de série d'entrée formatées suppriment les caractères vides (espaces, tabulations, caractère de nouvelle ligne) jusqu'à ce qu'un caractère autre qu'un espace soit rencontré, puis tentent d'analyser le caractère autre qu'un espace. et les caractères suivants selon les paramètres de format. Cette série de fonctions renvoie le nombre de variables analysées et attribuées avec succès. Si elle rencontre une fin de fichier ou une erreur, elle renvoie EOF.

==================Ligne de séparation==================

En ce qui concerne les tampons, nous devons mentionner les deux fonctions de réglage du tampon setbuf et setvbuf, qui sont déclarées comme suit :

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

setvbuf sont :

  • _IOFBF (tampon complet) : lire les données lorsque le tampon est vide, écrire des données dans le flux lorsque ; le tampon est plein.

  • _IOLBF (tampon de ligne) : lit une ligne de données ou écrit des données dans le flux à la fois. Par exemple :

    stdio,stdout

  • _IONBF (pas de mise en mémoire tampon) : lire les données directement à partir du flux ou écrire des données directement dans le flux , Et il n'y a pas de tampon. Par exemple :

    stderr

setbuf(stream, buf) ; = = NULL : équivalent à (void)setvbuf(stream, NULL, _IONBF, 0);

  • buf pointe vers un tampon de longueur

    BUFSIZ

     : équivalent à ( void)setvbuf(stream, buf, _IOFBF, BUFSIZ);
  • Remarque : La macro BUFSIZ

    est définie dans stdio.h.
Je voudrais également mentionner la légendaire

erreur classique de setbuf

, qui a été mentionnée dans "C Traps and Defects" :

 main()
{
    int c;
    char buf[BUFSIZ];
<br>
    setbuf(stdout,buf);
    while((c = getchar()) != EOF)
        putchar(c);
Le problème est le suivant :
    <br>
Le programme rend le contrôle au système d'exploitation Auparavant, la bibliothèque d'exécution C devait effectuer un travail de nettoyage, dont une partie consistait à actualiser le tampon de sortie, mais à ce moment-là, la fonction principale avait fini de s'exécuter et la portée du tampon buf était dans la fonction principale. le tableau de caractères buf avait été publié, ce qui entraînait une sortie étrange et tronquée.
    return 0;
}

Solution : Vous pouvez définir buf sur statique, ou sur une variable globale, ou appeler malloc pour appliquer dynamiquement de la mémoire.

==================Ligne de séparation==================

Viens See More ci-dessous Jetez un œil à plusieurs méthodes de vidage de tampon populaires :

fflush(stdin); la formule

  • du document standard C99 :

On peut voir que
If stream points to an output stream or an update stream in which the most recent
fflush ne définit pas le comportement du flux d'entrée en tant que paramètre
operation was not input, the fflush function causes any unwritten data for that stream
. Mais d'après la définition de fflush sur MSDN :
to be delivered to the host environment to be written to the file; otherwise, the behavior is
undefined.

On voit que fflush (stdin) est toujours valable sur VC ! Étant donné que chaque compilateur implémente différemment le comportement non défini de fflush, il n'est pas recommandé d'utiliser fflush(stdin) pour actualiser le tampon d'entrée.
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,
fflush clears the contents of the buffer.

setbuf(stdin, formule NULL

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

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn