Apprendre le langage C en 10 minutes
Le langage C a la réputation d'être compliqué, pourtant, c'est plutôt faux. Nous allons voir comment apprendre ses bases en seulement 10 minutes! Il ne s'agit pas de tout savoir, mais de découvrir le langage par l'exemple. Ensuite, c'est la pratique qui vous fera progresser! À vos marques, prêts, partez!
Petit programme
Commençons par regarder ce petit programme :
#include <stdio.h>
int main(void)
{
printf("Bonjour tout le monde !\n");
return 0;
}
D'abord on inclut la bibliothèque stdio.h, responsable des entrées et des sorties standards. Cela nous permet d'utiliser la fonction printf, qui permet d'ajouter du texte dans le terminal.
Ensuite on définit la fonction appelée au démarrage du programme, main. Cette fonction renvoit un entier (int) et ne prend rien en paramètre (void). Son code est contenu dans des accolades.
Puis on appelle la fonction printf, qui va afficher la chaîne « Bonjour tout le monde ! » suivie d'un retour à la ligne (\n).
Enfin, on renvoit 0, code qui indique à Linux que tout s'est terminé normalement (return 0;)
Pour exécuter ce programme, on va le compiler:
gcc bonjour.c
La compilation donne un fichier exécutable appelé a.out
On le la,ce avec :
$ ./a.out
Bonjour tout le monde !
Commentaires
Les commentaires sont inclus entre /* et */, dans ce cas ils peuvent s'étaler sur plusieurs lignes :
/*
un commentaire
deux commentaires
*/
Ou alors on précède chaque ligne de deux slashs // :
// un commentaire
// deux commentaires
Variables et pointeurs
Les variables sont identifiées par leur nom et leur type. Elles peuvent être soit globales, si elles sont disponibles pour tout le programme, soit locales, si elles sont à l'intérieur d'une fonction ou d'une partie de fonction. Elles sont initialisées grâce au symbole = :
#include <stdio.h>
#include <stdlib.h>
double vitesse ; /* 'vitesse' est une variable globale de type réel */
int main(int argc, char *argv[])
{
int bicyclettes = 4; /* 'bicyclettes' est une variable de type entier locale à la fonction 'main', elle vaut 4 */
printf("Vous avez %d vélos\n", bicyclettes);
return 0;
}
Vous avez 4 vélos
Il existe différents types de variables, voici quelques exemples : int pour les nombres entiers courts, long pour les longs nombres entiers, float et double pour les nombres décimaux, char pour une lettre.
Dans le printf, on a un % suivi d'une lettre, qui permet de dire quoi afficher. %d représente int, %ld représente long, %f float ou double.
Les pointeurs en C sont des variables spéciales qui contiennent l'adresse mémoire d'une autre variable. Ils sont utilisés pour manipuler et accéder directement à cette variable en utilisant cette adresse.
Ainsi, bicyclettes correspond à la valeur de la variable et &bicyclettes correspond à l'adresse de cette même variable.
Pour créer une variable de type pointeur, on rajoute le symbole * devant son nom :
int *bicyclettes = &bicyclettes;
Les pointeurs semblent un peu archaïques et compliqués au début, mais on s'habitude vite.
On peut récupérer une variable avec scanf :
int main(int argc, char *argv[])
{
int bicyclettes = 0; // On initialise la variable à 0
printf("Combien de vélos sont dans votre garage ? ");
scanf("%d", &bicyclettes); // On demande d'entrer l'âge avec scanf
printf("Vous avez %d vélos dans votre garage.\n", bicyclettes);
return 0;
}
Combien de vélos sont dans votre garage ? 6
Vous avez 6 vélos dans votre garage.
Tableaux
Les tableaux s'initialisent comme suit:
int tableau[3];
tableau[0] = 1983;
tableau[1] = 1989;
tableau[2] = 1995;
Attention, les index des tableaux commencent à 0 et leur nom sans crochet est un pointeur sur l'adresse de la première case du tableau :
printf("%d", tableau);
Si on demande la variable qui se trouve à cette adresse, on obtient la première valeur du tableau, on fera :
printf("%d", *tableau);
Ce qui correspond à :
printf("%d", tableau[0]);
Pour avoir la 2e variable, on fera :
printf("%d", tableau[1]);
Le C a aussi les listes chaînées, les tables de hachage et les piles et les files.
Chaînes de caractères
Une chaîne de caractères est un tableau de type char. Elle se termine toujours par un \0, le caractère de fin de chaîne.
char chaine[8] = "manchot"; // manchot fait 7 lettres + le caractère \0
Il existe quelques fonctions prédéfinies dans la bibliothèque pour les chaînes string.h, par exemple :
#include <stdio.h>
#include <string.h>
int main() {
char chaine1[20] = "Hello";
char chaine2[20] = "World";
char resultat[40];
// strlen: longueur d'une chaîne
printf("Longueur de chaine1: %d\n", strlen(chaine1));
printf("Longueur de chaine2: %d\n", strlen(chaine2));
// strcat: concacténation de deux chaînes
strcat(chaine1, chaine2);
printf("Chaîne concacténée: %s\n", chaine1);
// strcpy: copie une chaîne dans une autre
strcpy(resultat, chaine1);
printf("Chaîne copiée: %s\n", resultat);
// strcmp: comparer deux chaînes
int comparison = strcmp(chaine1, chaine2);
if (comparison == 0) {
printf("Les chaînes sont égales.\n");
} else if (comparison < 0) {
printf("chaine1 est plus petite que chaine2.\n");
} else {
printf("chaine1 est plus grande que chaine2.\n");
}
// strstr: trouver une sous sous-chaîne dans une chaîne
char *substring = strstr(chaine1, "Léa");
if (substring != NULL) {
printf("Sous-chaîne trouvée: %s\n", substring);
} else {
printf("Sous-chaîne non trouvée.\n");
}
// sprintf: formater une chaîne
int num = 42;
sprintf(resultat, "La réponse est %d.", num);
printf("%s\n", resultat);
return 0;
}
On utilise \n pour aller à la ligne. Un autre caractère courant dans les chaînes est \t pour la tabulation.
Opérations sur les nombres
Les opérations sur les nombres sont assez simples :
#include <stdio.h>
int main() {
int num1, num2; // Déclaration de deux variables entières
int somme, difference, produit, division; // Déclaration des variables pour stocker les résultats des opérations
float divise; // Déclaration d'une variable pour stocker le résultat de la division (en raison de la précision limitée des nombres entiers)
// Lecture des deux nombres entiers
printf("Entrez deux nombres entiers : ");
scanf("%d,%d", &num1, &num2);
// Calcul des résultats des opérations
somme = num1 + num2;
difference = num1 - num2;
produit = num1 * num2;
division = (float)num1 / num2; // Calcul de la division et convertison au type flottant
modulo = num1 % num2; // Calcul de la modulo
// Affichage des résultats des opérations
printf("La somme des deux nombres entiers est : %d\n", somme);
printf("La différence entre les deux nombres entiers est : %d\n", difference);
printf("Le produit des deux nombres entiers est : %d\n", produit);
printf("La division de %d par %d est : %.2f\n", num1, num2, division); // Affichage de la division avec une précision de 2 chiffres décimaux
printf("Le modulo de %d par %d est : %d\n", num1, num2, modulo); // Affichage de la modulo
return 0;
}
Il y a aussi des raccourcis. Ainsi :
int main() {
int a = 5, b = 3;
//a++ correspond à a = a+1
printf("Addition avec assignement: %d\n", a++);
//a-- correspond à a = a-1
printf("Soustraction avec assignement: %d\n", a--);
//a *= b correspond à a = a*b
a *= b;
printf("Multiplication avec assignement: %d\n", a);
return 0;
}
Structures de contrôle
Voici un exemple avec les structures conditionnelles if, else if et else:
if (taille == "85a")
{
printf("Tout ce qui est petit est joli !");
}
else if (taille == "90b")
{
printf("Tout ce qui est moyen est bien !");
}
else if (taille == "95c")
{
printf("Quand c'est gros c'est beau !");
}
else
{
printf("Chaque taille a son charme");
}
Le même exemple avec switch:
switch (taille)
{
case "85a":
printf("Tout ce qui est petit est joli !");
break;
case "90b":
printf("Tout ce qui est moyen est bien !");
break;
case "95c":
printf("Quand c'est gros c'est beau !");
break;
default:
printf("Chaque taille a son charme");
break;
}
On peut aussi définir les conditions avec ? et :
jours = (bissextile) ? 366 : 365;
est équivalent à :
if (bissextile)
jours = 366;
else
jours = 365;
Une boucle en programmation est une structure qui permet de répéter un bloc de code plusieurs fois, en fonction d'une condition. Elle permet d'exécuter des instructions de manière itérative jusqu'à ce que la condition spécifiée soit satisfaite.
La boucle "while" exécute un bloc de code tant que la condition spécifiée est vraie.
int nombre = 0;
while (nombre < 5)
{
printf("La valeur est %d\n", nombres);
nombres++;
}
La boucle "for" parcourt un ensemble de valeurs et exécute quelque chose pour chaque valeur.
int compteur;
for (nombre = 0 ; nombre < 5 ; nombre++)
{
printf("La valeur est %d\n", nombre);
}
Fonctions
Normalement, on ne met pas tout dans le main mais on décompose son code en fonctions. Voici un exemple qui calcule la factorielle d'un nombre :
#include <stdio.h>
int factorielle(int n) {
if (n == 0 || n == 1) {
return 1;
} else {
return n * factorielle(n - 1);
}
}
int main() {
int num;
printf("Entrez un nombre: ");
scanf("%d", &num);
int result = factorielle(num);
printf("Factorielle de %d est %d\n", num, result);
return 0;
}
Manipulation des fichiers
fopen ouvre des fichiers, fclose les ferme, fgets les lit, fputs et fprintf écrivent des chaînes de caractère dedans. Ces fonctions prennent comme paramètre quelle permission est autorisée sur les fichiers : "r" (lecture), "w" (écriture); "r+" (lecture et écriture), "w+" (lecture et écriture, avec suppression du contenu précédemment).
#include <stdio.h>
#include <stdlib.h>
int main() {
FILE *fichier;
char entree[100];
// Ouvrir le fichier pour l'écriture
fichier = fopen("exemple.txt", "w");
if (fichier == NULL) {
printf("Erreur lors de l'ouverture du fichier\n");
return 1;
}
// Écrire du texte dans le fichier en utilisant fputs
fputs("Bonjour, le monde!\n", fichier);
// Écrire du texte formaté dans le fichier en utilisant fprintf
fprintf(fichier, "La valeur de PI est environ: %.2f\n", 3.14159);
// Fermer le fichier
fclose(fichier);
// Réouvrir le fichier pour la lecture
fichier = fopen("exemple.txt", "r");
if (fichier == NULL) {
printf("Erreur lors de l'ouverture du fichier\n");
return 1;
}
// Lire une ligne du fichier en utilisant fgets
fgets(entree, sizeof(entree), fichier);
printf("Entrée: %s", entree);
// Fermer le fichier
fclose(fichier);
return 0;
}
Mémoire
Une variable peut prendre plus ou moins d'espace en mémoire, notamment en fonction de son type. On peut réserver de la mémoire avec malloc() pour une variable et la libérer avec free().
#include <stdio.h>
#include <stdlib.h>
int main() {
int *ptr;
int n;
printf("Entrez le nombre d'entiers à allouer en mémoire : ");
scanf("%d", &n);
// Allocation de la mémoire pour n entiers à l'aide de malloc
ptr = (int*) malloc(n * sizeof(int));
if (ptr == NULL) {
printf("Erreur d'allocation de mémoire\n");
exit(1);
}
// Affectation de valeurs à la mémoire allouée
for (int i = 0; i < n; i++) {
ptr[i] = i * i;
}
// Affichage du contenu de la mémoire allouée
printf("Contenu de la mémoire allouée :\n");
for (int i = 0; i < n; i++) {
printf("%d ", ptr[i]);
}
printf("\n");
// Libération de la mémoire allouée à l'aide de free
free(ptr);
return 0;
}