Plus de C ...

This commit is contained in:
Samy Avrillon 2021-10-18 08:24:56 +02:00
parent 78a2846be6
commit ef369a75dc
No known key found for this signature in database
GPG Key ID: 4220348226C4A071
7 changed files with 372 additions and 0 deletions

28
C6.1.c Normal file
View File

@ -0,0 +1,28 @@
#include <stdio.h>
#define N 100
int divisible(int n, int q){
return n%q==0;
}
int premier(int n){
if(n<2)return 0;
for(int k=2;k*k<=n;k++){
if(divisible(n,k))
return 0;
}
return 1;
}
int main() {
int n;
do{
printf("Quel nombre ? ");
scanf("%d",&n);
}while(0>=n || n>=1000);
for(int k=2;k<=n;k++)
if(premier(k))printf("%d, ", k);
printf("et c'est tout ce que vous m'avez demandé.\n");
}

18
C6.2.c Normal file
View File

@ -0,0 +1,18 @@
#include<stdio.h>
#define N 30
int fib(int k){
if(k<2)
return 1;
return fib(k-1)+fib(k-2);
}
int main() {
int n;
do{
printf("Quel nombre ? ");
scanf("%d",&n);
}while(0>=n || n>=1000);
printf("Voilà votre %d\n", fib(n));
}

43
C6.6.c Normal file
View File

@ -0,0 +1,43 @@
#include <stdio.h>
#define N 50
/**
* Renvoie le couple (F_k, F_k+1)
*/
void fiboRec(int aa[N], int k){
if(k<=1)aa[k] = 1;
else aa[k] = aa[k-2]+aa[k-1];
if(k+1<N)fiboRec(aa, k+1);
}
/**
* Est-ce ce qui a é demandé ? Si oui, c'est très long.
*/
int fiboRecMoche(int k){
if(k<=1) return 1;
return (fiboRecMoche(k-1) + fiboRecMoche(k-2));
}
void fiboPlain(int aa[N]){
aa[0] = aa[1] = 1;
for(int k=2;k<N;k++)
aa[k] = aa[k-2] + aa[k-1];
}
int main() {
int fiboArr[N];
int fiboArrRec[N];
fiboRec(fiboArrRec,0);
fiboPlain(fiboArr);
printf("Fibo récursif : %d\n", fiboArrRec[N-1]);
printf("Fibo non récursif : %d\n", fiboArr[N-1]);
// Avec cette ligne ça met trop de temps. Complexité exponentielle, miam miam.
printf("Fibo très moche : %d\n", fiboRecMoche(N-1));
return 0;
}

172
C6.7.c Normal file
View File

@ -0,0 +1,172 @@
#include<stdio.h>
#include<stdlib.h>
#define N 5
#define BATEAUX_COUNT 2
#define BATEAUX_LENGTHES_ARR {2,2}
#define J_atoi(x) printf("-----------------------------------\n\e[1;1H\e[2JJoueur %d, c'est à vous: \n",x)
#define printclear() printf("\e[1;1H\e[2J")
/*
* g==0 -> eau
* g==1 -> eau torpillée
* g==2 -> bateau
* g==3 -> bateau torpillé
*/
typedef int Grille[N][N];
void initialiserGrille(Grille grille){
for(int i=0; i<N; i++)
for(int j=0; j<N; j++)
grille[i][j] = 0;
}
void afficherGrille(Grille grille, int secret){
printf("");
for(int i=0; i<N; i++)printf("");
printf("\n");
for(int j=0; j<N; j++){
printf("");
for(int i=0; i<N; i++){
switch(grille[i][j]){
case 0:
printf(" ");break;
case 1:
printf("");break;
case 2:
printf(secret?" ":"");break;
case 3:
printf("");break;
default:
printf("?");
}
}
printf("\n");
}
printf("");
for(int i=0; i<N; i++)printf("");
printf("\n");
}
int viserCase(Grille grille, int x, int y){
if(grille[x][y]%2==1)return 0;// On ne retouche pas
grille[x][y] += 1;
return grille[x][y]>=2;
}
/**
* dir==0 -> Horizontal
* dir==1 -> Vertical
*/
int setBateau(Grille grille, int longueur, int px, int py, int dir){
int coefx = dir==0;
int coefy = dir==1;
if((dir!=0) && (dir!=1))return 0;
if((px<0) || (py<0))return 0;
if((px+coefx*longueur >N) || (py+coefy*longueur>N)) return 0;
for(int i=0; i<longueur; i++)
if(grille[px+coefx*i][py+coefy*i]==2)return 0;
for(int i=0; i<longueur; i++)
grille[px+coefx*i][py+coefy*i] = 2;
return 1;
}
void demandeRemplirGrille(Grille g, int bateauxLength[BATEAUX_COUNT]){
int px,py,dir;
for(int k=0; k<BATEAUX_COUNT; k++){
printclear();
afficherGrille(g, 0);
do{
printf("Placez un bateau de taille %d (x y dir) avec (dir==0 pour horizontal):", bateauxLength[k]);
scanf("%d %d %d", &px, &py, &dir);
}while(!setBateau(g, bateauxLength[k], px, py, dir));
}
}
void remplirAupif(Grille g, int bateauxLength[BATEAUX_COUNT]){
int k=0;
while(k<BATEAUX_COUNT){
int tx = rand() % N;
int ty = rand() % N;
int dir = rand() % 2;
if(setBateau(g, bateauxLength[k], tx, ty, dir))k++;
}// Presque sûr que ça finit
}
int main(){
int jeu;
do{
printf("1 pour jouer contre un humain, 2 pour jouer contre l'ordinateur, 0 pour quitter : ");
scanf("%d", &jeu);
}while(jeu<0 || jeu>2);
if(jeu==0)return 0;
Grille g1, g2;
initialiserGrille(g1);
initialiserGrille(g2);
int bateauxLength[BATEAUX_COUNT] = BATEAUX_LENGTHES_ARR;
int tx, ty;
demandeRemplirGrille(g1,bateauxLength);
//remplirAupif(g1, bateauxLength);
if(jeu==1){
J_atoi(2);
demandeRemplirGrille(g2, bateauxLength);
}else{
remplirAupif(g2, bateauxLength);
}
int batCount=0;
for(int k=0; k<BATEAUX_COUNT; k++)batCount+=bateauxLength[k];
int bateaux[2] = {batCount, batCount};
int joueur = 0; // Inutile si contre un ordinateur.
while(bateaux[0]!=0 && bateaux[1]!=0){
if(jeu==1)J_atoi(joueur);
printf("Base: \n");
afficherGrille(joueur==0?g1:g2,0);
printf("Objectif: \n");
afficherGrille(joueur==0?g2:g1,1);
printf("Où voulez-vous tirer ? (x y) ");
scanf("%d %d",&tx, &ty);
if(viserCase(joueur==0?g2:g1 ,tx, ty)){
printf("Touché !\n");
bateaux[(joueur+1)%2]--;
}else
printf("Plouf !\n");
if(jeu==2){
//Faire le coup de l'ordinateur
do{
tx = rand() % N;
ty = rand() % N;
}while(g1[tx][ty]%2!=0);
if(viserCase(g1, tx, ty)){
printf("L'ordinateur a touché un bateau !\n");
bateaux[joueur]--;
}else
printf("L'ordinateur a tiré dans l'eau !\n");
}else{
joueur = (joueur+1)%2;
}
}
printf("Victoire du joueur %d !\n", (joueur+1)%2)
}

67
C6.md Normal file
View File

@ -0,0 +1,67 @@
C 6
=
### Exercice 3
Le programme suivant ne compile pas, car la fonction `f` appelée dans la fonction `main` n'est pas déclarée. Le compilateur `C` en crée donc une, et râle quand il en croise une nouvelle. Il suffit donc d'ajouter la ligne suivante juste au dessus de la fonction `main` pour définir correctement la fonction `f` qui sera utilisée et définie à posteriori.
```
float f(float x);
```
### Exercice 4
À la fin de ce programme, `x` vaut `0` parce que le paramètre `int x` indique que l'appel à `f(x)` transmet *la valeur* de `x`. Afin de passer la référence, il aurait fallu mettre un parametre de type `int* x` et ensuite appeler `*x = *x+1`. (pourquoi y a t'il un `float` d'ailleurs ?)
### Exercice 5
À la fin de ce programme, tab vaut `[1, 2]`. Le tableau est un pointeur déguisé, et ce sont donc des références qui sont passées.
### Exercice 6
Calculer la suite de fibonnaci avec une boucle se fait en complexité O(n). Ça va.
Calculer la suite de fibonnaci avec une (mauvaise) récursivité, complexité exponentielle. Le coût suit en effet la relation de récurence `M_n = M_n-1 + M_n-2`. On peut aussi faire une récurence plus sympa en renvoyant deux termes de la suite.
```
#include <stdio.h>
#define N 50
/**
* Renvoie le couple (F_k, F_k+1)
*/
void fiboRec(int aa[N], int k){
if(k<=1)aa[k] = 1;
else aa[k] = aa[k-2]+aa[k-1];
if(k+1<N)fiboRec(aa, k+1);
}
/**
* Est-ce ce qui a été demandé ? Si oui, c'est très long.
*/
int fiboRecMoche(int k){
if(k<=1) return 1;
return (fiboRecMoche(k-1) + fiboRecMoche(k-2));
}
void fiboPlain(int aa[N]){
aa[0] = aa[1] = 1;
for(int k=2;k<N;k++)
aa[k] = aa[k-2] + aa[k-1];
}
int main() {
int fiboArr[N];
int fiboArrRec[N];
fiboRec(fiboArrRec,0);
fiboPlain(fiboArr);
printf("Fibo récursif : %d\n", fiboArrRec[N-1]);
printf("Fibo non récursif : %d\n", fiboArr[N-1]);
// Avec cette ligne ça met trop de temps. Complexité exponentielle, miam miam.
printf("Fibo très moche : %d\n", fiboRecMoche(N-1));
return 0;
}
```

16
C7.6.c Normal file
View File

@ -0,0 +1,16 @@
#include <stdio.h>
#define N 10
int main(){
char s[N];
printf("Entrez votre pseudo\n");
if(fgets(s, N, 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<N && s[i]!='\n';i++){}
s[i] = '\0';
printf("Résultat: %s\n", s);
return 0;
}

28
C7.md Normal file
View File

@ -0,0 +1,28 @@
C7
=
### Exercice 1
Le code affiche le caractère `a` qui a pour code ascii 97 = 48(code ascii du `0`) + 49 (code ascii du `1`)
### Exercice 2
Ce code incrémente la variable `c` jusqu'à ce que sa valeur dépasse sa taille théorique. Alors l'incrément lui donne la valeur 0 (`11111111 + 00000001 -> 00000000` en non signé). Les caractères correspondants sont ensuite affichés.
Le processeur aurait pû aussi planter lors de l'appel à la somme créant un `overflow`.
Pour c<128, le programme nous affiche la liste de certains caractères `ASCII` avec leurs codes associés.
### Exercice 3
En C, une chaine de caractères est typiquement est une suite de caractères terminée par le caractère nul (`\0`). La chaine de caractères `"toto"` a donc une taille mémoire de 5. Essayer de l'afficher plantera ou du moins, ne produira probablement pas le résultat demandé, car ce dernier caractère ne sera pas trouvé.
`gcc` autorise au moins cette construction, même si elle est dangereuse.
### Exercice 4
En C, une chaine de caractère a le type `char*`. C'est donc un pointeur vers une case mémoire de type `char` (taille 1 octet). Pour lire la chaine, il faut lire les caractères et incrémenter le pointeur (passer à l'octet suivant) jusqu'à tomber sur le caractère nul (`\0` correspond à l'octet nul).
### Exercice 5
Ce programme est problématique puisque si le pseudo est plus grand que 10 caractères, scanf essaiera d'écrire des octets d'autres variables, pouvant mener a des Segfault ou des attaques par *buffer overflow*.
Un autre problème est aussi que `scanf` arrête sa lecture à la lecture du premier espace. Donc si l'utisateur a un espace dans son pseudo, scanf ne récuperera que la premiere partie et récuperera la seconde plus tard, bref c'est la mouise.