Skip to content

Instantly share code, notes, and snippets.

@alxlion
Last active February 17, 2016 10:20
Show Gist options
  • Save alxlion/d4a812e92e270a109fde to your computer and use it in GitHub Desktop.
Save alxlion/d4a812e92e270a109fde to your computer and use it in GitHub Desktop.
Correction TP 1GCC - 2015-2016
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#define MAX_LENGTH 1024
void convertToBinary(char* word); // Ces prototypes de fonctions (ou signatures) pouvaient
void convertToHex(char* word); // très bien se trouver dans un fichier .h et leur implémentation
void convertToBase64(char* word); // dans un fichier .c correspondant.
int main(int argc, char *argv[])
{
char wordToConvert[MAX_LENGTH];
int base = 0;
/*
* 1re étape: On commence par définir nos deux premières variables qui vont nous être
* utile pour notre programme.
*/
/* Pour le mode CLI : ./monProgramme argument1 argument2
* \/ \/ \/
argv[0] argv[1] argv[2]
*/
if(argc > 1) {
// Première méthode non recommandée, l'utilisateur peut provoquer un buffer overflow: Faille de sécurité !
// wordToConvert = argv[1];
strncpy(wordToConvert, argv[1], MAX_LENGTH); // Meilleure sécurité
base = atoi(argv[2]); // On converti notre pointer char (argv[2]) en int pour le stocker dans notre variable base.
// Never trust the user input !
if (base != 2 && base != 16 && base != 64) {
puts("Wrong base :(");
return 1;
}
}
/* Pour le mode STDIN: Lancement du programme sans arguments */
else {
puts("Enter a sentence to convert: ");
// On utilise fgets() afin de pouvoir stocker les espaces et donc des phrases à partir de l'entrée standard (console) : stdin
fgets(wordToConvert, MAX_LENGTH, stdin);
puts("Enter the base to convert (2, 16, 64): ");
// %d: On attend de l'utilisateur un entier. &base : stockage de la valeur à l'adresse de la variable base !
scanf("%d", &base);
}
/* Une fois qu'on a nos deux variables, on va pouvoir les utiliser
* grâce à nos fonctions (qui pouvaient être dans un autre fichier source).
*/
switch(base) {
case 2:
convertToBinary(wordToConvert);
break;
case 16:
convertToHex(wordToConvert);
break;
case 64:
convertToBase64(wordToConvert);
break;
// Pas besoin de default car on vérifie avant que la base soit bien 2, 16 ou 64.
}
return 0;
}
void convertToBinary(char* word) {
/*
* On pouvait utiliser la fonction itoa() mais ne faisant pas parti du standard C
* il était déconseillé de l'utiliser (certains compilateurs ne l'accepte plus).
* Ici, mille et une façon de convertir un binaire, voici la mienne.
*/
for(int i = 0; i < strlen(word)-1; i++) {
printf("%c%c%c%c%c%c%c%c ", // %c : on veut afficher soit '0' ou '1' qui sont des char
// Utilisation des masques pour chaque bit
(word[i] & 0b10000000)? '1' : '0',
(word[i] & 0b01000000)? '1' : '0',
(word[i] & 0b00100000)? '1' : '0',
(word[i] & 0b00010000)? '1' : '0',
(word[i] & 0b00001000)? '1' : '0',
(word[i] & 0b00000100)? '1' : '0',
(word[i] & 0b00000010)? '1' : '0',
(word[i] & 0b00000001)? '1' : '0'
);
}
printf("\n");
}
void convertToHex(char* word) {
/*
* On utilise ici les avantages du printf()
*/
for(int i = 0; i < strlen(word)-1; i++) {
printf("%X", word[i]);
}
printf("\n");
}
void convertToBase64(char* word) {
/*
* L'encodage (et le décodage) en base64 est de loin la fonction la plus évidente et facile à implémenter.
* Il n'est pas de votre niveau et demande l'utilisation de certaines bibliothèques (OpenSSL) pour pouvoir l'implémenter
* correctement. Ici elle a été implémentée manuellement, elle ne vient pas de moi (http://rosettacode.org/wiki/Base64_encode_data#Manual_implementation).
* Le barême sera ajusté en conséquence étant donné ce qui été demandé en seulement 2h.
*/
static char base64en[] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', '0', '1', '2', '3',
'4', '5', '6', '7', '8', '9', '+', '/',
};
int i, j;
char out[strlen(word)-1];
for (i = j = 0; i < strlen(word)-1; i++) {
int s = i % 3; /* from 6/gcd(6, 8) */
switch (s) {
case 0:
out[j++] = base64en[(word[i] >> 2) & 0x3F];
continue;
case 1:
out[j++] = base64en[((word[i-1] & 0x3) << 4) + ((word[i] >> 4) & 0xF)];
continue;
case 2:
out[j++] = base64en[((word[i-1] & 0xF) << 2) + ((word[i] >> 6) & 0x3)];
out[j++] = base64en[word[i] & 0x3F];
}
}
/* move back */
i -= 1;
/* check the last and add padding */
if ((i % 3) == 0) {
out[j++] = base64en[(word[i] & 0x3) << 4];
out[j++] = '=';
out[j++] = '=';
} else if ((i % 3) == 1) {
out[j++] = base64en[(word[i] & 0xF) << 2];
out[j++] = '=';
}
for(int i = 0; i < strlen(out); i++) {
printf("%c", out[i]);
}
printf("\n");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment