Maison > développement back-end > Tutoriel C#.Net > 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是最好的语言
Libérer: 2018-08-01 11:46:59
original
3147 Les gens l'ont consulté

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

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

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
Copier après la connexion
{
Copier après la connexion
Copier après la connexion
Copier après la connexion
	char*	_ptr;//指向当前缓冲区读取位置
Copier après la connexion
	int	_cnt;//缓冲区中剩余数据长度
Copier après la connexion
	char*	_base;
Copier après la connexion
	int	_flag;
Copier après la connexion
	int	_file;
Copier après la connexion
	int	_charbuf;
Copier après la connexion
	int	_bufsiz;
Copier après la connexion
	char*	_tmpfname;
Copier après la connexion
} FILE;
Copier après la connexion

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)
Copier après la connexion
{
Copier après la connexion
Copier après la connexion
Copier après la connexion
  return (--stdin->_cnt >= 0)
Copier après la connexion
    ?  (int) (unsigned char) *stdin->_ptr++
Copier après la connexion
    : _filbuf (stdin);
Copier après la connexion
}
Copier après la connexion
Copier après la connexion

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);
Copier après la connexion
int setvbuf(FILE * restrict stream, char * restrict buf, int mode, size_t size);
Copier après la connexion

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()
Copier après la connexion
{
Copier après la connexion
Copier après la connexion
Copier après la connexion
    int c;
Copier après la connexion
    char buf[BUFSIZ];
Copier après la connexion
<br>
Copier après la connexion
    setbuf(stdout,buf);
Copier après la connexion
    while((c = getchar()) != EOF)
Copier après la connexion
        putchar(c);
Copier après la connexion
Le problème est le suivant :
    <br>
Copier après la connexion
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;
Copier après la connexion
}
Copier après la connexion
Copier après la connexion

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
Copier après la connexion
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
Copier après la connexion
. 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
Copier après la connexion
undefined.
Copier après la connexion

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
Copier après la connexion
contents of the buffer associated with the stream. If the stream is open for input,
Copier après la connexion
fflush clears the contents of the buffer.
Copier après la connexion

setbuf(stdin, formule NULL

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

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

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

  • 经典式

 c;
Copier après la connexion
while((c = getchar()) != '\n' && c != EOF);
Copier après la connexion

由代码知,不停地使用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!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
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
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal