#include <stdio.h>
#include <stdlib.h>
#include <string.h>


/* prototypes des fonctions, necessaires si declarees apres le main */
char* alloue_chaine(int longueur);
void matrix_affiche(int **t, int x, int y);
int cherche_min(int* tableau, int longueur);
int cherche_min_ptrs(int* tableau, int longueur);
void swap(float *a, float *b);
int** matrix_alloue(int x, int y);
void matrix_affiche_ptrs(int **t, int x, int y);
void matrix_affiche_ptrs_2(int t[][], int x, int y);
void alloue_chaine_2(char** chaine, int longueur);



/* pas d'espaces apres le \ */
#define ABS(X) \
(X > 0) ? X : -(X)


int 
main(void)
{
  /*   char* str = alloue_chaine(10); */
  char* str; 
  int tab[5][5] = {{8, 4, 1, 3, 2}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}};
  float a1 = 1.0, a2 = 2.0;
  int i, j;
  int **Neo;

  alloue_chaine_2(&str, 10); 

  sprintf(str, "012345678");
  printf("%s", str);

  printf("\npos plus petit: %d", cherche_min_ptrs(tab[0], 5));

  swap(&a1, &a2);
  printf("\n%f, %f", a1, a2);

  Neo = matrix_alloue(3, 6);
  matrix_affiche_ptrs(Neo , 3, 6);


  printf("\n%d", ABS(-5));
  printf("\n%d", ABS(2 - 4));


  free(str);  
  free(Neo);

  return EXIT_SUCCESS;
} 


/* FAIT */
/* creer une fonction qui affiche un tableau bidimensionnel d'entiers
   tableau dynamique, parcours sans pointeurs */
void matrix_affiche(int **t, int x, int y)
{
  int i, j;

  for (i = 0; i < x; i++)
    {
      printf("\n");
      for (j = 0; j < y; j++) printf("%d ;",t[i][j]);
    }
}
/* marche avec t[5][5] comme type et tab comme valeur, ou avec une
   matrice allouee dynamiquement */


/* FAIT */
/* creer une fonction qui alloue un tableau de caracteres de longueur donnee */
char* alloue_chaine(int longueur)
{
  char *adresse;

  if ((adresse = (char*) calloc(longueur, sizeof(char))) == NULL)
    {fprintf(stderr, "\n plus de memoire"); exit(1);}
  else 
    {return adresse;}   
}


/* A corriger */
/* creer une fonction recherchant la position du plus petit element
   d'un tableau d'entiers non-trie */
int cherche_min(int* tableau, int longueur)
{
  int i, min_pos;

  for (i = 0, min_pos = i; i < longueur; i++) 
    {
      if (tableau[i] < tableau[min_pos]) min_pos = i;
    }
  
  return min_pos;
} 
/* renvoie toujours un entier positif */


/* A FAIRE */
/* idem avec les pointeurs */
int cherche_min_ptrs(int* tableau, int longueur)
{
  int *i, *min;

  for (i = tableau, min = tableau; i < tableau + longueur; i++) 
    {
      if (*i < *min) min = i;
    }
  
  return min - tableau;
} 


/* FAIT */
/* creer une fonction inversant la valeur de deux variables flottantes */
void swap(float *a, float *b)
{
  float tmp;

  tmp = *a;
  *a = *b; *b = tmp;
}
/* on ne peut JAMAIS modifier un parametre d'entree. On doit donc
   passer l'adresse d'une variable que l'on veut modifier */


/* A FAIRE */
/* allouer une matrice de dimensions x * y d'entiers */
int** matrix_alloue(int x, int y)
{
  int i;
  int **row = (int **) malloc (x * sizeof(int*));

  if (row == NULL) {fprintf(stderr, "\n plus de memoire"); exit(1);}

  for (i = 0; i < x; i++)
    {
      if ((row[i] = (int*) malloc (y * sizeof(int))) == NULL)
	{fprintf(stderr, "\n plus de memoire"); exit(1);}
    }

  return row;
}


/* A FAIRE */
/* creer une fonction qui affiche un tableau bidimensionnel d'entiers
   (declare dynamiquement), parcours version pointeurs*/
void matrix_affiche_ptrs(int **t, int x, int y)
{
  int **mat, *row;

  for (mat = t; mat < t + x; mat++) 
    {
      printf("\n");
      for (row = *mat; row < *mat + 10; row++) 
	printf("%d ;", *row);
    }
}


/* A FAIRE */
/* creer une fonction qui affiche un tableau bidimensionnel d'entiers
   (declare statiquement), parcours version pointeurs*/
void matrix_affiche_ptrs_2(int t[][], int x, int y)
{
  int *cursor;
  
  for (cursor = (int *)t; cursor < (int *)t + 20 * 10; cursor++)
    {printf("\n%d", *cursor);}
}


/* IMPORTANT: 
 
 * un tableau bidimensionnel statique t[][] est implemente sous
   forme d'un seul tableau dans lequel les lignes sont mises bout a bout.
 * un tableau bidimensionnel dynamique est implemente sous forme d'un tableau 
   de pointeurs, contenant l'adresse de tableaux d'elements.
   
   Si l'operateur [][] permet d'acceder aux elements des tableaux
   statiques ou dynamiques malgre leurs differences d'implementation,
   le fait de declarer int t[][] comme parametre d'une fonction oblige
   a fournir un tableau statique.

   Il est impossible de faire passer un tableau statique pour un
   tableau dynamique (par un cast) vu qu'ils sont implementes differemment!!
   
*/


/* Le retour de swap! */


/* creer une fonction qui alloue un tableau de caracteres de longueur
   donnee sans retourner l'adresse d'allocation par return*/
void alloue_chaine_2(char** chaine, int longueur)
{
  if ((*chaine = (char*) calloc(longueur, sizeof(char))) == NULL)
    {fprintf(stderr, "\n plus de memoire"); exit(1);}
}
/* il faut passer l'adresse du pointeur sur la chaine pour ensuite le modifier */


/* Programmer la macro valeur absolue */  

/* Programmer une macro SWAP (une variable supplementaire peut etre necessaire) */
/* reverse the values of A and B 
   requires extra variable of same type for value swapping */
#define REVERSE_VALUES(A, B, SWP) \
SWP = B; B = A; A = SWP;

/* faire: cpp nomfichier.c pour voir ce que donne le code produit par
   une macro */

/* Fichiers: savoir faire un programme qui ecrit dans un fichier et le relit */





