FIN DU C (je l'espère)

This commit is contained in:
Mysaa 2021-11-19 19:11:50 +01:00
parent d1f50dc10e
commit 07e4d08e83
7 changed files with 581 additions and 34 deletions

267
C12.2.c
View File

@ -227,7 +227,7 @@ struct personnage* askRegistryEntry(struct personnage** liste){
/* 13 */
void paspapa(struct personnage* batard){
if(batard==NULL)return;// On n'enleve aucun lien
if(batard==NULL || batard->pere==NULL)return;// On n'enleve aucun lien
if(batard->frereSuivantPapa != batard){
if(batard->pere->premierEnfant == batard)batard->pere->premierEnfant = batard->frereSuivantPapa;
struct personnage* fraterie = batard;
@ -245,7 +245,7 @@ void paspapa(struct personnage* batard){
/* 14 */
void pasmaman(struct personnage* batard){
if(batard==NULL)return;
if(batard==NULL || batard->mere==NULL)return;
if(batard->frereSuivantMaman != batard){
if(batard->mere->premierEnfant == batard)batard->mere->premierEnfant = batard->frereSuivantMaman;
struct personnage* fraterie = batard;
@ -290,9 +290,11 @@ struct personnage* removePremierNom(struct personnage** lliste){
return act;
}
struct personnage* orderPersos(struct personnage* liste){
void orderPersos(struct personnage** listeP){
if(liste==NULL)return NULL;
struct personnage* liste = *listeP;
if(liste==NULL)return;
struct personnage* newList = removePremierNom(&liste);
struct personnage* lastAdded = newList;
@ -302,7 +304,7 @@ struct personnage* orderPersos(struct personnage* liste){
lastAdded = toAdd;
}
return newList;
*listeP = newList;
}
// Je ne comprends pas la deuxième partie de la question ...
@ -483,24 +485,25 @@ void freeListe(struct personnage* origin){
///// Main pour les tests
void loadTestRegistry(struct personnage** liste){
addRegistryEntry(liste ,"Brandon","Jihair","Saoul-Helene");
addRegistryEntry(liste,"Jessica","Jihair","Saoul-Helene");
addRegistryEntry(liste,"Jennifer","Jihair","Saoul-Helene");
addRegistryEntry(liste,"Jonatan","Huggy","Pamella");
addRegistryEntry(liste,"Brenda","Huggy","Pamella");
addRegistryEntry(liste,"Kevin","Huggy", "Pamella");
addRegistryEntry(liste,"Jacques",NULL, NULL);
addRegistryEntry(liste,"Valery","Jonathan","Jennifer");
addRegistryEntry(liste,"Georges","Jonathan","Jennifer");
addRegistryEntry(liste,"François","Jonathan","Jessica");
addRegistryEntry(liste,"Charles","Kevin","Jessica");
}
int mainTests(){
struct personnage* liste = NULL;
loadTestRegistry(&liste);
addRegistryEntry(&liste ,"Brandon","Jihair","Saoul-Helene");
addRegistryEntry(&liste,"Jessica","Jihair","Saoul-Helene");
addRegistryEntry(&liste,"Jennifer","Jihair","Saoul-Helene");
addRegistryEntry(&liste,"Jonatan","Huggy","Pamella");
addRegistryEntry(&liste,"Brenda","Huggy","Pamella");
addRegistryEntry(&liste,"Kevin","Huggy", "Pamella");
addRegistryEntry(&liste,"Jacques",NULL, NULL);
addRegistryEntry(&liste,"Valery","Jonathan","Jennifer");
addRegistryEntry(&liste,"Georges","Jonathan","Jennifer");
addRegistryEntry(&liste,"François","Jonathan","Jessica");
addRegistryEntry(&liste,"Charles","Kevin","Jessica");
askRegistryEntry(&liste);
// Entrée rendant la structure incohérente.
//addRegistryEntry(liste,"Kevin","Charles","Jessica");
@ -510,7 +513,7 @@ int mainTests(){
}
dumpState(liste);
liste = orderPersos(liste);
orderPersos(&liste);
printVraiNom(liste->chaineGlobale->chaineGlobale);
printf("\n");
@ -526,15 +529,7 @@ int mainTests(){
return 0;
}
int main(){
struct personnage* liste = NULL;
char c;
char p1[NameLength+1], p2[NameLength+1];
char* newName;
int p3;
// Bon, j'ai mal lu le sujet, j'ai fait des matrices rectangulaires ...
void printHelp(){
printf("Bienvenue sur l'interface pour regarder votre série préférée.\n");
printf("'n $nom' pour ajouter un personnage;\n");
printf("'p $père' déclare un nouvel enfant à son père;\n");
@ -550,16 +545,30 @@ int main(){
printf("'d $nom' affiche les déscendants d'une génération donnée d'un personnage\n");
printf("'D $nom' affiche les déscendants jusqu'à une génération donnée d'un personnage;\n");
printf("'x' vérifie la cohérence du graphe généalogique.;\n");
printf("'q' pour quitter\n");
printf("'l' charge les données de la fiche;\n");
printf("'h' pour réavoir ce message;\n");
printf("'q' pour quitter (vous ne vous amusez pas ?)\n");
}
int main(){
struct personnage* liste = NULL;
char c;
char p1[NameLength+1], p2[NameLength+1];
struct personnage *pp1, *pp2;
char* newName;
int pg;
printHelp();
while(1){
printf("Commande ? ");
c = getchar();
getchar();// On bouffe l'espace
getchar();// On bouffe l'espace ou le retour à la ligne
switch(c){
case 'n':
scanf(NameLengthScanf, p1);
scanf(NameLengthScanf, p1);getchar();
p1[NameLength] = '\0';
newName = malloc((strlen(p1)+1)*sizeof(char));
if(newName==NULL)
@ -570,12 +579,206 @@ int main(){
printf("Le personnage %s a été créé.\n", newName);
break;
case 'p':
scanf(NameLengthScanf, p1);getchar();
p1[NameLength] = '\0';
pp1 = getByName(liste, p1);
if(pp1==NULL){
printf("Personnne ne répond au nom de %s\n", p1);
break;
}
printf("Qui a la chance d'avoir %s comme papa ? ", p1);
scanf(NameLengthScanf, p2);getchar();
p2[NameLength] = '\0';
pp2 = getByName(liste, p2);
if(pp2==NULL){
printf("Personnne ne répond au nom de %s\n", p2);
break;
}
papounet(pp1, pp2);
printf("%s est l'heureux papounet de %s !\n", p1, p2);
break;
case 'm':
scanf(NameLengthScanf, p1);getchar();
p1[NameLength] = '\0';
pp1 = getByName(liste, p1);
if(pp1==NULL){
printf("Personnne ne répond au nom de %s\n", p1);
break;
}
printf("Qui a la chance d'avoir %s comme maman ? ", p1);
scanf(NameLengthScanf, p2);getchar();
p2[NameLength] = '\0';
pp2 = getByName(liste, p2);
if(pp2==NULL){
printf("Personnne ne répond au nom de %s\n", p2);
break;
}
mamounette(pp1, pp2);
printf("%s est l'heureuse mamounette de %s !\n", p1, p2);
break;
case 'c':
dumpState(liste);
break;
case 'e':
askRegistryEntry(&liste);
break;
case 'P':
scanf(NameLengthScanf, p1);getchar();
p1[NameLength] = '\0';
pp1 = getByName(liste, p1);
if(pp1==NULL){
printf("Personnne ne répond au nom de %s\n", p1);
break;
}
paspapa(pp1);
printf("%s est maintenant orphelin de son pére (vous êtes un monstre).\n", p1);
break;
case 'M':
scanf(NameLengthScanf, p1);getchar();
p1[NameLength] = '\0';
pp1 = getByName(liste, p1);
if(pp1==NULL){
printf("Personnne ne répond au nom de %s\n", p1);
break;
}
pasmaman(pp1);
printf("%s est maintenant orphelin de sa mère (vous êtes un monstre).\n", p1);
break;
case 'o':
orderPersos(&liste);
printf("La liste des personnages a été triée.\n");
break;
case 'v':
scanf(NameLengthScanf, p1);getchar();
p1[NameLength] = '\0';
pp1 = getByName(liste, p1);
if(pp1==NULL){
printf("Personnne ne répond au nom de %s\n", p1);
break;
}
printVraiNom(pp1);
printf("\n");
break;
case 'a':
scanf(NameLengthScanf, p1);getchar();
p1[NameLength] = '\0';
pp1 = getByName(liste, p1);
if(pp1==NULL){
printf("Personnne ne répond au nom de %s\n", p1);
break;
}
printf("Vous voulez quelle génération ? ");
scanf("%d", &pg);getchar();
if(pg<0){
printf("Ce n'est pas un numéro de génération valide\n");
break;
}
printf("Ancetres de génération %d : ",pg);
printNthGP(pp1, pg, 0);
printf("\n");
break;
case 'A':
scanf(NameLengthScanf, p1);getchar();
p1[NameLength] = '\0';
pp1 = getByName(liste, p1);
if(pp1==NULL){
printf("Personnne ne répond au nom de %s\n", p1);
break;
}
dumpAncetres(pp1);
break;
case 'd':
scanf(NameLengthScanf, p1);getchar();
p1[NameLength] = '\0';
pp1 = getByName(liste, p1);
if(pp1==NULL){
printf("Personnne ne répond au nom de %s\n", p1);
break;
}
printf("Vous voulez quelle génération ? ");
scanf("%d", &pg);getchar();
pg++;
if(pg<=0){
printf("Ce n'est pas un numéro de génération valide\n");
break;
}
printf("Ses décendants de génération %d sont : ", pg);
dumpNthDescendents(pp1, pg);
printf("\n");
break;
case 'D':
scanf(NameLengthScanf, p1);getchar();
p1[NameLength] = '\0';
pp1 = getByName(liste, p1);
if(pp1==NULL){
printf("Personnne ne répond au nom de %s\n", p1);
break;
}
printf("Vous voulez jusqu'à quelle génération ? ");
scanf("%d", &pg);getchar();
pg++;
if(pg<=0){
printf("Ce n'est pas un numéro de génération valide\n");
break;
}
dumpDescendenceUntil(pp1, pg);
break;
case 'x':
if(yatilPbGenealogique(liste))
printf("Il y a un problème dans cet arbre ...\n");
else
printf("Aucun problème de généalogie détéctée.\n");
break;
case 'l':
loadTestRegistry(&liste);
printf("La liste par défaut a été chargée.\n");
break;
case 'h':
printHelp();
break;
case 'q':
goto fend;
}
getchar();
}

30
C13.1.c Normal file
View File

@ -0,0 +1,30 @@
#include <stdio.h>
typedef int longueur;
typedef int masse;
typedef int** test;
#define tset int**
int main(){
int a=2;
int *aa=&a;
int **aaa = &aa; // aaa est un test
test *pouf1, pif1;
tset *pouf2, pif2;
pouf1 = &aaa;
pif1 = aaa;
pouf2 = &aaa;
pif2 = a;
printf("%d %d %d %d", ***pouf1, ***pouf2, **pif1, pif2);
longueur l;
printf("Quelle longueur ? ");
scanf("%u", &l);
printf("%d, c'est un excellent choix !\n",l);
}

73
C13.3.c Normal file
View File

@ -0,0 +1,73 @@
#include<stdio.h>
enum NIVEAU {TRES_FACILE, FACILE, DIFFICILE, TRES_DIFFICILE, EXPERT, INDEFINI};
enum NIVEAU demanderNiveau(){
char choix;
printf("Bienvenue au Koikecélenombre !\n"
"Sélectionnez votre NIVEAU (je ne comprends pas le SNAKE_CASE)\n"
"1: très facile\n"
"2: facile\n"
"3: difficile\n"
"4: très difficile\n"
"5: expert\n"
"q: quitter l'application\n"
"Votre choix : ");
scanf("%c", &choix);getchar();
switch(choix){
case '1':
return TRES_FACILE;
case '2':
return FACILE;
case '3':
return DIFFICILE;
case '4':
return TRES_DIFFICILE;
case '5':
return EXPERT;
default:
return INDEFINI;
}
}
int main() {
int nmax;
int ndevine;
int nprop;
enum NIVEAU niv;
while(1){
niv = demanderNiveau();
switch(niv){
case TRES_FACILE:
nmax=10;break;
case FACILE:
nmax=20;break;
case DIFFICILE:
nmax=50;break;
case TRES_DIFFICILE:
nmax=100;break;
case EXPERT:
nmax=500;break;
default:
return 0;
}
do{
printf("Ami, donnez votre nombre : ");
scanf("%d", &ndevine);
}while(nmax<ndevine || 1>ndevine);
//for(int i=0; i<420; i++){printf("\n");}
nprop=0;
printf("\033[2JMaintenant, joueur, faites vos propositions.\n");
for(int j=1; nprop!=ndevine; j++){
printf("Je pense que c'est le ");
scanf("%d", &nprop);
if(nprop<ndevine)printf("C'est plus.\n");
else if(ndevine<nprop)printf("C'est moins.\n");
else printf("C'est ça !\nFélicitations, tu as trouvé en %d propositions.\n",j);
}
}
}

25
C13.4.c Normal file
View File

@ -0,0 +1,25 @@
#include <stdio.h>
union monu
{
unsigned char a[2];
float b;
long long int c;
};
// Si on essaie d'accéder à un autre champ que celui initialisé, alors la valeur sera simplement lue mais sous l'œil de la variable
// demandée. Ici, le programme affiche la valeur 0.42e-3 convertie en binaire puis reconverti en entier (plus des octets arbitraires «non initialisés» puisquqe long long int est plus grand que float)
// La taille de l'union est, comme attendu, le max de la taille de ses composantes.
// Ici, sizeof(union monu)=sizeof(long long int)=8 octets.
int main(){
union monu v = {};
v.b = 0.42e-3;
printf("%lld\n", v.c);
printf("%ld\n", sizeof(union monu));
}

181
C13.5.c Normal file
View File

@ -0,0 +1,181 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define N 5
#define NumLength (10+4+1)
#define IntLength (8)
union description
{
unsigned char lettresPref[2];
float taille;
long long int telephone;
};
enum descType {LettresPref, Taille, Telephone};
typedef struct personne personne;
struct personne{
int age;
char* initiales;
enum descType descType;
union description* desc;
};
void description(personne* p){
switch(p->descType){
case LettresPref:
printf("%s, agé de %d ans a pour lettres préférées le %c et le %c.\n",p->initiales, p->age, p->desc->lettresPref[0], p->desc->lettresPref[1]);
break;
case Taille:
printf("%s, agé de %d ans mesure %f m \n",p->initiales, p->age, p->desc->taille);
break;
case Telephone:
printf("%s, agé de %d ans est joignable au %llu \n",p->initiales, p->age, p->desc->telephone);
break;
}
}
int scanfs(char* dest, int length){
if(fgets(dest, length-1, stdin)==NULL){
return 1;// Une erreur est survenue lors de la lecture (trop long ?)
}
// On doit supprimer le retour à la ligne qu'a capturé fgets.
int i;
for(i=0;i<length && (dest)[i]!='\n';i++){}
if(i>=length){// On a Overflow
// On nettoie les caracteres ecrits en trop
while( (!strchr(dest,'\n')) && (!strchr(dest,EOF)))
if(!fgets(dest, length-1,stdin))
break;
return 2;
}
dest[i] = '\0';
return 0;
}
void nextLine(){
int c;
while ((c = getchar()) != '\n' && c != EOF) { };
}
void demander(personne* p){
int age;
int descTypeN;
char* initiales = calloc(IntLength,sizeof(char));
if(initiales==NULL)return;
printf("Création d'une nouvelle personne : \n");
do{
printf("Initiales : ");
} while(scanfs(initiales,IntLength));
printf("Âge : ");
if(scanf("%d", &age)!=1){
printf("Ce n'est pas un nombre, je met 42 dans le doute\n");
nextLine();
age = 42;
} else
getchar();
printf("Quelle description allez-vous donner (0 pour les lettres, 1 pour la taille, 2 pour le num) ? ");
if(scanf("%d", &descTypeN)!=1){
printf("Ce n'est pas un nombre, je met 2$ dans le doute\n");
nextLine();
descTypeN = 2;
} else
getchar();
enum descType descType;
union description* desc;
switch(descTypeN){
case 0:
desc = malloc(sizeof(unsigned char)*2);
if(desc==NULL){
free(initiales);return;
}
printf("Quelles sont ses deux lettres préférées ? ");
desc->lettresPref[0] = getchar();
desc->lettresPref[1] = getchar();
nextLine();
descType = LettresPref;
break;
case 1:
desc = malloc(sizeof(float));
if(desc==NULL){
free(initiales);return;
}
printf("Quelle est sa taille ? ");
scanf("%f",&(desc->taille));getchar();
descType = Taille;
break;
case 2:
desc = malloc(sizeof(long long int));
if(desc==NULL){
free(initiales);return;
}
printf("Quelle est son num ? ");
scanf("%llu",&(desc->telephone));getchar();
descType = Telephone;
break;
}
p->initiales = initiales;
p->age = age;
p->descType = descType;
p->desc = desc;
}
void freePerso(personne* perso){
free(perso->initiales);
free(perso->desc);
}
int lesmeme(personne* p1, personne* p2){
if(!((p1->age==p2->age) && (strcmp(p1->initiales, p2->initiales)==0) && (p1->descType==p2->descType)))
return 0;
switch(p1->descType){
case LettresPref:
return (p1->desc->lettresPref[0])==(p2->desc->lettresPref[0])
&& (p1->desc->lettresPref[1])==(p2->desc->lettresPref[1]);
case Taille:
return (p1->desc->taille)==(p2->desc->taille);
case Telephone:
return (p1->desc->telephone)==(p2->desc->telephone);
}
return 0;
}
int main(){
personne persos[N];
for(int i=0;i<N;i++){
demander(persos+i);
description(persos+i);
}
for(int i=1;i<N;i++){
for(int j=0;j<i;j++){
if(lesmeme(persos+i,persos+j)){
printf("Alerte doublon !\n");
description(persos+i);
}
}
}
for(int i=0;i<N;i++)
freePerso(persos+i);
}

35
C13.md Normal file
View File

@ -0,0 +1,35 @@
# C13
## Exercice 2
1.
Les typedef permettent d'assigner des types plus "précis" à des variables. Que feraient les physiciens sans leur analyse dimensionelle ?
C'est un moyen de préciser ce que représentre la variable autre part que le nom. Donc en soi, c'est une sorte de documentation, puisque ça n'a pas d'effet sur le code résultant.
2. Le typedef est juste une notation, les deux types sont complétement mélangeables, on peut donner à `int` à une fonction demandant du `longueur` sans que le *runtime*, ni le compilateur ne râle.
3. Deux types créés à partir du même sont du même fait eux aussi indiscernables.
4. Une autre utilité est de raccourcir le nom de types: par exemple pour remplacer `unsigned long long int` par `entier`, ou `struct personnage*` en `perso`.
5. Vrai. Je ne sais pas trop quoi dire de plus.
6. Faux. Define est une directive **pré**processeur ce qui signifie que les macros créés vont être résolues avant que le compilateur *effectif* n'agisse. La macro va être étendue telle quel, avec possiblement des erreurs provenant de mauvais parenthésage (voir fiches posterieures). Par exemple le code suivant montre la différence :
```
typedef int** test;
#define tset int**
int main(){
int a=2;
int *aa=&a;
int **aaa = &aa; // aaa est un test
int ***aaaa = &aaa; // aaaa est un test*
test *pouf1, pif1;// pouf1 est un int*** et pif1 un int** (test* et test)
tset *pouf2, pif2;
// Cette ligne est préprocécussée en `int** *pouf2, pif2`, donc pouf2 est un int***, mais pif2 est un int !
// C'est pour cela que les assignation suivantes sont bien typées
pouf1 = aaaa;
pif1 = aaa;
pouf2 = aaaa;
pif2 = a;
}
```

View File

@ -103,7 +103,7 @@ La troisième ligne du main est intriguante. Elle essaie de modifier le 7e carac
Le problème est que cette mémoire est allouée en statique au démarage du programme. Donc elle ne peut pas être modifiée. Et pourtant, Valgrind ne détecte aucune erreur. Je pense que c'est dû au fait que le noyau C ne renvoie pas d'erreur lorsque cette mémoire en lecture seule demande à être modifiée. Cela n'a aucun effet, mais pas non plus d'erreur.
### Exercice 5
### Exercice 5
J'ai corrigé le premier exo. J'avais seulement deux erreurs: Une due à une mauvaise gestion du `scanf` et l'autre due à un simple oubli de libérer les variables.