/* 

CS 203. Correction de la feuille 1 

Pour compiler ce fichier, il faut faire appel a la librairie mathematique avec l'option -lm

Credit : certains des programmes presentes ont ete realises par Pierre Cohort

*/

#include <stdio.h>
#include <math.h>  /* pour la fonctions cos et eventuellement la constante Pi */

/*
M_PI est utilise dans l'exercice II

La commande suivante n'est pas necessaire sauf pour etre dans la norme ANSI
car elle est dans math.h
*/

# define M_PI		3.14159265358979323846


/* Exercice I */
int main_exercice1()
{
  printf("Leonard de Vinci\n\n\n"); 
  /* commentaire : le caractere de retour a la ligne \n doit etre
     inclus dans la chaine */
  return(0);
}



/* Exercice II */  

int main_exercice2() {
  printf("cos(Pi/6)=%f\ncos(Pi/2)=%f\n",cos(M_PI/6),cos(M_PI/3));
  return(0);
  /* le programme affiche
     cos(Pi/3)=0.866025
     cos(Pi/6)=0.500000
  */
}


/* Exercice III */

int fois_deux(int a)
{
  return 2*a;
  /* commentaire : il est inutile de placer le resultat dans
     une variable intermediaire avant de le retourner */ 
}

int main_exercice3()
{
  printf("2*%d = %d\n\n\n\n",9,fois_deux(9));
  return(0);
}
  


/* exercice IV */

double LameLambda(double E, double v)
     /* commentaire : on doit specifier le type de tous les parametres de 
	la fonction. La syntaxe (double E,v) est interdite.  */
{
  return E*v/((1+v)*(1-2*v));
}
/* commentaires : 
    - lorsque l'on appelle la fonction avec v=-1 ou v=0.5,
      une division par zero est produite et le resultat renvoye est 
      inf (l'infini).
    - dans l'addition 1+v, le nombre 1 est de type entier mais le 
      compilateur le convertit automatiquement en un double car v
      est de type double. 
      On peut faire soi-meme la convertion en ecrivant 1.+v
    - penser a ecrire toute les multiplications. Par exemple,
      (1+v)(1-2*v) n'est pas interprete comme la multiplication
      des deux termes entre parentheses.  */ 

double LameMu(double E, double v)
{
  return E/(2*(1+v));
}

int main_exercice4() 
{  
  double E=1.23,v=2.45;
  printf("E=%f , v=%f : Lambda=%f\n",E,v,LameLambda(E,v));
  printf("E=%f , v=%f : Mu=%f\n\n\n\n",E,v,LameMu(E,v));
  return 0;
}



/* exercice V */
/* les identificateurs NON ACCEPTES sont :
      
      fonction-1   (a cause du signe - ; le compilateur comprend
                    qu'il faut retrancher 1 a l'identificateur fonction)
       
      3   (c'est un nombre) 
      
      3e_jour    (commence par un nombre)  */



/* exercice VI */

int main_exercice6()
{
  int A, B, C, D, X, Y;

  A=20; B=5; C=-10; D=2; X=12; Y=15;
  printf("A=%d; B=%d; C=%d; D=%d; X=%d; Y=%d\n",A,B,C,D,X,Y);
  printf("(5*X)+2*((3*B)+4)  = %d\n", (5*X)+2*((3*B)+4) );
  printf("A=%d; B=%d; C=%d; D=%d; X=%d; Y=%d\n\n\n",A,B,C,D,X,Y);
  /* reponse :  98 . Aucune variable ne change de valeur. */

  A=20; B=5; C=-10; D=2; X=12; Y=15;
  printf("A=%d; B=%d; C=%d; D=%d; X=%d; Y=%d\n",A,B,C,D,X,Y);
  printf("(5*(X+2)*3)*(B+4)  = %d\n", (5*(X+2)*3)*(B+4) );
  printf("A=%d; B=%d; C=%d; D=%d; X=%d; Y=%d\n\n\n",A,B,C,D,X,Y);
  /* reponse :  1890 . Different du precedent; attention aux priorites dictees 
     par les parentheses. Aucune variable ne change de valeur. */
  
  A=20; B=5; C=-10; D=2; X=12; Y=15;
  printf("A=%d; B=%d; C=%d; D=%d; X=%d; Y=%d\n",A,B,C,D,X,Y);
  printf("A == (B=5)  = %d\n", A == (B=5) );
  printf("A=%d; B=%d; C=%d; D=%d; X=%d; Y=%d\n\n\n",A,B,C,D,X,Y);
  /* reponse : 0 . L'expression (B=5) vaut 5 car le programme affecte
     d'abord la valeur 5 a B puis evalue l'expression (B) qui vaut donc
     (5). Ensuite, (A == (B=5)) vaut (A == 5); cette
     expression n'est pas vraie et vaut donc 0 . Aucune variable ne change
     de valeur (B valait deja 5)*/

  A=20; B=5; C=-10; D=2; X=12; Y=15;
  printf("A=%d; B=%d; C=%d; D=%d; X=%d; Y=%d\n",A,B,C,D,X,Y);
  printf("A += (X+5)  = %d\n", A += (X+5) );
  printf("A=%d; B=%d; C=%d; D=%d; X=%d; Y=%d\n\n\n",A,B,C,D,X,Y);
  /* reponse : 37 . L'expression (X+5) est d'abord evaluee : elle vaut
     17. Ce nombre est ensuite ajoute a la variable A (operateur +=) qui
     vaut donc finalement 37. L'expression initiale vaut A en fin
     de calcul, soit 37. La variable A change de valeur */ 
  
  A=20; B=5; C=-10; D=2; X=12; Y=15;
  printf("A=%d; B=%d; C=%d; D=%d; X=%d; Y=%d\n",A,B,C,D,X,Y);
  printf("A != (C *= (-D))  = %d\n", A != (C *= (-D)) );
  printf("A=%d; B=%d; C=%d; D=%d; X=%d; Y=%d\n\n\n",A,B,C,D,X,Y);
  /* reponse : 0 . L'expression C *= (-D) multiplie C par -D et
     met le resultat dans C qui vaut alors 20 ( -10 * (-2) ).
     L'expression initiale vaut alors A != 20 ce qui est faux
     car A vaut 20. Le resultat retourne est donc 0. La variable
     C change de valeur. */

  A=20; B=5; C=-10; D=2; X=12; Y=15;
  printf("A=%d; B=%d; C=%d; D=%d; X=%d; Y=%d\n",A,B,C,D,X,Y);
  printf("A *= C+(X-D)  = %d\n", A *= C+(X-D) );
  printf("A=%d; B=%d; C=%d; D=%d; X=%d; Y=%d\n\n\n",A,B,C,D,X,Y);
  /* reponse : 0 . L'expression C+(X-D) vaut 0 ( -10+(12-2) ).
     A est ensuite multiplie par ce nombre (operateur *=) et vaut
     donc finalement 0. La variable A change de valeur. */

  A=20; B=5; C=-10; D=2; X=12; Y=15;
  printf("A=%d; B=%d; C=%d; D=%d; X=%d; Y=%d\n",A,B,C,D,X,Y);
  printf("A %%= D++  = %d\n", A %= D++ );
  printf("A=%d; B=%d; C=%d; D=%d; X=%d; Y=%d\n\n\n",A,B,C,D,X,Y);
  /* reponse : 0 . L'expression est d'abord evaluee comme
     A %= D et D est seulement ensuite incremente de 1 car l'operateur ++
     est place apres la variable D.
     L'expression vaut donc 20%2 = 0 . Les deux variables A et D changent
     de valeur.*/
  
  A=20; B=5; C=-10; D=2; X=12; Y=15;
  printf("A=%d; B=%d; C=%d; D=%d; X=%d; Y=%d\n",A,B,C,D,X,Y);
  printf("A %%= ++D  = %d\n", A %= ++D );
  printf("A=%d; B=%d; C=%d; D=%d; X=%d; Y=%d\n\n\n",A,B,C,D,X,Y);
  /* reponse : 2 . Contrairement a l'exemple precedent, l'operateur ++
     est place avant la variable D : D est donc d'abord incrementee
     et l'expression est evaluee comme A %= (D+1). 
     L'expression vaut donc 20%3 soit 2*/
  
  A=20; B=5; C=-10; D=2; X=12; Y=15;
  printf("A=%d; B=%d; C=%d; D=%d; X=%d; Y=%d\n",A,B,C,D,X,Y);
  printf("(X++)*(A+C)  =%d\n",(X++)*(A+C)); 
  printf("A=%d; B=%d; C=%d; D=%d; X=%d; Y=%d\n\n\n",A,B,C,D,X,Y);
  /* reponse : 120 . L'expression est en fait evaluee comme
     X*(A+C) et c'est seulement apres que la variable X est incrementee
     de 1. L'expression vaut donc 120. Seule la variable X change 
     de valeur. */

  A=20; B=5; C=-10; D=2; X=12; Y=15;
  printf("A=%d; B=%d; C=%d; D=%d; X=%d; Y=%d\n",A,B,C,D,X,Y);
  printf("A=X*(B<C)+Y*!(B<C)  = %d\n", A = X*(B<C)+Y*!(B<C) );
  printf("A=%d; B=%d; C=%d; D=%d; X=%d; Y=%d\n\n\n",A,B,C,D,X,Y);
  /* reponse : 15 . L'expression (B<C) est fausse et vaut donc 0.
     L'expression !(B<C) est vraie et vaut donc 1. L'expression
     X*(B<C)+Y*!(B<C) vaut donc Y. Cette valeur est mise dans A.
     La valeur finale de l'expression est A, soit 15. La variable
     A change de valeur. */
  
  A=20; B=5; C=-10; D=2; X=12; Y=15;
  printf("A=%d; B=%d; C=%d; D=%d; X=%d; Y=%d\n",A,B,C,D,X,Y);
  printf("!(X-D+C)||D  = %d\n", !(X-D+C)||D );
  printf("A=%d; B=%d; C=%d; D=%d; X=%d; Y=%d\n\n\n",A,B,C,D,X,Y);
  /* reponse : 1 . L'operateur ! est prioritaire sur ||. L'expression
     est donc evaluee comme (!(X-D+C))||(D). La variable D vaut 2 et, 
     en tant qu'expression booleenne, est consideree comme vraie. 
     Puisque l'operateur precedent D est || (ou), 
     la valeur finale de l'expression est 1 
     (pas besoin d'evaluer !(X-D+C) car on a la fois vrai||vrai=vrai
     et faux||vrai=vrai). Aucune variable ne change de valeur. */

  A=20; B=5; C=-10; D=2; X=12; Y=15;
  printf("A=%d; B=%d; C=%d; D=%d; X=%d; Y=%d\n",A,B,C,D,X,Y);
  printf("A&&B||!0&&C&&!D  = %d\n", A&&B||!0&&C&&!D );
  printf("A=%d; B=%d; C=%d; D=%d; X=%d; Y=%d\n\n\n",A,B,C,D,X,Y);
  /* reponse : 1 . L'operateur && (et) etant prioritaire sur || (ou),
     l'expression est evaluee comme  (A&&B) || ((!0)&&C&&(!D)).
     Puisque A et B sont non nuls, ces variables, en tant 
     qu'expressions booleennes, sont considerees comme vraies :
     l'expression A&&B vaut donc 1. L'expression finale est donc 
     vraie et vaut donc 1. Aucune variable ne change de valeur. */ 
 
  A=20; B=5; C=-10; D=2; X=12; Y=15;
  printf("A=%d; B=%d; C=%d; D=%d; X=%d; Y=%d\n",A,B,C,D,X,Y);
  printf("((A&&B)||(!0&&C))&&!D  = %d\n", ((A&&B)||(!0&&C))&&!D );
  printf("A=%d; B=%d; C=%d; D=%d; X=%d; Y=%d\n\n\n",A,B,C,D,X,Y);
  /* reponse : 0 . L'expression est evaluee comme
     ((A&&B)||(!0&&C)) && (!D). Or, Puisque D vaut 2, !D est 
     considere comme faux. L'expression initiale est donc fausse
     ( (...) && faux  est toujours faux, quel que soit la valeur
     de (...) ). Aucune variable ne change de valeur. */

  return 0;
}



/* exercice VII */

int f(int x)  
     /* Fonction qui ajoute 1 a sont argument
        ENTREE : entier x 
        SORTIE : entier x+1
     */
{
  /*  Le x qui apparait dans cette fonction est une COPIE du x qui 
      qui apparait dans le programme principal */
  int y;      /* declaration de la variable y de type entier */
  y=++x;      /* x est incremente puis affecte a y */
  return y;   /* la fonction retourne y */
}

int main_exercice7() 
{
  int x=1, y;   /* declaration des variables x et y de type entier, 1 est affecte a x */
  y=f(x);     /* y=f(x) donc y recoit 2 */
  printf("%d %d\n",x,y);  /* affichage de x et y */
  return 0;   /* le programme retourne 0 au shell */
}



/* main */

/* On anticipe un peu, ce qui suit permet de faire un menu */

int main()
{
  int n;

  printf("Feuille d'exercices 1\n");
  printf("Choix de l'exercice : ");
  scanf("%d",&n);

  switch (n) {
  case 1: main_exercice1(); break;
  case 2: main_exercice2(); break;
  case 3: main_exercice3(); break;
  case 4: main_exercice4(); break;
  case 6: main_exercice6(); break;
  case 7: main_exercice7(); break;
  }

  return 0;
}