Cours C++
Révisions de C
Correction du TP 0.1

Alain Plantec

On désire développer un gestionnaire de rendez-vous en mémoire. Un rendez-vous comprend le nom et le numéro de téléphone de la personne avec qui on a rendez-vous, le lieu et la date du rendez-vous.

1 Première version


#include <stdio.h>

#define LGNOM 100
#define LGNUM 20
#define LGLIEU 100
#define LGDATE 20
#define TAILLE_CARNET 100

struct TRendezVous
{
  char nom[LGNOM];
  char num_tel[LGNUM];
  char lieu[LGLIEU];
  char date[LGDATE];

  int valide; /* ajoute pour les besoins de mise en oeuvre */
};

struct TCarnet 
{
  int nb;
  struct TRendezVous rdvs[TAILLE_CARNET]; /* tableau de struct TRendezVous */
};

void rendez_vous_creer(struct TRendezVous * _this);
void rendez_vous_detruire(struct TRendezVous * _this);
void rendez_vous_afficher(const struct TRendezVous * _this, FILE * _out);
void rendez_vous_saisir(struct TRendezVous * _this, FILE * _in);

void carnet_creer(struct TCarnet * _this);
void carnet_detruire(struct TCarnet * _this);
bool carnet_ajouter_rendez_vous(struct TCarnet * _this, const struct TRendezVous *);
void carnet_rechercher_rendez_vous(const struct TCarnet * _this, const char *, struct TCarnet * _res);
void carnet_retirer_rendez_vous(struct TCarnet * _this, const char * nom, const char * _date);
void carnet_afficher(const struct TCarnet * _this, FILE * _out);

void rendez_vous_creer(struct TRendezVous * _this)
{
  _this->nom[0] = 0;
  _this->num_tel[0] = 0;
  _this->lieu[0] = 0;
  _this->date[0] = 0;
  _this->valide = 0;
}

void rendez_vous_detruire(struct TRendezVous * _this)
{
  /* rien a faire */
}

void rendez_vous_afficher(const struct TRendezVous * _this, FILE * _out)
{
  fprintf(_out, "'%s' '%s' '%s' '%s'", _this->nom, _this->num_tel, _this->lieu, _this->date);
}


void rendez_vous_saisir(struct TRendezVous * _this, FILE * _in)
{
  /* Attention, pas de blanc dans les champs, il faudrait une fonction de saisie
     caractere par caractere pour accepter les blancs
  */
  fscanf(_in, "%s %s %s %s", _this->nom, _this->num_tel, _this->lieu, _this->date);
  fflush(_in);
  _this->valide = 1;
}

void carnet_creer(struct TCarnet * _this)
{
  int no;
  _this->nb = 0;
  for (no = 0; no < TAILLE_CARNET; no++) {
    rendez_vous_creer(&(_this->rdvs[no]));
  }
}

void carnet_detruire(struct TCarnet * _this)
{
  /* rien a faire */
}

bool carnet_ajouter_rendez_vous(struct TCarnet * _this, const struct TRendezVous * _rdv)
{
  if (_this->nb < TAILLE_CARNET) {
    _this->rdvs[_this->nb] = *_rdv;
    _this->rdvs[_this->nb].valide = 1;
    _this->nb++;
    return true;
  }
  return false;
}

void carnet_rechercher_rendez_vous(const struct TCarnet * _this, const char * _date, struct TCarnet * _res)
{
  int no;
  for (no = 0; no < _this->nb; no++) {
    if (_this->rdvs[no].valide && strcmp(_date, _this->rdvs[no].date) == 0) {
      carnet_ajouter_rendez_vous(_res, &_this->rdvs[no]);
    }
  }
}

void carnet_retirer_rendez_vous(struct TCarnet * _this, const char * _nom, const char * _date)
{
  int no;
  for (no = 0; no < _this->nb; no++) {
    if (_this->rdvs[no].valide) {
      if (strcmp(_nom, _this->rdvs[no].nom) == 0 && strcmp(_date, _this->rdvs[no].date) == 0) {
	/* on marque le rendez-vous comme invalide */
	_this->rdvs[no].valide = 0;
      }
    }
  }
}

void carnet_afficher(const struct TCarnet * _this, FILE * _out)
{
  int no;
  for (no = 0; no < _this->nb; no++) {
    if (_this->rdvs[no].valide) {
      rendez_vous_afficher(&_this->rdvs[no], _out);
      fprintf(_out, "\n");
    }
  }
}


main()
{
  char c = 0;
  struct TCarnet carnet;
  carnet_creer(&carnet);

  while (c != 'q') {
    fflush(stdin);
    fflush(stdout);
    printf("(a)jouter (r)echercher (s)upprimer (l)ister (q)uitter\n");
    scanf("%c", &c);
    switch (c) {
      case 'a' : {
	struct TRendezVous nouv;
	rendez_vous_creer(&nouv);
	printf("nom, num.tel. lieu et date : ");
	rendez_vous_saisir(&nouv, stdin);
	if (!carnet_ajouter_rendez_vous(&carnet, &nouv)) {
	  fprintf(stderr, "Carnet plein\n");
	}
	rendez_vous_detruire(&nouv);
	break;
      }
      case 's' : {
	char bufdate[1024];
	char bufnom[1024];
	printf("nom et date : ");
	fflush(stdin);
	scanf("%s %s", bufnom, bufdate);
	carnet_retirer_rendez_vous(&carnet, bufnom, bufdate);
	break;
      }
      case 'l' : {
	carnet_afficher(&carnet, stdout);
	break;
      }
      case 'r' : {
	char bufdate[1024];
	struct TCarnet resultat;
	carnet_creer(&resultat);
	printf("date : ");
	fflush(stdin);
	scanf("%s", bufdate);
	carnet_rechercher_rendez_vous(&carnet, bufdate, &resultat);
	carnet_afficher(&resultat, stdout);
	carnet_detruire(&resultat);
	break;
      }
    }
  }
  carnet_detruire(&carnet);
}



2 Seconde version


#include <stdio.h>

#define INPUT_BUF 1024 /* pour les entrees au clavier */

struct TRendezVous
{
  char * nom;
  char * num_tel;
  char * lieu;
  char * date;
};

struct TCarnet 
{
  int nb;
  struct TRendezVous ** rdvs; /* tableau de pointeurs sur des struct TRendezVous */
};

void rendez_vous_creer(struct TRendezVous * _this);
void rendez_vous_detruire(struct TRendezVous * _this);
void rendez_vous_afficher(const struct TRendezVous * _this, FILE * _out);
void rendez_vous_saisir(struct TRendezVous * _this, FILE * _in);

// Deux fonctions suplementaires utiles
void rendez_vous_modifier(struct TRendezVous * _this, 
			  const char * nom, 
			  const char * num_tel, 
			  const char * lieu, 
			  const char * date);
void rendez_vous_copier(struct TRendezVous * _this, const struct TRendezVous * _autre);


void carnet_creer(struct TCarnet * _this);
void carnet_detruire(struct TCarnet * _this);
void carnet_ajouter_rendez_vous(struct TCarnet * _this, const struct TRendezVous *);
void carnet_rechercher_rendez_vous(const struct TCarnet * _this, const char *, struct TCarnet * _res);
void carnet_retirer_rendez_vous(struct TCarnet * _this, const char * nom, const char * _date);
void carnet_afficher(const struct TCarnet * _this, FILE * _out);

static char * util_chaine_vide()
{
  char * buf = new char;
  *buf = 0;
  return buf;
}

static char * util_modifier_chaine(char ** _dst, const char * _src)
{
  if (strlen(*_dst) < strlen(_src)) {
    delete *_dst;
    *_dst = new char [strlen(_src) + 1];
  }
  strcpy(*_dst, _src);
}

void rendez_vous_creer(struct TRendezVous * _this)
{
  _this->nom = util_chaine_vide();
  _this->num_tel = util_chaine_vide();
  _this->lieu = util_chaine_vide();
  _this->date = util_chaine_vide();
}

void rendez_vous_detruire(struct TRendezVous * _this)
{
  delete _this->nom;
  delete _this->num_tel;
  delete _this->lieu;
  delete _this->date;
}

void rendez_vous_modifier(struct TRendezVous * _this, 
			  const char * nom, 
			  const char * num_tel, 
			  const char * lieu, 
			  const char * date)
{
  util_modifier_chaine(&(_this->nom), nom);
  util_modifier_chaine(&(_this->num_tel), num_tel);
  util_modifier_chaine(&(_this->lieu), lieu);
  util_modifier_chaine(&(_this->date), date);
}

void rendez_vous_copier(struct TRendezVous * _this, const struct TRendezVous * _autre)
{
  rendez_vous_modifier(_this, _autre->nom, _autre->num_tel, _autre->lieu, _autre->date);
}

void rendez_vous_afficher(const struct TRendezVous * _this, FILE * _out)
{
  fprintf(_out, "'%s' '%s' '%s' '%s'", _this->nom, _this->num_tel, _this->lieu, _this->date);
}

void rendez_vous_saisir(struct TRendezVous * _this, FILE * _in)
{
  /* Attention, pas de blanc dans les champs, il faudrait une fonction de saisie
     caractere par caractere pour accepter les blancs
  */
  char nom[INPUT_BUF], num_tel[INPUT_BUF], lieu[INPUT_BUF], date[INPUT_BUF];
  fscanf(_in, "%s %s %s %s", nom, num_tel, lieu, date);
  rendez_vous_modifier(_this, nom, num_tel, lieu, date);
  fflush(_in);
}

void carnet_creer(struct TCarnet * _this)
{
  _this->nb = 0;
  _this->rdvs = new struct TRendezVous *; 
}

void carnet_detruire(struct TCarnet * _this)
{
  int no;
  // il faut detruire les rendez-vous contenus
  for (no = 0; no < _this->nb; no++) {
    // on detruit le contenu d'un rendez-vous
    rendez_vous_detruire(_this->rdvs[no]);
    // on desalloue le rendez-vous (on sait qu'il a ete alloue par carnet_ajouter_rendez-vous)
    delete _this->rdvs[no];
  }
  // et recuperer la memoire allouee pour le tableau de pointeurs
  delete _this->rdvs;
}

void carnet_ajouter_rendez_vous(struct TCarnet * _this, const struct TRendezVous * _rdv)
{
  int no;
  // On alloue et construit le nouveau rendez-vous
  struct TRendezVous * nouv_rdv = new struct TRendezVous;
  rendez_vous_creer(nouv_rdv);
  rendez_vous_copier(nouv_rdv, _rdv);
  
  // On recherche une position utilisable entre 0 et _this->nb 
  // (la place d'un rendez-vous retire par carnet_retirer_rendez_vous)
  for (no = 0; no < _this->nb; no++) {
    if (_this->rdvs[no] == NULL) {
      break;
    }
  }

  // ici, si no < _this->nb, c'est qu'on a trouve une place, sinon, il faut agrandir le tableau
  if (no == _this->nb) {
    int noi;
    struct TRendezVous ** old_rdvs = _this->rdvs;
    _this->rdvs = new struct TRendezVous * [_this->nb + 1];

    // on a une case (pour un pointeur) de plus dans _this->rdvs
    _this->nb++;

    // on recopie les anciens pointeurs
    for (noi = 0; noi < _this->nb - 1; noi++) {
      _this->rdvs[noi] = old_rdvs[noi];
    }
    delete old_rdvs;
  }

  // on peut affecter le nouveau rendez-vous
  _this->rdvs[no] = nouv_rdv;
}

void carnet_rechercher_rendez_vous(const struct TCarnet * _this, const char * _date, struct TCarnet * _res)
{
  int no;
  for (no = 0; no < _this->nb; no++) {
    if (_this->rdvs[no] != NULL && strcmp(_date, _this->rdvs[no]->date) == 0) {
      carnet_ajouter_rendez_vous(_res, _this->rdvs[no]);
    }
  }
}

void carnet_retirer_rendez_vous(struct TCarnet * _this, const char * _nom, const char * _date)
{
  int no;
  for (no = 0; no < _this->nb; no++) {
    if (_this->rdvs[no]) {
      if (strcmp(_nom, _this->rdvs[no]->nom) == 0 && strcmp(_date, _this->rdvs[no]->date) == 0) {
	// on detruit le rendez-vous
	rendez_vous_detruire(_this->rdvs[no]);
	// on desalloue le pointeur
	delete _this->rdvs[no];
	// on marque la position comme reutilisable
	_this->rdvs[no] = NULL;
      }
    }
  }
}

void carnet_afficher(const struct TCarnet * _this, FILE * _out)
{
  int no;
  for (no = 0; no < _this->nb; no++) {
    if (_this->rdvs[no] != NULL) {
      rendez_vous_afficher(_this->rdvs[no], _out);
      fprintf(_out, "\n");
    }
  }
}


// C'est exactement le meme main que pour la version precedente
main()
{
  char c = 0;
  struct TCarnet carnet;
  carnet_creer(&carnet);

  while (c != 'q') {
    fflush(stdin);
    fflush(stdout);
    printf("(a)jouter (r)echercher (s)upprimer (l)ister (q)uitter\n");
    scanf("%c", &c);
    switch (c) {
      case 'a' : {
	struct TRendezVous nouv;
	rendez_vous_creer(&nouv);
	printf("nom, num.tel. lieu et date : ");
	rendez_vous_saisir(&nouv, stdin);
	carnet_ajouter_rendez_vous(&carnet, &nouv);
	rendez_vous_detruire(&nouv);
	break;
      }
      case 's' : {
	char bufdate[1024];
	char bufnom[1024];
	printf("nom et date : ");
	fflush(stdin);
	scanf("%s %s", bufnom, bufdate);
	carnet_retirer_rendez_vous(&carnet, bufnom, bufdate);
	break;
      }
      case 'l' : {
	carnet_afficher(&carnet, stdout);
	break;
      }
      case 'r' : {
	char bufdate[1024];
	struct TCarnet resultat;
	carnet_creer(&resultat);
	printf("date : ");
	fflush(stdin);
	scanf("%s", bufdate);
	carnet_rechercher_rendez_vous(&carnet, bufdate, &resultat);
	carnet_afficher(&resultat, stdout);
	carnet_detruire(&resultat);
	break;
      }
    }
  }
  carnet_detruire(&carnet);
}







Plantec Alain
2002-02-21