1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
| #include <stdio.h>
#include <stdlib.h>
#include <time.h>
int **create_mat(int, int);
void print_sum(int **, int **, int, int);
void desalloc(int **, int);
int alea(int n);
int main(int argc, char **argv)
{
/* -tc- C'est sans doute une question de preference personnelle, mais c'est
selon moi une bonne pratique de ne definir qu'une varaible par ligne et
d'initialiser les pointeurs a la valeur NULL (signifie que l'adresse est
invalide). */
int **mat1 = NULL;
int **mat2 = NULL;
/* -tc- J'utilise de preference le type size_t pour representer les
dimensions d'une matrice. */
int nligs = 0;
int ncols = 0;
char *pend = NULL;
/* -tc- Le generateur de nombres pseudo-aleatoires doit etre initialise une
seule fois au debut du programme, et non a chaque appel de create_mat().*/
srand(time(NULL));
if (argc != 3)
{
fprintf(stderr, "Usage : %s n p\n", argv[0]);
/* -tc- main() ne peut retourner de maniere portable que 0, EXIT_SUCCESS
ou EXIT_FAILURE. En principe, je n'aime pas trop les return sauvages,
mais bon, les gouts et les couleurs... */
return EXIT_FAILURE;
}
/* -tc- Pour la representation en chaine de caractere d'un entier, je
prefere utiliser la fonction strtol() qui permet une gestion d'erreur
beaucoup plus fine de atoi() devenue (inofficiellement?) obsolete. */
nligs = strtol(argv[1], &pend, 10);
/* -tc- On teste que l'entier passe par l'utilisateur en etait bien un. En
principe, il faudrait encore traiter les debordements eventuels de
capacite. */
if (*pend != 0)
{
fprintf(stderr, "Erreur: l'argument n doit etre un nombre!\n");
fprintf(stderr, "Usage : %s n p\n", argv[0]);
/* -tc- Meme remarque que plus haut consernant les return sauvages... */
return EXIT_FAILURE;
}
ncols = strtol(argv[2], &pend, 10);
if (*pend != 0)
{
fprintf(stderr, "Erreur: l'argument p doit etre un nombre!\n");
fprintf(stderr, "Usage : %s n p\n", argv[0]);
/* -tc- Meme remarque que plus haut consernant les return sauvages... */
return EXIT_FAILURE;
}
/* -tc- Il faut tester que la creation des matrices n'a pas echoue! */
mat1 = create_mat(nligs, ncols);
if (mat1 != NULL)
{
mat2 = create_mat(nligs, ncols);
if (mat2 != NULL)
{
print_sum(mat1, mat2, atoi(argv[1]), atoi(argv[2]));
desalloc(mat2, nligs), mat2 = NULL;
}
desalloc(mat1, nligs), mat1 = NULL;
}
return 0;
}
int **create_mat(int n, int p)
{
/* -tc- C'est une bonne pratique d'initialiser les pointeurs a la valeur
NULL. */
int **matrice = NULL;
/* -tc- En C, il est deconseille de caster la valeur retournee par malloc(). */
matrice = malloc(n * sizeof *matrice);
/* -tc- Par contre, il est fortement conseille de tester la valeur retournee
par malloc(). */
if (matrice != NULL)
{
int i, j;
int err = 0;
/* -tc- Je recommande de toujours utiliser les accolades, meme lorsque
la boucle possede une instruction unique. C'est beaucoup plus lisble! */
for (i = 0; err == 0 && i < n; i++)
{
matrice[i] = malloc(p * sizeof *matrice[i]);
/* -tc- La aussi, on teste la valeur retournee par malloc(). En cas
d'echec, on n'oublie pas de faire le menage! */
if (matrice[i] != NULL)
{
for (j = 0; j < p; j++)
{
matrice[i][j] = alea(100);
}
}
else
{
/* -tc- Erreur d'allocation: on fait le menage! */
while (i > 0)
{
i--;
free(matrice[i]);
}
free(matrice), matrice = NULL;
err = 1;
}
}
}
return matrice;
}
void print_sum(int **mat1, int **mat2, int n, int p)
{
if (mat1 != NULL && mat2 != NULL && n > 0 && p > 0)
{
int i, j;
for (i = 0; i < n; i++)
{
for (j = 0; j < p; j++)
{
printf("%d ", mat1[i][j] + mat2[i][j]);
}
printf("\n" );
}
}
}
void desalloc(int **mat, int n)
{
/* -tc- On commence par valider les arguments */
if (mat != NULL && n > 0)
{
int i;
for (i = 0; i < n; i++)
{
free(mat[i]);
}
free(mat);
}
}
/* -tc- Fonction recommandee dans la FAQ C pour generer un nombre aleatoire
entre 0 et N. Pour plus d'infos:
- http://c.developpez.com/faq/?page=nombres#NOMBRES_random_bornes
- http://www.bourguet.org/cpp/random.pdf
*/
int alea(int n)
{
int partSize = (n == RAND_MAX) ? 1 : 1 + (RAND_MAX - n)/(n+1);
int maxUsefull = partSize * n + (partSize-1);
int draw;
do
{
draw = rand();
}
while (draw > maxUsefull);
return draw/partSize;
} |
Partager