Buffer circulaire

Soyez le premier à donner votre avis sur cette source.

Snippet vu 20 287 fois - Téléchargée 22 fois

Contenu du snippet

J'ai remarqué qu'il n'y avait pas de source sur les buffers circulaires. Etonnant pourtant c'est quelque chose à savoir. C'est vrai que le raisonnement n'est pas simple en lui même mais en le principe est d'allouer une memoire et stocker des données à l'intérieur en boucle. ce ki veut dire que une fois arrivà la fin de la mémoire on repart au debut. Si vous aimez les pointeurs vous allez adorer

Source / Exemple :


#include <stdio.h>
#include <malloc.h>
#include <conio.h>
#include <string.h>

typedef struct
{
			char *debut;
			char *fin;
			char *producteur;
			char *consommateur;
} CIRC;

CIRC * open_circ(int taille);
int get_circ(CIRC *B);
int put_circ(CIRC *B, int c);

void main (void)

{
	CIRC * Buffer;
	int  c;
	char choix; // Variable qui contiendra le choix de l'opération à effectuer

	// Ouverture d'un buffer circulaire
	Buffer = open_circ(20);

	do
	{
		printf("\t\t\t   buffer circulaire\n\n\n");
		printf("\t      1. Ajouter 1 caractère\n");
		printf("\t      2. Lire un caractère\n");
		printf("\t      3. Quitter\n\n\n");
		printf("  Faire votre choix svpl ? ");

		fflush(stdin);
		scanf("%c",&choix);
		switch(choix)
		{
			case '1' :
			// Ajouter 1 caractère
				printf("Entrer un caractère : ");
				fflush(stdin);
				scanf("%c", &c);
				if(put_circ(Buffer, c)== EOF)
					printf("Le buffer est plein!\n");

			break;

			case '2' :
			// Lire un caractère
				 c = (char)get_circ(Buffer);
				 if( c != EOF)
					printf("Le caractère lu est : %c\n",c);
				 else
					printf("Le buffer est vide!\n");
			break;

			case '3' : printf("Au revoir");break;

			default  : printf("Vérifier votre choix svpl ! \n");
		}
	}
	while( choix != '3' ) ;
}
CIRC * open_circ(int taille)
{
	CIRC * B;
	B = (CIRC *)malloc(taille);
	if(B == NULL)
	{
		return(EOF);
	}
	else
	{
		B->debut = (char *)B+(sizeof(CIRC));
		B->consommateur = (char *)B+(sizeof(CIRC));
		B->producteur = (char *)B+(sizeof(CIRC));
		B->fin = (char *)B+taille;

	}
	return(B);
}
int get_circ(CIRC *B)
{
	if(B->consommateur == B->producteur)
		return(EOF);
	if(++(B->consommateur)==B->fin)
		B->consommateur = B->debut;
	return (*(B->consommateur));

}
int put_circ(CIRC *B, int c)
{
	char *p;
	p=B->producteur + 1;
	if (p == B->fin)
	{
		p = B->debut;
	}
	if (p == B->consommateur)
	{
		return(EOF);
	}

  • p = c;
B->producteur = p; return (c); }

Conclusion :


J'avoue que c'est pas simple à comprendre. mais prenez le temps de le faire. ceci pourra vous servire un jour

A voir également

Ajouter un commentaire

Commentaires

Messages postés
4
Date d'inscription
mercredi 16 juin 2010
Statut
Membre
Dernière intervention
10 janvier 2012

Bonjour,
je dois également réaliser un buffer circulaire pour transférer des échantillons sonores
Je vais essayer de tester ton code et surtout de le modifier pour mon application mais je ne promets rien.
Tcho.
Utilisateur anonyme
En fait cette source a surtout pour effet de démontrer l'utilisation des pointeurs. Vu que les pointeurs ne sont pas simples d'utilisation.
Messages postés
1
Date d'inscription
vendredi 12 octobre 2007
Statut
Membre
Dernière intervention
21 décembre 2007

Pas intuitif les params pour open de CIRC la taille alouee n'est pas le nombre d'element dans ton buffer circulaire qui est taille - sizeof(CRIC)
Tu as en plus un petit bug si taile est < sizeof(CRIC).
Danc ce dernier cas tu n'as pas de place pour le stockage des donnees, tes pointeur de control vont aussi se telescper pour ne pas dire se mordre la queues :)
Autre detail sur l'open circ elle devrais retourner NULL en cas d'ehec pas EOF qui est un pointeur valid.

Perso je preffere gere un buffer circulaire via index (ou offset c'est idem) plutot que les pointeurs c'est surtourt pour eliminer les if dans la manipulation des pointeur sur entree sortie de donnes et le test de rebouclage typiquement
Buffer[In]=Data
In= (In+1)%TailleBufer
Si tu choisi TailleBuffer 2^N alors le modulo se limite a un '&'(2^N -1) encore plus rapide que les modulo ... ex N8
Buffer[In++]=Data;
In&=0xFF;

Dans un souci de perf comme la gestion d'une fifo sur interrupt cela peu avoir son importance...
Utilisateur anonyme
Pas mal ton analyse. Je pense que tu as l'habitude d'en faire. Je veux juste préciser quelques choses. La fin du buffer est marqué par le pointeur fin. On positionne le pointeur debut au debut, le nom me semble assez explicite, et le pointeur fin ben à la fin.

Aussi, le buffer est un buffer circulaire, ceux qui veut dire en d'autre terme qu'il n'as pas de fin, en fait le pointeur fin sert à indiquer à la fonction qu'il faut retourner au debut et en aucun cas de lui indiquer que le buffer est plein. le buffer est plein que quand le consommateur une mémoire avant le producteur. Le mot circulaire est très important dans l'interprétation de la source.

Merci de critiquer ma source. Si elle te plait pas personne ne t'interdit de créer la tienne et de la poster sur le site. Cette source et la comme exemple, si une personne veut l'utiliser pour gérer du son c'est son droit. Elle aura déjà les base. Je le répète encore une fois cette source est là pour montrer le fonctionnement des buffer circulaire. La personne qui est interessé la récupère et la modifie à sa convenance. Toi si t'en a pas besoin va voir ailleur. Si ton but est de rabaisser les autres je crois que tu n'a rien a foutre ici. Ha oui en fait les .h j'en déclare plusieurs pour la simple raison que si j'ai besoin d'autre fonction je me fais pas chier à les déclarer.

A oui pour finir ton int get_circ(CIRC *B, int * dest); est inutile dans cette source. Ca compliquerait la compréhension des buffers.
Messages postés
282
Date d'inscription
dimanche 1 avril 2001
Statut
Membre
Dernière intervention
12 février 2007

juste les deux choses qui m'ont parues les plus gênantes dans l'introduction :
"Etonnant pourtant" le lecteur n'est pas tenu de savoir qu'il faut une pause entre ces deux mots quand il lit.
"mais en le principe" il semble manquer le mot "fait"

mais après tout on est pas là pour juger ton Français, plus le code.
j'ai d'ailleurs une chose de plus à noter à ce niveau, puisque je viens seulement de remarquer que tu utilise ton consommateur et ton producteur pour déterminer la 'fin' du buffer, mais pourtant tu utilise la valeur EOF dans tes fonctions pour laisser à l'utilisateur la possibilité de savoir quand le buffer est finit.
Mais et si jamais l'utilisateur voulait créer un buffer circulaire, pour gérer du son comme c'est souvent le cas dans ce type de tampons ? La donnée du son et bien souvent une valeur arbitraire, pouvant contenir la valeur de EOF justement!
En résumé, quelqu'un utilisant ce code tel quel et gérant un tampon de son, peut de façon aléatoire voir son programme déconner puisque il pourrait croire que le tampon serait finit sans qu'il le soit, soit une perte de données.
Pourquoi n'utilise pas plutôt un modèle de fonction get, dont l'entête serait plutôt :
int get_circ(CIRC *B, int * dest);

Et à la place de renvoyer la valeur, renverrait le status (0 en cas de réussite, 1 en cas d'echec par exemple), et prendrait en argument de sortie 'dest', l'octet à lire.
Rien ne changerait du côté de la fonction put, juste ses valeurs de retour, et ce n'est pas plus compliqué puisque la structure s'y prête déjà. Et après tout cela tu pourras commencer à juger le code source comme de niveau "intermédiaire" (il est très éloigné des codes experts que l'on peut trouver sur ce site)

Pour les commentaires, si je le reproche c'est parce que j'ai moi aussi la mauvaise habitude de ne pas en faire, mais comme tout programmeur, on sait que "plus-tard" se résume bien souvent à jamais.
Ah et les .h, évites aussi d'inclure sans savoir ceux que tu connais, ça fait un peu "tâche" dans un code source. Normalement, stdio.h et stdlib.h devraient te suffirent.

En espérant pouvoir noter en remontant la moyenne de cette source.
Afficher les 8 commentaires

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.