Exercice langage C: Fonctions d'algèbre linéaire
Dans cet exercice, vous allez mettre en oeuvre les fonctions d'algèbre linéaire que vous avez vues en cours.
- Commencez par définir une structure Matrice
struct Matrice {
float *tab;
int nl, nc;
};Ajoutez ensuite le code pour les fonctions get et set permettant d'accéder aux éléments du tableau. Comme suggéré dans le cours, vérifiez que la ligne et la colonne auxquelles on désire accéder sont bien valides. Ajoutez également les fonctions alloue_matrice et affiche.
Toutes ces fonctions ont été vues en cours, et leur implémentation ne devrait donc pas poser de problèmes.
- Rédigez le code d'une fonction copie, dont le but est de copier le contenu d'une matrice dans une autre. La fonction prendra deux arguments: un pointeur sur la matrice source et un autre sur la matrice destination. On suppose que la matrice destination a déjà été allouée. La fonction prendra soin de vérifier que les deux matrices ont bien la même taille, avant d'effectuer la copie.
- Ecrivez deux fonctions intitulées set_id et set_0 permettant d'initialiser une matrice à la matrice identité et à la matrice nulle, respectivement.
Les en-têtes de ces fonctions devront être:
bool set_id(Matrice *mat);void set_0(Matrice *mat);La fonction set_id retournera false si la matrice passée en paramètre n'est pas carrée, et true si l'opération s'est bien passée.
- Implémentez une fonction init permettant d'initialiser une matrice. Vous allez écrire une fonction différente pour chaque type de matrice que vous voudrez initialiser. Par exemple, pour initialiser une matrice 2 x 2 , vous devrez écrire la fonctionvoid init(Matrice *matrice, float c1, float c2, float c3, float c4)
alors que pour initialiser une matrice 2 x 3, il faudra utiliser
void init(Matrice *matrice, float c1, float c2, float c3, float c4, float c5, float c6)car elle contient 6 coefficients. Cette dernière fonction peut, par ailleurs, autant servir à initialiser une matrice 3 x 2 que 2 x 3. Soyez donc bien attentifs lorsque vous l'implémentez. On supposera qu'une matrice à 6 coefficients n'a pas la forme 1 x 6 ou 6 x 1, car la structure Vecteur s'occupera de ces cas-là.
#include
#include
using namespace std;
// ******* Structures *******
struct Matrice {
float *tab;
int nl, nc;
};
struct Vecteur {
float *tab;
int n;
};
// ******* Fonctions pour Matrice *******
float get(Matrice *mat, int ligne, int col) {
if (ligne >= 0 && ligne nl && col >= 0 && col nc)
return mat->tab[ligne * mat->nc + col];
else {
cout cout nc nl cout }
return 0;
}
void set(Matrice *mat, int ligne, int col, float val) {
if (ligne >= 0 && ligne nl && col >= 0 && col nc)
mat->tab[ligne * mat->nc + col] = val;
else {
cout cout nc nl cout }
}
Matrice *alloue_matrice(int nl, int nc) {
Matrice *res = new Matrice;
res->nl = nl;
res->nc = nc;
res->tab = new float[nc * nl];
return res;
}
void libere_matrice(Matrice *mat) {
delete[] mat->tab;
delete mat;
}
void affiche(Matrice *mat) {
for (int i=0; inl; i++) {
for (int j=0; jnc; j++)
cout cout }
}
bool set_id(Matrice *mat) {
if (mat->nc == mat->nl) {
for (int i=0; inl; i++)
for (int j=0; jnc; j++)
if (i == j)
set(mat, i, j, 1);
else
set(mat, i, j, 0);
return true;
}
else {
cout return false;
}
}
void set_0(Matrice *mat) {
for (int i=0; inl; i++)
for (int j=0; jnc; j++)
set(mat, i, j, 0);
}
// pour matrices a 6 coefficients
void init(Matrice *mat, float c1, float c2, float c3, float c4, float c5,
float c6) {
if ((mat->nc == 3 && mat->nl == 2) || (mat->nc == 2 && mat->nl ==3)) {
mat->tab[0] = c1;
mat->tab[1] = c2;
mat->tab[2] = c3;
mat->tab[3] = c4;
mat->tab[4] = c5;
mat->tab[5] = c6;
}
else
cout }
// pour matrices a 9 coefficients
void init(Matrice *mat, float c1, float c2, float c3, float c4, float c5,
float c6, float c7, float c8, float c9) {
if (mat->nc == 3 && mat->nl == 3) {
mat->tab[0] = c1;
mat->tab[1] = c2;
mat->tab[2] = c3;
mat->tab[3] = c4;
mat->tab[4] = c5;
mat->tab[5] = c6;
mat->tab[6] = c7;
mat->tab[7] = c8;
mat->tab[8] = c9;
}
else
cout }
// pour matrices a 12 coefficients
void init(Matrice *mat, float c1, float c2, float c3, float c4, float c5,
float c6, float c7, float c8, float c9, float c10, float c11, float c12) {
if ((mat->nc == 2 && mat->nl == 6) || (mat->nc == 3 && mat->nl == 4) ||
(mat->nc == 4 && mat->nl == 3) || (mat->nc == 6 && mat->nl == 2)) {
mat->tab[0] = c1;
mat->tab[1] = c2;
mat->tab[2] = c3;
mat->tab[3] = c4;
mat->tab[4] = c5;
mat->tab[5] = c6;
mat->tab[6] = c7;
mat->tab[7] = c8;
mat->tab[8] = c9;
mat->tab[9] = c10;
mat->tab[10] = c11;
mat->tab[11] = c12;
}
else
cout }
void copie(Matrice *mat, Matrice *res) {
if (mat->nl == res->nl && mat->nc == res->nc)
for (int i=0; inl; i++)
for (int j=0; jnc; j++)
set(res, i, j, get(mat, i, j));
else
cout }
void add_mat(Matrice *m1, Matrice *m2, Matrice *res) {
if (m1->nc == m2->nc && m1->nl == m2->nl && res->nc == m1->nc
&& res->nl == m1->nl)
for (int i=0; inl; i++)
for (int j=0; jnc; j++)
set(res, i, j, get(m1, i, j) + get(m2, i, j));
else
cout }
float trace(Matrice *mat) {
float tr = 0;
if (mat->nl == mat->nc)
for (int i=0; inl; i++)
tr += get(mat, i, i);
else
cout return tr;
}
void mult(Matrice *m1, Matrice *m2, Matrice *res) {
if (m1->nc == m2->nl && res->nl == m1->nl && res->nc == m2->nc)
for (int i=0; inl; i++)
for (int j=0; jnc; j++) {
res->tab[i * res->nc + j] = 0;
for (int k=0; knc; k++)
res->tab[i * res->nc + j] += get(m1, i, k) * get(m2, k, j);
}
else
cout }
void transpose_mat(Matrice *mat, Matrice *res) {
if (mat->nc == res->nl && mat->nl == res->nc)
for (int i=0; inl; i++)
for (int j=0; jnc; j++)
set(res, i, j, get(mat, j, i));
else
cout }
// ******* Fonctions pour Vecteur *******
float get(Vecteur *vec, int n) {
if (n >= 0 && n n)
return vec->tab[n];
else {
cout cout n cout }
return 0;
}
void set(Vecteur *vec, int n, float val) {
if (n >= 0 && n n)
vec->tab[n] = val;
else {
cout cout n cout }
}
Vecteur *alloue_vecteur(int n) {
Vecteur *res = new Vecteur;
res->n = n;
res->tab = new float[n];
return res;
}
void libere_vecteur(Vecteur *vec) {
delete[] vec->tab;
delete vec;
}
void affiche(Vecteur *vec) {
for (int i=0; in; i++)
cout }
void init(Vecteur *vec, float c1, float c2, float c3, float c4) {
if (vec->n == 4) {
vec->tab[0] = c1;
vec->tab[1] = c2;
vec->tab[2] = c3;
vec->tab[3] = c4;
}
else
cout }
float norm_vect(Vecteur *vec) {
float somme = 0;
for (int i=0; in; i++)
somme += get(vec, i) * get(vec, i);
return sqrt(somme);
}
float produit_scalaire(Vecteur *v1, Vecteur *v2) {
float produit = 0;
if (v1->n != v2->n)
cout else {
for (int i=0; in; i++)
produit += v1->tab[i] * v2->tab[i];
}
return produit;
}
Exercice langage C: programme qui lit les résultats du tirage du Loto
Travail à Faire :
Ecrivez un programme qui lit les résultats du tirage du Loto (6 numéros) et les stocke dans un tableau. Le programme lira ensuite les 6 numéros que vous avez joués.
La prochaine étape du programme consiste à déterminer combien de numéros corrects vous avez tirés. Pour cela, comparez les deux tableaux de numéros et stockez les numéros corrects dans un nouveau tableau dont la taille sera exactement le nombre de numéros corrects.
Finalement, le programme devra afficher vos numéros ainsi que les numéros corrects.
Remarque: n'écrivez pas tout le code en un seul bloc, mais modularisez-le en utilisant plusieurs fonctions. Idéalement, votre programme devrait contenir les fonctions suivantes: lire_numeros,compte_numeros_corrects, alloue_tableau, stocke_numeros_corrects et affiche_numeros.
#include
using namespace std;
int *alloue_tableau(int taille) {
return new int[taille];
}
int *lire_numeros(void) {
int *numeros = alloue_tableau(6);
for (int i=0; i cout do
cin >> numeros[i];
while (numeros[i] 45);
}
return numeros;
}
int compte_numeros_corrects(int *t1, int *t2) {
int matches = 0;
for (int i=0; i for (int j=0; j if (t1[i] == t2[j])
matches++;
return matches;
}
void stocke_numeros_corrects(int *t1, int *t2, int *c) {
int index = 0;
for (int i=0; i for (int j=0; j if (t1[i] == t2[j]) {
c[index] = t1[i];
index++;
}
}
void affiche_numeros(int *t, int taille) {
for (int i=0; i cout cout }
int main(int argc, char **argv) {
cout int *tirage = lire_numeros();
cout int *numeros_perso = lire_numeros();
int nombre_corrects = compte_numeros_corrects(tirage, numeros_perso);
int *corrects = alloue_tableau(nombre_corrects);
stocke_numeros_corrects(tirage, numeros_perso, corrects);
cout cout affiche_numeros(tirage, 6);
cout affiche_numeros(corrects, nombre_corrects);
delete [] corrects;
delete [] numeros_perso;
delete [] tirage;
return 0;
}
Exercice langage C : Fonction Afficher les chiffres en base 10
#include
6#define B 10
// Affiche les chiffres de l’inverse
void affinv(int n){
int r; int q;
r=1;
do{
q=(B*r) / n;
r=(B*r) % n;
printf("%i", q);
}
while (r!=1);
printf("\n");
}
//Calcule la longueur de la p´eriode
int periode(int n){
int r; int q; int i;
r=1; i=0;
do{
q=(B*r) / n;
r=(B*r) % n;
//printf("%i", q);
i++;
}
while (r!=1);
//printf("\n");
return i;
}
main(){
int n, d;
int prem, ferm;
for(n=2; nif (n%2!=0 && n%5!=0){
//On teste si n est premier
d=2;
while(dprem = (n%d != 0);
ferm = (n-1) % periode(n) == 0;
if (ferm && prem) printf("%i confirme le petit theoreme de Fermat\n", n);
if (!ferm && prem) printf("%i infirme le petit theoreme de Fermat\n", n);
if (ferm && !prem) printf("%i infirme la reciproque du petit theoreme de Fermat\n", n);
}
}
}
Exercice langage C: Répertoire
On veut réaliser un répertoire téléphonique. Chaque personne est représentée dans le répertoire par un nom, prénom et le numéro de téléphone. Pour représenter une personne, définir un type de structure personne qui contient deux chaînes de caractères et un entier.
- érire une fonction void ajout_personne (FILE *rep) qui saisit une personne et l'ajoute à la fin du fichier passé en paramètre
- écrire une fonction void affiche_ensemble_personne (FILE *rep) qui affiche le contenu du fichier
- écrire une fonction void trouve_numéro_personne (FILE *rep, char *nom) qui permet de trouver le numéro de téléphone d??une personne donnée en paramètre
- écrire une fonction void changer_numéro_personne (FILE *rep, char *nom) qui permet de changer le numéro de téléphone d'une personne donnée en paramètre
- écrire une fonction void menu(FILE *rep) qui demande l'opération à exécuter : ajouter une personne, afficher le contenu du répertoire, trouver un numéro ou quitter le programme
- écrire le programme principal
#include
struct complexe
{
double p_reel; /* partie reelle */
double p_imag; /* partie imaginaire */
};
typedef struct complexe Complexe;
void saisir(Complexe *pc);
void afficher(Complexe c);
void ajouter(Complexe *pc1, Complexe c2);
int main()
{
Complexe var1, var2;
printf("Saisie premier complexe : ");
saisir(&var1);
printf("Saisie second complexe : ");
saisir(&var2);
ajouter(&var1, var2);
printf("Affichage premier complexe : ");
afficher(var1);
printf("\nAffichage second complexe : ");
afficher(var2);
printf("\n");
return 0;
}
void saisir(Complexe *pc)
{
printf("\nRe: ");
scanf("%lf", & (*pc).p_reel);
printf("Im: ");
scanf("%lf", & pc->p_imag);
}
void afficher(Complexe c)
{
printf("%f + %f i", c.p_reel, c.p_imag);
}
void ajouter(Complexe *pc1, Complexe c2)
{
(*pc1).p_reel += c2.p_reel;
pc1->p_imag += c2.p_imag;
}
Exercice langage C: Lecture et écriture en mode binaire
Cet exercice a pour but de vérifier les points techniques suivants :
- L'ouverture d'un fichier en écriture en mode binaire
- Tester si un fichier est ouvert (en particulier si vous avez les droits d'écriture sur le fichier)
- Ecrire des données en binaire
- Fermer le fichier une fois l'écriture terminée
Travail à Faiire:
Proposez un programme qui écrit en binaire une chaîne de caractère suivant de la liste des entiers de 0 à 1000 :
Liste des entiers de 1 à 1000
1
2
...
1000
#include
#include
int main (int argc, char * argv[]) {
std::ofstream myfile;
char * filename = "exampleBinary.txt";
myfile.open (filename, std::ios::out | std::ios::binary);
if(myfile.is_open())
{
myfile.write("Liste des entiers de 1 à 1000",29*sizeof(char));
for(int i = 0 ; i {
myfile.write((char*)&i,sizeof(int));
}
}
else
{
std::cout }
myfile.close();
return 0;
}
Exercice langage C : Chaîne et Tableau
Exercice 1:
Ecrire un programme qui lit une liste de Nb nombres, la décale d'un cran vers le haut (le premier doit se retrouver en dernier), l'affiche puis la décale vers le bas.
On pourra décomposer le programme en fonctions.
Exercice 2:
Classer automatiquement un tableau de Nb entiers puis l'afficher dans l'ordre croissant puis décroissant.
On pourra utiliser des fonctions de l'exercice précédent.
On pourra créer un (ou plusieurs) tableau temporaire (donc local).
Si vous vous en sentez la force, prévoyez le cas de valeurs égales.
rotation
#include
typedef int composante;
void lecture(composante *t,int *nb)
{
int i;
puts("nombre de valeurs à entrer ? ");
scanf("%d",nb);
for(i=1;i {
printf("%dième valeur : ",i);
scanf("%d",t++);
}
}
void affiche(composante *t, int max)
{
int i;
for(i=0;i puts(" ");
}
void decale_bas(composante *deb, int max)
{
composante c,*t;
t=deb+(max-1);
c=*t;
while (t>deb) {*t=*(t-1);t--;}
*t=c;
}
void decale_haut(composante *t, int nb)
{
composante c;int i;
c=*t;
for (i=1;i *t=c;
}
void main(void)
{
composante tableau[100];
int nombre;
lecture(tableau,&nombre);
puts("tableau initial :");
affiche(tableau,nombre);
decale_haut(tableau,nombre);
puts("décalage vers le haut :");
affiche(tableau,nombre);
decale_bas(tableau,nombre);
puts("décalage vers le bas :");
affiche(tableau,nombre);
}
#include
#define dim 100
typedef int composante;
void lecture(composante *t,int *nb)
{
int i;
puts("nombre de valeurs à entrer ? ");
scanf("%d",nb);
for(i=1;i{
printf("%dième valeur : ",i);
scanf("%d",t++);
}
}
void affiche(composante *t, int max)
{
int i;
for(i=0;i
puts(" ");
}
int indice_min(composante t[],int indice_dep, int nb_indices)
/* cherche l'indice de la valeur du tableau :
* -soit égale à t[indice_dep], mais d'indice > à indice_dep;
* -soit la plus petite mais >t[indice_deb]
*/
{
int i,indice_resultat=-1;
for(i=indice_dep+1;i
/* si on est encore là c'est qu'il n'y en pas d'égal */
for(i=0;iif ((t[i]>t[indice_dep]) && ((indice_resultat
return(indice_resultat);
}
void copier(composante *source, composante *dest, int nb)
/* copie le tableau source dans le tableau dest */
{
int i;
for(i=0;i
}
void classe(composante tab[], int nb)
{
composante tempo[dim]; /* un malloc(sizeof(composante)*nb) aurait été
mieux mais on n'en a pas encore parlé en cours */
int i,ind_faits,indice;
/* 1er : recherche du plus petit, le 1er si ex aequo */
indice=0;
for(i=1;iif(tab[i]
tempo[ind_faits=0]=tab[indice];
/* les suivants : recherche le + petit mais > au précédent */
for(ind_faits=1;ind_faits{
indice=indice_min(tab,indice,nb);
tempo[ind_faits]=tab[indice];
}
copier(tempo,tab,nb);
}
void main(void)
{
composante tableau[dim];
int nombre;
lecture(tableau,&nombre);
puts("tableau initial :");
affiche(tableau,nombre);
classe(tableau,nombre);
puts("tableau classé :");
affiche(tableau,nombre);
}
Exercice langage C: Fonctions simples
Travail à Faire:
Pour tester les fonctions suivantes, appelez-les dans la fonction main de votre programme:
- Ecrivez une fonction min2 qui reçoit deux arguments de type float et retourne le plus petit d'entre eux. Le type de retour devra donc être float.
- Ecrivez une fonction min3 qui prend trois arguments de type int et retourne le plus petit d'entre eux. Comment utiliser la fonction min2 du point précédent pour écrire le corps de min3 en une ligne ?
- Ecrivez une fonction arrondi qui prend un argument de type float et retourne l'argument arrondi à deux décimales.
- Ecrivez une fonction traduction qui prend en argument un entier entre 0 et 6 et l'affiche à l'écran en toutes lettres (zero, un, ..., six). Quelles sont les différences entre cette fonction et les précédentes ?
float min2(float a, float b) {
if (a return a;
else
return b;
}
Pour calculer le minimum de 3 nombres, on peut, par exemple, calculer d'abord le minimum des 2 premiers, et ensuite calculer le minimum de ce résultat et du dernier nombre. Comme on a déjà écrit une fonction retournant le minimum de 2 nombres au point précédent, on peut donc la réutiliser.
int min3(int a, int b, int c) {
return int(min2(min2(a, b), c));
}
Pour arrondir un nombre à 2 décimales, il suffit de le multiplier par 100, le convertir en int, le reconvertir en float et le diviser par 100, comme nous l'avions vu à la série 2. Lorsqu'on divise 2 nombres, si l'un d'entre eux est un float, le compilateur effectuera une division réelle. Dans le corrigé, on écrit la constante 100 100.0 afin que le compilateur la considère comme une constante float, ce qui nous évite de faire la conversion explicite.
float arrondi(float a) {
return int(a * 100) / 100.0;
}
Il n'y pas d'autre manière que de fournir un texte particulier pour chaque nombre. La fonction peut aussi s'écrire avec des ifs.
void traduction(int n) {
switch (n) {
case 0:
cout break;
case 1:
cout break;
case 2:
cout break;
case 3:
cout break;
case 4:
cout break;
case 5:
cout break;
case 6:
cout break;
}
}
Exercice langage C: Introduction aux pointeurs
1. Le programme ci-dessous illustre le fonctionnement des pointeurs en affichant les différentes valeurs contenues dans les variables.
Lisez-le en essayant de le comprendre. Essayez de déduire quelles vont être les valeurs affichées par les instructions cout.
#include
using namespace std;
int main(int argc, char **argv) {
int i = 9;
cout "Contenu de i: '" i "'" endl;
cout "Adresse de i: '" (unsigned int)&i "'" endl endl;
/* On declare un pointeur sur int et on lui
* affecte l'adresse de i. On dit que p
* pointe sur i. */
int *p = &i;
cout "Contenu de p: '" (unsigned int)p "'" endl;
cout "Adresse de p: '" (unsigned int)&p "'" endl;
cout "Contenu de la variable pointee par p: '" *p "'" endl endl;
// On affecte 10 a l'adresse pointee par p.
*p = 10;
cout "Contenu de la variable pointee par p: '" *p "'" endl;
cout "Contenu de i: '" i "'" endl;
// Partie a completer
// Fin de la partie a completer
return 0;
}
2. Recopiez le programme donné dans emacs, compilez-le et lancez-le. Est-ce que les résultats affichés correspondent à ce que vous aviez prévu au point précédent?
Remarque: les adresses en mémoire sont toujours affichées sous forme hexadécimale (base 16). Pour les voir sous forme décimale, il faut les convertir en unsigned int, comme dans l'exemple ci-dessus.
3. Complétez le programme en incrémentant la variable i de 10 (i = i + 10), sans avoir recours directement à la variable i (utilisez un pointeur). Affichez ensuite la valeur de i pour vérifier que l'opération s'est bien déroulée.
4. Déclarez un nouveau pointeur sur int que vous nommerez q. Faites pointer q sur i. A nouveau, faites-le sans utiliser directement la variable i. Affichez le contenu du pointeur q pour vérifier votre code.
5. Déclarez une variable f de type float. Initialisez-la à. Echangez ensuite son contenu avec celui de i, sans avoir recours à la variable i. Affichez les valeurs de i et f.
6. Déclarez une nouvelle variable j de type int que vous initialisez à 8. Faites pointer q sur j. Maintenant, échangez les valeurs de i et j sans utiliser ni i, ni j.
Affichez finalement les valeurs de i et j.
#include
using namespace std;
int main(int argc, char **argv) {
int i = 9;
cout "Contenu de i: '" i "'" endl;
cout "Adresse de i: '" (unsigned int)&i "'" endl endl;
/* On declare un pointeur sur int et on lui
* affecte l'adresse de i. On dit que p
* pointe sur i. */
int *p = &i;
cout "Contenu de p: '" (unsigned int)p "'" endl;
cout "Adresse de p: '" (unsigned int)&p "'" endl;
cout "Contenu de la variable pointee par p: '" *p "'" endl endl;
// On affecte 10 a l'adresse pointee par p.
*p = 10;
cout "Contenu de la variable pointee par p: '" *p "'" endl;
cout "Contenu de i: '" i "'" endl;
// Partie a completer
// 3. i incrementee de 10
cout "3." endl;
*p = *p + 10;
cout "Contenu de i: '" i "'" endl;
// 4. nouveau pointeur sur i
cout "4." endl;
int *q = p;
cout "Contenu de la variable pointee par q: '" *q "'" endl;
// 5. echange
cout "5." endl;
float f = 5;
int t = *p;
*p = int(f);
f = t;
cout "Contenu de i: '" i "'" endl;
cout "Contenu de f: '" f "'" endl;
// 6. echange (2)
cout "6." endl;
int j = 8;
q = &j;
int k = *q;
*q = *p;
*p = k;
cout "Contenu de i: '" i "'" endl;
cout "Contenu de j: '" j "'" endl;
// Fin de la partie a completer
return 0;
}
Exercice langage C: Fonctions et pointeurs
Créez un nouveau programme, auquel vous ajouterez la fonction suivante :
void fonction1(int *p, int v) {
*p = v;
}
1. Effectuez un appel à fonction1 dans la fonction main. Faites-le de manière à comprendre ce que fait fonction1.
2. Ecrivez une fonction
void echange(int *p1, int *p2) {
}
qui échange le contenu de p1 et p2 sans utiliser d'affectation avec ces variables, mais en se servant de fonction1.
3. Testez votre fonction
echange en l'appelant dans main.
#include
using namespace std;
void fonction1(int *p, int v) {
*p = v;
}
void echange(int *p1, int *p2) {
int t;
fonction1(&t, *p1);
fonction1(p1, *p2);
fonction1(p2, t);
}
int main(int argc, char **argv) {
int i = 5;
int j = 9;
echange(&i, &j);
cout return 0;
}