Exercice langage C : Nombres Premiers dans un Inventaire
Enoncé de l'exercice:
Écrire un programme permettant de déterminer les nombres premiers dans l'intervalle [1,n] à l'aide du crible d'Ératosthène.
Il consiste à former une table avec tous les entiers naturels compris entre 2 et n et à rayer (mise à zéro), les uns après les autres, les entiers qui ne sont pas premiers de la manière suivante : dès que l'on trouve un entier qui n'a pas encore été rayé, il est déclaré premier, et on raye tous les multiples de celui-ci.
À la fin du procédé, les nombres non barrés sont des nombres premiers.
On tiendra compte du fait qu'un nombre donné peut déjà avoir été éliminé en tant que multiple de nombres précédents déjà testés.
Par ailleurs, on sait que l'on peut réduire la recherche aux nombres de 2 à sqrt(n) (si un entier non premier est strictement supérieur à sqrt(n) alors il a au moins un diviseur inférieur à sqrt(n) et aura donc déjà été rayé).
#include
#include
§MEVBCBfint main()
{
const int n = 1000;
int tab_nombres[n];
int imax;
int i, j;
/*
* Remplissage du tableau "tab_nombres"
* à l'aide des nombres de 1 à 1000.
*/
for( i=1; i
/*
* Impression des nombres non exclus
* qui sont les nombres premiers cherchés.
* Impression de 10 nombres par ligne.
*/
printf( "Les nombres premiers entre 1 et "
"%d sont :\n\n", n );
for( i=1; i
Exercice langage C : Suites et Fonctions mathématiques
Exercice 1
#include
/* le polynôme P(X) = X^5 - X^4 + 2X^3 - 2X^2 + 3X - 3 */
float a[] = { 1, -1, 2, -2, 3, -3 };
/* le degré de P (la taille de a est n + 1) */
int n = 5;
float x, xp, p;
int i;
int main() {
for(;;) {
printf("x ? ");
scanf("%f", &x);
if (x == 0 && xp == 0)
break;
xp = x;
p = a[0];
for (i = 1; i p = p * x + a[i];
printf("P(%f) = %f\n", x, p);
}
}
C'est le très classique schéma de Hörner, qui permet d'évaluer un polynôme de degré n en ne faisant que n multiplications.
Afin de tester l'algorithme pour diverses valeurs de x nous l'avons entouré d'une boucle, mais nous n'avons pas de raison d'affirmer que telle valeur de x est invalide et marque la fin. Nous avons fait la convention suivante : si vous donnez la valeur 0 deux fois de suite (ou en premier) cela arrête le programme. Oui, c'est alambiqué ; vous avez une meilleure idée ?
Exercice 2
#include
#define NL 5
#define NC 5
float A[NL][NC] = {
{ 21, 9, 16, 4, 25 },
{ 22, 15, 17, 15, 26 },
{ 23, 7, 18, 3, 27 },
{ 24, 15, 19, 15, 28 },
{ 24, 8, 20, 12, 29 } };
int tMin[NC], nMin, p, i, j, k;
float vMin;
int main() {
for (p = 0; p /* calcul de l'ensemble des indices des minima de la ligne p */
nMin = 1;
tMin[0] = 0;
vMin = A[p][0];
for (j = 1; j if (A[p][j] == vMin)
tMin[nMin++] = j;
else if (A[p][j] nMin = 1;
tMin[0] = j;
vMin = A[p][j];
}
/* de ces indices lesquels sont-ils maxima de leur colonne? */
for (j = 0; j k = tMin[j];
for (i = 0; i if (A[i][k] > vMin)
break;
if (i >= NL)
printf("(%d,%d) ", p, k);
}
}
printf("\n");
}
Exercice langage C: Les Instructions
1. Donnez la déclaration d’une fonctionf sans paramètre et qui ne retourne aucune valeur.
2. Donner la déclaration d’un pointeur sur un tableau de 10 chaînes de caractères.
3. Que vaut la variableernet à la fin du code suivant?
On rappelle quex += y est équivalent àx = x + Y et que de manière généralex op = y est équivalent àx = x op y.
int ernet = 100;
ernet += 5;
ernet
*= 10;
ernet /= 15;
ernet %= 4;
4. (*2) Soit le code suivant :
#include
#define MAX = 10
int main() {
int tab[MAX];
tab[2] = 2;
printf("%d", tab[MAX-8]);
}
Ce programme compile-t-il? Si oui qu’af?che-t-il?
1. (*2) Soit le code suivant :
int i=0, tab[10], n=27 ;
do {
tab[i++] = n % 10 ;
} while ((n /= 10) > 10) ;
Que contient le tableau tab en ?n de programme ?
Réponse : tab[0] vaut 7 et les autres cases du tableau ont une valeur indéterminée.
Comme il s’agit d’une boucle do while, l’instruction associée est exécutée au moins une
fois. L’expression i++ se lit de gauche à droite, c’est à dire retourne la valeur de i avant
de l’incrémenter, soit 0. Donc tab[0] vaut le reste de la division entière entre 27 (n) et
10, soit 7. tab[0] vaut 7.
Le test de l’instruction est faux car n / 10 vaut 2 qui est inférieur à 10. Les autres cases
du tableau ont donc une valeur indéterminée.
2. (*3) Soit le code suivant :
int i ;
printf("i ? ") ;
scanf("%d", &i) ;
switch (i) {
case 0 : printf(" NUL") ; break ;
case 1 : case 3 : case 5 : case 7 : case 9 :
printf(" IMPAIR") ; break ;
case 2 : case 4 : case 6 : case 8 :
printf(" PAIR") ; break ;
default : printf("NEGATIF OU PAS UN CHIFFRE") ; break ;
}
Réécrivez l’instruction switch en n’utilisant que des instructions if.
Réponse :
int i ;
printf("i ? ") ;
scanf("%d", &i) ;
if (i == 0) {
printf(" NUL") ;
}
else if (i == 1 || i ==3 || i == 5 || i == 7 || i == 9) {
printf(" IMPAIR") ;
}
else if (i == 2 || i ==4 || i == 6 || i == 8) {
printf(" PAIR") ;
}
else {
printf("NEGATIF OU PAS UN CHIFFRE") ;
}
3. Donnez la déclaration d’une fonction g sans paramètre et qui retourne l’adresse d’un entier.
Réponse : int g(void) ;
4. Donnez la déclaration d’une fonction f sans paramètre et qui ne retourne aucune valeur
Réponse : void f(void) ;
Exercice langage C: Ouverture d'un fichier en lecture en mode binaire
Cet exercice a pour but de vérifier les points techniques suivants :
- L'ouverture d'un fichier en lecture en mode binaire
- Tester si un fichier est ouvert (en particulier si vous avez les droits de lecture sur le fichier)
- Lecture des données écrites en binaire
- Fermer le fichier une fois la lecture terminée
Travail à Faire:
Proposez un programme qui lit le fichier écrit en binaire de l'exercice précédent et affiche son contenu. Vous devriez obtenir :
Liste des entiers de 1 à 1000
1
2
...
1000
#include
#include
int main (int argc, char * argv[]) {
std::ifstream myfile;
char * filename = "exampleBinary.txt";
char buffer[29];
int value;
myfile.open (filename, std::ios::in | std::ios::binary);
if(myfile.is_open())
{
myfile.read(buffer,29*sizeof(char));
std::cout for(int i = 0 ; i {
myfile.read((char*)&value,sizeof(int));
std::cout }
}
else
{
std::cout }
myfile.close();
return 0;
}
Exercice langage C : Procédures
Travail à Faire:
Ecrire une procédure qui lit une chaîne de caractères et l'interprète comme un entier positif dans la base décimale. On écrira 2 fonctions :
La fonction chaine2entier qui récupère une chaîne de caractère et retourne un entier.
Prototype : int chaine2entier(char *)
La fonction estentier qui récupère un caractère et retourne 0 s’il ne correspond pas à un chiffre 1 s’il correspond à un chiffre.
Prototype : int estentier(char) ;
#include
int estentier(char) ;
int chaine2entier(char *) ;
main()
{
/* Déclarations */
char CH[100]; /* chaîne numérique à convertir */
long N; /* résultat numérique */
printf("Entrez un nombre entier et positif : ");
gets(CH);
printf("%s\n",CH) ;
N = chaine2entier(CH) ;
if(N printf("%s ne représente pas correctement un entier positif.\n", CH);
else
printf("La chaine %s a pour valeur %d\n" ,CH,N) ;
}
int chaine2entier(char *CH)
{
int I;
int N = 0 ;
int OK = 1 ;
for (I=0; OK && CH[I]; I++)
if (estentier(CH[I]))
N = N*10 + (CH[I]-'0');
else
OK=0;
if (OK)
return N ;
else
return -1 ;
}
int estentier(char c)
{
if ((c>='0')&&(c return 1 ;
else
return 0 ;
}
Exercice langage C déclaration des variables simples
Traduisez les déclarations suivantes en C, sachant que vous travaillerez dans les ensembles de nombres indiqués. Choisissez les types les plus économiques, sans perdre en précision.
(1) | entier | COMPTEUR | {0 ,..., 300} | |
(2) | entier | X,Y | {-120 ,..., 100} | |
(3) | entier | MESURE | {-10 ,..., 104} | |
(4) | réel | SURFACE1 | {0.5 ,..., 150075} | |
(5) | réel | SURFACE2 | {-12 ,..., 1500750.5} | |
(6) | entier | N1 | {0 ,..., 210} | |
(7) | entier | N2 | {-47 ,..., 47} | |
(8) | entier | N3 | {0 ,..., 326} | |
(9) | entier | N4 | {-1280 ,..., 1285} | |
(10) | booléen | TROUVE | {vrai, faux} |
Solution:
(1) | entier COMPTEUR | {0 ,..., 300} |
int COMPTEUR; | ||
(2) | entier X,Y | {-120 ,..., 100} |
char X,Y; | ||
(3) | entier MESURE | {-10 ,..., 104} |
int MESURE; | ||
(4) | réel SURFACE1 | {0.5 ,..., 150075} |
float SURFACE1; | 6 positions significatives | |
(5) | réel SURFACE2 | {-12 ,..., 1500750.5} |
double SURFACE2; | 8 positions significatives | |
(6) | entier N1 | {0 ,..., 210} = {0 ,..., 1024} |
int N1; | ||
(7) | entier N2 | {-47 ,..., 47} = {-16384 ,..., 16384} |
int N2; | ||
(8) | entier N3 | {0 ,..., 326} = {0 ,..., 1 073 741 824} |
long N3; | ||
(9) | entier N4 | {-1280 ,..., 1285} = {-1 ,..., 3.4*1010} |
double N4; | 11 positions significatives | |
(10) | booléen TROUVE | {vrai, faux} |
int TROUVE; | par convention |
Exercice langage C : Chaîne de Caractères
1.
(*3) Soit le code suivant :
char tab[] = "bonjour";
int i;
for (i=0; tab[i]!= ’\0’; i++) {
tab[i] = tab[i] - ’a’ + ’A’;
}
Que fait ce programme?
Proposez une version sans utiliser l’opérateur d’accès tableau ([]).
2.
Dans le code suivant :
char ch[] = "Bonjour",
*pc = ch;
while (
*pc) pc++;
Que vautpc après l’exécution de l’instructionwhile? Vers quel caractère pointe-t-il?
3.
Que vaut la variablej à la ?n de la fonctionf?
void f(int i) {
int ?j;
?j = i;
}
1.
(*2) Donner la déclaration d’un tableau dont chacun de ses 20 éléments est une structure à trois champs : un entier nombre, un pointeur d’entier ptrint et un tableau de 15 caractères.
Supposant ce tableau initialisé, donnez l’expression permettant de placer dans le champ
ptrint du 4ème élément du tableau, l’adresse du champ nombre du 11ème élément.
Réponse : tableau[3].ptrint = &tableau[10].nombre
Avec les déclarations suivantes :
typedef struct examen_t {
int nombre ;
int ptrint ;
char chaine [15] ;
} Examen ;
Examen tableau[20] ;
2.
Soit la déclaration suivante : char les[] = "ab".
Que vaut les[2] ?
Réponse : les[2] vaut ’\0’.
Le tableau les est une chaîne de caractères, car il a été initialisé avec une chaîne ("ab").
Le nombre d’éléments de ce tableau est donc le nombre de caractères présent dans la chaîne, plus 1, le caractère de ?n de chaîne. En conséquence, les[2] contient celui-ci, c’est à dire ’\0’.
3.
Donnez une forme équivalente à l’expression &tab[0].
Réponse : &tab[0] tab.
Exercice langage C : Partie Administrateur
Il s'agit de faire un programme permettant de gérer des fichiers de QCM. Un qcm sera représenté par une
structure du type :
typedef truct qcm {
int numquest;
char quest[256];
char rep1[256];
char rep2[256];
char rep3[256];
char rep4[256];
int solrep;
} TQCM;
Où numquest est le numéro de la question,
quest est la chaine de caractère représentant la question, rep1 à rep 4 les 4 réponses possibles.
solrep est le numéro de la seule solution à la question
Le programme permet de passer en mode administrateur pour générer des fichiers de qcm, ou en mode utilisateur pour utiliser les qcm. Ces deux modes font l'objet de deux parties différentes. Il est conseillé de commencer par la partie administrateur. Le code de la fonction main vous est donné ci-dessous :
int main (void)
{
char calu;
do { printf("(a) mode administrateur,\n(b) mode utilisateur,\n");
printf("(c) quitter,\nvotre choix : ");
scanf(" %c", &calu);
switch(calu)
{ case 'a': gestion_admin();
calu = 'c';
break;
case 'b': gestion_util();
calu = 'c';
break;
case 'c': printf("fin du programme \n\n");
break;
default : printf("\nmauvaise saisie recommencer !!\n");
}
} while( calu !='c');
return 0;
}
1) Faire une fonction de prototype TQCM tsaisie_quest(void) qui permet de saisir au clavier le numéro de la question, le libellé de la question, les 4 réponses possibles, le numéro de la réponse solution.
Nota : vous utiliserez de préférence la fonction fgets(char *ligne, 255, stdin) qui permet la lecture au clavier d'une chaine de caractères jusqu'au retour chariot. En cas de problème vous utiliserez la fonction scanf("%s", char *ligne) en remplaçant les espaces par les caractères '_'.
2) Faire une fonction de prototype void fenr_quest(TQCM *Q, FILE * fq) qui permet d'enregistrer la structure Q, passée en paramètre dans le fichier fq ouvert préalablement en écriture en fin de fichier.
/* PROGRAMME QCM */
#include
#include
#define MLIGNE 256 /* Taille d'une ligne en nombre de caracteres */
#define MNAME 100 /* Taille d'un nom de fichier en nombre de caracteres */
typedef struct
{
int numquest; /* Numero de la question */
char quest[MLIGNE]; /* Question du QCM */
char rep1[MLIGNE]; /* Premiere reponse possible */
char rep2[MLIGNE]; /* Deuxieme reponse possible */
char rep3[MLIGNE]; /* Troisieme reponse possible */
char rep4[MLIGNE]; /* Quatrieme reponse possible */
int solrep; /* Numero de la bonne reponse */
} Question;
TQCM tsaisie_quest(void); /* mode administrateur, saisie de la question et de la réponse
*/
void fenr_quest(TQCM *Q, FILE * fq);
/* mode administrateur, enregistrement de la question Q dans le fichier ouvert fq*/
int fcreer_qcm(char *nomfic);
Exercice langage C: Opérations de Mise à Jour
Cet exercice a pour but de vérifier les points techniques suivants :
- Utilisation simple de tableaux.
- Festion d'une liste simple grâce à un tableau statique.
Travail à Faire :
Ecrire un programme qui gère une liste d'entiers grâce au menu suivant :
1. Ajouter un entier
2. Afficher la liste des entiers
3. Supprimer dernier entier de la liste.
4. Afficher la dernière note tapée
5. Quitter
Il y aura au maximum 10 entiers. Lorsqu'on rajoute un entier, il sera rajouté à la fin de la liste.
#include
using namespace std;
const int N=10;
int main()
{
int t[N],nb=0,choix,e,i;
bool fini=false;
while(fini==false)
{
cout"1. Ajouter un entier"endl;
cout"2. Afficher la liste des entier"endl;
cout"3. Supprimer le dernièr entier de la liste"endl;
cout"4. Afficher le dernier entier de la liste"endl;
cout"5. Quitter"endl;
cout"Votre choix : ";cin>>choix;
switch(choix)
{
case 1 : cout"Tapez un entier : ";cin>>e;
if(nbN){t[nb]=e; nb++; cout"ENTIER AJOUTE"endl;}
else cout"IMPOSSIBLE LE TABLEAU EST PLEIN"endl;
break;
case 2 : if(nb==0)cout"LA LISTE EST VIDE"endl;
else {
cout"VOICI LA LISTE"endl;
for(i=0;inb;i++)coutt[i]" ";
coutendl;
}
break;
case 3 : if(nb>0){nb--; cout"ENTIER SUPPRIME"endl;}
else cout"LA LISTE EST VIDE"endl;
break;
case 4 : if(nb>0)cout"lLE DERNIER ENTIER EST "t[nb-1]endl;
else cout"LA LISTE EST VIDE"endl;
break;
case 5 : fini=true;
break;
}
}
return 0;
}
Exercice langage C: Programmes différents
1.
(*2) Donnez l’expression C permettant de calculeri=i?2n.
2.
Soit la déclaration suivante :char les[] = "ab".
Que vautles[2]?
3.
Soitge, un tableau de 10 caractères. Donnez l’instruction permettant de saisir au clavier une chaîne de caractères, sans utiliser le caractère’&’.
4.
(*2) Soit le code suivant :
int i=0, tab[10], n=27;
do {
tab[i++] = n % 10;
} while ((n /= 10) > 10);
Que contient le tableautab en ?n de programme?
9. (*2) Soit le code suivant :
void g(int *p) {
*p = 12 ;
}
int main() {
int *p ;
g(p) ;
printf("%d\n", *p) ;
}
Qu’est ce qui s’af?che ?
Réponse : L’af?chage est indéterminé ou erreur d’exécution.
Le pointeur p dé?ni dans la fonction main n’est pas initialisé. Comme il s’agit d’une
variable locale, son contenu est indéterminé.
L’expression g(p), puis, dans la fonction g, pp = 12, sont donc erronées. Avec de la
chance, il y aura une erreur à l’exécution (segmentation error), ou pire, un écrasement
mémoire.
10. Que vaut la variable j à la ?n de la fonction f ?
void f(int i) {
int j ;
j = i ;
}
Réponse : Son contenu est indéterminé.
j est un pointeur, qui n’est pas initialisé. Comme il s’agit d’une variable locale, son contenu est indéterminé.
L’expression j est donc erronée. Avec de la chance, il y aura une erreur à l’exécution
(segmentation error), ou pire, un écrasement mémoire.
11. (*2) Que vaut la variable fleuri dans le code suivant :
char fleuri = 100 ;
fleuri *= 2 ;
Pourquoi ?
Réponse : fleuri vaut -56.
Le type char est signé. Sa plage de valeurs est de -128 à 127 (de 2
n1
à 2
n1 1), où
n est le nombre de bits du type, ici 8. Concernant les nombres signés, pour un nombre
ositif donné, nous avons la formule suivante : a 2
n = (a). Ici, pour fleuri égal à
200, le nombre négatif correspondant est donc -56.
Exercice langage C: Fonctions double
1. Ecrivez une fonction qui affiche un triangle d'étoiles, et qui prend en paramètre le nombre de lignes du triangle:
* *** *****2. Utilisez cette fonction pour afficher un sapin:
* *** * *** ***** * *** ***** ******* *Vous devrez certainement modifier un peu la fonction écrite au point 1) afin que votre sapin ressemble à celui dessiné ci-dessus.
1. Tout l'intérêt de l'exercice réside dans la recherche de la relation entre le numéro de ligne et le nombre d'espaces et d'étoiles. Si i est le numéro de ligne, commençant à 0, et lignes le nombre de lignes, le nombre d'espaces est donné par lignes-i-1 et le nombre d'étoiles par 2*i+1.
void dessine_etage(int lignes)
{
for (int i = 0; i {
for (int j = 0; j cout for (int j = 0; j cout cout }
}
2. Pour obtenir le même dessin que sur l'énoncé, il faut décaler les étages du sapin en ajoutant des espaces suppléntaires. Une solution consiste à légèrement modifier la fonction dessine_etageen lui ajoutant un paramètre spécifiant le nombre d'espaces supplémentaires.
#include
using namespace std;
void dessine_etage(int lignes, int espaces)
{
for (int i = 0; i for (int j = 0; j cout for (int j = 0; j cout cout }
}
int main(int argc, char **argv) {
dessine_etage(2, 2);
dessine_etage(3, 1);
dessine_etage(4, 0);
dessine_etage(1, 3);
return 0;
}