Examen de C et C++
Année 2011/2012 - Deuxième session
Numéro d'anonymat :
On considère une fonction void comb_bitwise(int x, int y, int k, int* r) qui combine deux entiers x et y en conservant les k bits de poids faibles de x et les (32-k) bits de poids fort de y. Le résultat est placé dans la variable pointée par r.
Vous devez répondre dans les cadres prévus à cet effet. Il sera tenu compte de la concision et de l'efficacité de vos programmes. Téléphones portables, calculatrices, ordinateurs et tablettes interdits. Notes personnelles (manuscrites ou imprimées) et documents de cours, TD et TP autorisés.
Fonctions et pointeurs appliqués à des valeurs scalaires, opérateurs bitwise.
4 points.
1 point Université de Bourgogne - UFR Sciences et Techniques - L2
Si x a pour représentation hexadécimale AABB007D, y a pour représentation hexadécimale 00AA1122 et que k vaut 12 donnez la valeur hexadécimale du
résultat. 1 point
Le principe proposé pour réaliser cette combinaison est d'utiliser deux masques complémen- taires m et ~m. Dans le masque m, les k bits de poids faibles sont à 0 et tous les autres bits à 1. Donnez le code permettant de construire ce masque m en utilisant des instructions bitwise du langage C.
Chaînes de caractères. 4 points.
Dessinez les représentations en mémoire des variables et instances de classes créées par cette fonction dans l'état où elles se trouvent juste avant la fin de l'exécution, en indiquant si elle sont stockées dans la pile ou dans le tas et en précisant les liens entre pointeurs et instances pointées .
void test_bitwise() {
}
void xpch() {
string* z = new string("abcdefgh");
string* w = new string("xyz");
(*w) = (*z);
}
En supposant que la fonction comb_bitwise est correctement programmée, réalisez une fonction void test_bitwise() qui déclare deux variables entières x et y, initialisées respectivement avec les valeurs 0xAABB007D et 0x00AA1122, et une variable entière r, puis qui appelle la fonction comb_bitwise, avec k=12, et qui affiche le résultat obtenu en hexadécimal.
1 point 1 point
L'exécution de la fonction xpch provoque t-elle une fuite mémoire ? Si oui, expliquez com- ment corriger le problème.
1 point
Tableaux 1D et 2D. 4 points.
Dans cet exercice, on représente des ta- bleaux encapsulés à deux dimensions à l'aide de la structure définie ci-contre dont les champs n et m représentent respec- tivement les nombres de lignes et de colon- nes.
typedef struct {
int** t;
int m;
int n;
}tab2D;
2 points Réalisez une fonction void
rempl_ch(char* s) qui modifie la chaîne pointée par s en remplaçant chaque espace par le caractère '_'.
void rempl_ch(char* s) {
}
A titre d'exemple, la figure ci-contre montre la représen- tation mémoire d'un tableau encapsulé de deux lignes et trois colonnes.
void ajouteLigne(tab2D* tab) {
Réalisez une fonction void ajouteLigne(tab2D* tab) qui augmente la capacité d'un tableau en lui ajoutant une nouvelle ligne initialisée avec des valeurs 0. La nouvelle ligne doit évidemment contenir m cellules.
Indice ; penser à utiliser calloc et realloc pour obtenir un code très concis.
void afficheTab(tab2D* tab) {
}
Réalisez une fonction void afficheTab(tab2D* tab) qui affiche à l'écran les valeurs conte- nues dans un tableau encapsulé.
Structures. 4 points.
typedef struct {
maillon* sommet;
}pile;
typedef struct _maillon {
int val;
_maillon* suivant;
}maillon;
Par convention, le sommet d'une pile non vide est le premier maillon du chaînage.
La fonction ci-contre permet d'initialiser une pile vide.
void initPile(pile* p) {
p->sommet=NULL;
}
2 points
1 point On représente une pile d'entiers à l'aide des structures suivantes.
Réalisez une fonction récursive maillon* chercheDernier(maillon* m) qui retourne l'adresse du dernier maillon de la chaîne de maillons commençant par le maillon situé en mémoire à l'adresse m.
void add(pile* p) {
}
Classes. 4 points.
Réalisez une fonction void test_pile() qui crée une pile, l'initialise, y empile les valeurs 5 et 10, fait appel à la fonction add pour les additionner, puis dépile et affiche le résultat.
class Buffer {
private:
int capacite;
int ipa;
int n;
int* tab;
Réalisez une fonction void add(pile*
p) qui dépile deux valeurs dans la pile pointée par p (en utilisant la fonction pop), les additionne, et empile le résultat (en utilisant la fonction push).
1 point On suppose qu'on dispose de fonctions void push(pile* p, int x) et int pop(pile* p) permet- tant respectivement d'empiler et de dépiler une valeur. Il ne vous est pas demandé de réali- ser ces fonctions.
Réalisez une fonction void add1(
pile* p) qui produit exactement le même résultat que add, mais de manière plus efficace, en réalisant un seul appel à la fonction pop et aucun appel à la fonction push.
void add1(pile* p) {
}
1 point
void test_pile() {
}
On définit une classe buffer représentant une file d'entiers, c'est à dire une structure munie d'une méthode void
ajouteVal(int val) permettant d'ajouter une nouvelle valeur dans la file et d'une méthode int retireVal() permettant de retirer la valeur la plus ancienne stockée dans la file.
Les valeurs de la file sont stockées dans un tableau géré de manière circulaire. L'ajout d'une nouvelle valeur à une file non vide se fait à la suite de la dernière valeur ajoutée,
1 point
void Buffer::ajouteVal(int val) {
} Réalisez une méthode void
Buffer::ajouteVal(int val) qui ajoute une valeur dans le buffer en supposant qu'il reste de la place.
Les variables d'instance ont les rôles suivants :
● capacite contient la taille du tableau, donc le nombre maximum de valeurs pouvant être stockées dans la file.
● n contient le nombre de valeurs effectivement stockées.
● ipa contient l'indice de la cellule où est stockée la valeur la plus ancienne.
● tab pointe sur le tableau contenant les valeurs.
Regardez la figure ci-dessous pour une bonne compréhension du principe. Elle représente un exemple de représentation du buffer à un moment donné. 4 valeurs sont stockées (valeur de la variable d'instance n). La plus ancienne est dans la cellule d'indice 4 (valeur de la varia- ble d'instance ipa). La plus récente est dans la cellule d'indice 1.
Si on ajoute une nouvelle valeur, elle sera placée dans la cellule d'indice 2 et n sera incrémenté. Si on retire une valeur, ce sera celle située dans la cellule d'indice ipa, c'est à dire 4, n sera décrémenté et ipa sera incrémenté.
La calcul de la position de l'élément le plus récent et l'incrémentation de ipa doivent tenir compte de la circularité de la représentation : la première cellule du tableau est considérée comme étant située juste après la dernière.
1 point
Réalisez le destructeur de la classe Buffer.
Buffer::~Buffer() {
} 1 point
void Buffer::agrandir(int delta) {
} 2 points
Réalisez une méthode void Buffer::agrandir(int delta) qui augmente la capacité d'un buffer sans en changer le contenu. La nouvelle capacité doit être égale à l'ancienne plus la valeur delta. Attention, vous ne devez rester dans le cadre du langage C++. En particulier, vous ne devez pas utiliser les méthodes malloc, calloc, realloc et free du langage C. Il est donc nécessaire de remplacer le tableau de stockage par un nouveau de plus grande taille. Veillez à ce que l'exécution de votre méthode ne provoque pas de fuite mémoire.