Le langage C

a marqué ce sujet comme résolu.

Concernant l'usage d'un IDE, une des raisons qui fasse que son utilisation est plus agréable est que l'édition et la compilation se font dans la même fenêtre. Ainsi, en cas d'erreur, on n'a pas à jongler entre le terminal et l'éditeur de texte (évidemment, ce problème ne concerne pas les purs barbus qui codent tout dans le terminal).

quark67

L'objectif est justement de laisser l'utilisateur jongler entre les différents programmes pour que ce dernier cerne bien le rôle de chacun d'eux. Alors, oui, cela est moins confortable qu'un IDE, mais à mon sens c'est la solution la plus profitable pour un débutant. L'essentiel n'est pas qu'il ait diverses fonctionnalités (pratiques ou non) à disposition, mais qu'il comprenne ce qu'il fait. Or, à mes yeux, cela n'est possible que via la ligne de commande.

Si le but du tutoriel est d'apprendre le langage C (ce qui est déjà un gros morceau), je trouve que brouiller l'apprentissage en y ajoutant une navigation entre deux logiciels, avec des commandes à entrer au Terminal, n'est pas l'idéal.

quark67

Il ne me paraît pas y avoir de différence de diffcultés entre configurer et utiliser un IDE et configurer et utiliser un éditeur de texte et un terminal.

Il est toujours possible d'indiquer aux utilisateurs avancés (ou curieux) qu'il est aussi possible de faire les manipulations en mode Terminal en suivant les indications pour GNU/Linux, BSD et autres Unixoïdes*.

quark67

C'est la solution qui avait été adoptée auparavant, mais elle a été abandonnée par après pour les raisons que j'ai évoquées précédemment et aussi parce que cela est assez pénible de détailler x interfaces avec les captures d'écran qui vont bien et qui change toutes les x versions.

Sur les Unixoïdes, y a-t-il un IDE qui s'impose ? Sinon, je suppose que leurs utilisateurs ne seront pas dépaysés par la ligne de commande et le terminal.

quark67

Je ne sais pas s'il y a un IDE majoritaire, mais je connais Code::Blocks, Qt Creator et Geany.

Sur Windows qu'y a-t-il ? (j'ignore totalement)

quark67

Code::Blocks et Visual Studio.

+0 -0
  • séparation du dernier extrait du chapitre sur les fichiers en cinq extraits ;
  • ajout d'un passage sur la fonction ungetc() ;
  • ajout d'un TP portant sur la réalisation d'un Puissance 4 ;
  • diverses corrections mineures.

Je précise que l'IA proposée dans le TP est assez naïve, mais elle a l'avantage d'être relativement simple à mettre en œuvre sans se faire poutrée après quatre tours. :-°

+0 -0
  • ajout d'un chapitre sur la gestion d'erreur (dans la partie 2) ;
  • suppression des introductions et conclusions des différentes parties ;
  • suppression de la troisième partie du cours ;
  • modification de l'introduction et de la conculsion principale ;
  • la première partie a été rebaptisée en Les bases du langage C et la seconde en Aggrégats, mémoire et fichiers ;
  • diverses corrections mineures.

La partie 2 étant à présent clôturée, le cous est prêt pour la validation. Le contenu de celui-ci va donc être gelé en attendant. Vos propositions et corrections sont toutefois toujours les bienvenues. ;)

+0 -0

Bon, il est tard, je vais m'arrêter là. J'ai parcouru toute la première partie du cours, et voici tout ce que j'ai pu relever. Notez bien que j'avais commencé à relever aussi l'orthographe et la typographie dans un bloc-notes différent, mais je me suis interrompu après le chapitre 1 parce que… fin, voyez vous-mêmes.

Remarque générale : vous mélangez allègrement guillemets droits simples et apostrophes typographiques ; il faudrait utiliser ces dernières dans tout le texte.

Autre remarque générale : il faut vous mettre d'accord pour savoir si vous vouvoyez un lecteur unique ou si vous vous adressez à un groupe de lecteurs. En effet, ces trois passages du chapitre 1 sont incohérents et il est impossible de trancher sans une décision de votre part.

Il vous faut donc être bien motivés

vous y serez confronté tôt ou tard

Si vous vous sentez prêts

Intro générale

de revoir un certains nombres de points

certain nombre

et qui nous ont aidé à faire

aidés

Conclusion générale

Pour continuer votre apprentissage, voici quelques derniers conseils

Dans la mesure où chacun des points de votre liste comporte un double point, et que deux d'entre eux contiennent un point de fin de phrase, il est indispensable de mettre un point à la fin de cette phrase, une majuscule au début de chaque item de la liste et un point (pas un point-virgule) à la fin de chaque.

etc

Un point à la fin de « etc. » (qui fusionne avec le point de fin de phrase si vous adoptez mon conseil précédent) et surtout pas d'italique.

ou façon de faire et progressez

façons

Vous pouvez par exemple commencez

commencer

visitant les forums de ce site

Pas d'italique à « forums ».

Chapitre 1 : Avant-propos

n’importe qu'elle personne intéressée

quelle

Les explications seront les plus claires possible

possibles

Toutefois, quelques qualités sont opportunes pour arriver au bout de ce cours

Même remarque que plus haut sur la typographie des listes.

comprendre, s’entrainer, faire des erreurs

« vous entraîner » passerait mieux

de cours, de forums et documentations

et de

suivre ce cours sans problèmes

problème

Allez plus loin

« Aller » passerait mieux.

Chapitre 1 : La programmation, qu’est-ce que c’est ?

Tout ce que vous possédez sur votre ordinateur sont des programmes

est un programme

on ne peut pas créer d’instructions

instruction

certaines instructions de bases

base

sauf cas particulier vraiment tordus

particuliers

spécialement conçu pour effectuer ces instructions

exécuter

sous la forme de chiffres binaire

binaires

forme de zéro ou de un

suites de zéro et de un (x3)

zéros, uns

des ordres à effectuer

exécuter

imaginez que vous devez communiquer

deviez (le subjonctif est plus naturel, et il est utilisé un peu plus bas dans le même contexte « imaginez que »)

une suite de zéro et de un

Quater repetita placent

Ce langage s’appelle : le langage machine.

Pas de double point.

évolué en une suite de zéro et de un

Quinquies repetita placent, mais je vous ai suggéré de supprimer la phrase qui contient celle-là, donc ça compte pas vraiment. ^^

voici un code écrit en C (que nous apprendrons à connaître) :

Et le même en langage machine (plus précisémment pour un processeur de la famille x86-64) :

Un point à la place des doubles points.

Chapitre 1 : Le langage C

Son succès était tel auprès des informaticiens

fut

sans devoir changé ledit code

changer

vers d’autres langages comme le Python par exemple.

Une virgule après « langages ».

mais en contrepartie on voit moins bien le

Une virgule après « contrepartie ».

n’importe quel compilateur sans problèmes

problème

la norme officielle coûtant relativement chère

cher

Chapitre 1 : L’algorithmique

une liste de 10 nombres dans l'ordre croissant

dix

Voici un exemple de pseudo-code :

Un point à la place du double point.

Chapitre 1 : Conclusion

Souvenez-vous bien qu’il vous faudra

« Rappelez-vous que » ou « Souvenez-vous de ce que », mais pas de mélange.

Chapitre 1 : Avant-propos

Elle s’oppose à une autre plus fréquente et plus superficielle, qui permet certes d’acquérir des connaissances rapidement, mais qui s’avère bien souvent peu payante sur le long terme, beaucoup de programmeurs débutants se retrouvant ainsi perdus lorsqu’ils sont jetés dans la jungle de la programmation à la fin d’un cours, ceux-ci manquant souvent de connaissances techniques, de (bonnes) pratique(s) et de rigueur.

Cette phrase est trop longue, il faudrait la couper en deux. Par exemple, avec un « En effet, » entre « long terme » et « beaucoup de programmeurs ».

Toutefois, quelques qualités sont opportunes pour arriver au bout de ce cours :

Ce n'est pas très important, et un vrai lecteur ne s'en rendra sans doute pas compte, mais les conseils que vous donnez pour débuter recouvrent largement ceux que vous donnez pour continuer à apprendre dans la conclusion générale.

Chapitre 1 : La programmation, qu’est-ce que c’est ?

Notre ordinateur est conçu, câblé, et peut traiter certaines instructions de bases, précâblées dans ses circuits,

Le début de cette phrase (jusqu'à « câblé ») est assez obscur, et je ne peux vous proposer de correction, ne sachant pas ce que vous cherchez à dire.

Autant vous dire que créer des programmes de cette façon revient à se tirer une balle dans le pied.

N'hésitez surtout pas à mettre un lien vers mon cours sur l'assembleur, pour ceux qui voudraient se rendre compte à quel point cette affirmation est juste. :D

Il existe de nombreux langages de programmation, et le C est un de ces langages.

« est l'un d'entre eux » serait plus léger, ce paragraphe ayant déjà une certaine tendance à la répétition.

Autrement dit, le rôle du traducteur est de transformer un texte écrit dans un langage de programmation évolué en une suite de zéro et de un que le processeur peut comprendre. Il ne vous est ainsi plus nécessaire de connaître la langue de votre processeur.

Je sais que l'apprentissage est une longue répétition, mais là, ça fait vraiment trop : vous ne faites que paraphraser.

Malgré tous ces langages de programmation disponibles, nous allons dans ce tutoriel nous concentrer sur un seul langage : le langage C.

Le deuxième « langage » est vraiment lourd.

Chapitre 1 : Le langage C

La norme sert donc à officialiser tout un tas de règles pour que tous les interprètes (et donc les compilateurs) la suivent.

Idem, paraphrase.

Chapitre 2 : Windows

Ensuite, cliquez sur « paramètres systèmes avancés ». Dans la nouvelle fenêtre qui s'ouvre, allez dans « paramètres systèmes avancés »

Il y a donc un menu « paramètres systèmes avancés » dans une fenêtre qui porte déjà ce même nom ?

Pour le télécharger, rendez-vous simplement dans la rubrique « téléchargements ».

La rubrique « téléchargements » de quoi ?

Chapitre 2 : GNU/Linux, *BSD et autres Unixoïdes

Ceci dépend de votre interprétateur de commande.

Interpréteur. ;)

Également, c'est un détail, mais pour Windows comme pour OS X, vous indiquez comment lancer le terminal, mais par pour les Unixoïdes. Or, quelqu'un qui a besoin qu'on lui apprenne cd ou mkdir ne saura pas nécessairement lancer un terminal voire n'en aura jamais entendu parler.

Chapitre 2 : Mac OS X

Référez-vous à l'introduction dédiée à GNU/Linux, *BSD et les autres Unixoïdes.

Il y a pas mal de redites entre les différentes sections, du coup, il serait peut-être plus judicieux de regrouper les trois OS ensemble et de ne donner les différences que point par point. Ce qui permettrait de donner quelques explications supplémentaires, comme le fait que c'est toujours GCC qui est utilisé en sous-main, mais comme il vient de GNU/Linux, il est emballé sous les autres OS ; ou encore, expliquer vite fait les commandes ésotériques de configuration, qui sont globalement les mêmes sur les 3 OS.

Chapitre 2 : Notre cible

Vous en connaissez énormément, peut-être sans le savoir : le lecteur de musique, le navigateur Internet, le logiciel de discussion instantanée, la suite bureautique, les jeux vidéos, ce sont tous des programmes graphiques, ou programmes GUI.

Je trouve que vous vous répétez par rapport à votre explication sur ce que sont des programmes, dans le chapitre 1.

Voici un exemple de programme en console :

Comme exemple de programme GUI, vous prenez un vrai logiciel complet de la vraie vie, et comme exemple de programme en ligne de commande, vous prenez un jeu de bas étage qu'on n'utilise même pas en vrai mais uniquement comme exercice de cours : ce faisant, vous donnez une mauvaise image des programmes en ligne de commande, et vous risquez que votre lecteur se demande si ça vaut la peine de se fader 22 chapitres (que vous avez annoncés comme difficiles) pour en arriver juste là. Du coup, vous devriez prendre comme exemple de vrais logiciels complets tels qu'on peut en utiliser : parted, zip et unzip, voire ssh ou un navigateur en mode texte. Ça permettrait de montrer qu'on peut faire des choses fantastiques juste en ligne de commande.

Chapitre 2 : Première rencontre

zcc main.c

Sous Windows, c'est zcc.bat qu'il s'appelle, vous n'avez pas créé d'alias (si c'est seulement possible).

Chapitre 2 : Les commentaires

J'insisterais un peu plus sur la nécessité et l'utilité des commentaires, mais je suis un grand commentateur, et on a pu voir que ce n'est pas forcément le cas de tout le monde, donc peut-être êtes-vous plus dans le camp des sceptiques. :)

Chapitre 3 : Qu'est-ce qu'une variable

Comme en témoigne cette citation des années 1940, provenant des concepteurs d'un des tout premiers ordinateurs

Y'a pas de citation.

Je trouve tout le passage sur la mémoire beaucoup trop détaillé pour vos besoins, même si je me doute que mewtwo a dû se faire plaisir là-dessus. Quel besoin a-t-on de connaître les registres ? Un programmeur C ne les utilisera jamais. Quel besoin aussi d'insister sur la différence entre RAM et HDD ? Les OS modernes virtualisent tellement la mémoire que même à un niveau aussi bas que le C on ne peut jamais savoir où se situe physiquement la mémoire qu'on utilise. Tout le passage sur les adresses et les références paraît déplacé à ce stade, il ne sera guère utile qu'au moment de parler des pointeurs : à ce niveau de connaissance, l'explication de l'étiquette est amplement suffisante. Et moins rébarbative pour votre lecteur novice total. ^^

Chapitre 3 : Déclarer une variable

Le lien vers une image de PDP-11 est mort.

Peut-être mettre un paragraphe sur l'utilité du typage statique ? Je sais que quand j'ai commencé le C, je trouvais que ce système était une contrainte inutile par rapport à un typage dynamique à la PHP, et je ne doute pas que d'autres débutants auront la même réaction.

const long abc = 3141596;

Vu que juste après, dans le bloc info, vous parlez de const avec l'exemple de pi, ne vouliez-vous pas donner à abc la valeur 31415926 plutôt ?

Chapitre 4 : Introduction

Comme sur la question de la mémoire, je trouve cette présentation des choses très proche du matériel plus contre-productive qu'autre chose. Les OS ont la main-mise totale sur la communication avec le matériel, et le programmeur C ne sera guère amené à communiquer qu'avec des abstractions fournies par son OS : vos lecteurs n'enverront jamais la moindre information à leur écran, dans le meilleur des cas, ils écriront dans STDOUT. D'ailleurs vous revenez dessus en fin d'intro : on va écrire quelque chose dans la console, et pas ailleurs !

Chapitre 5 : Les opérations mathématiques de base

Division et modulo

Y'a des fois où le diviseur est 6, d'autres ou c'est 4 (comme si vous aviez changé en cours de route), et le tout est incohérent, genre printf("15 / 4 = %d\n", 15 / 6); : il faut choisir l'un ou l'autre.

Chapitre 6 : Les opérateurs logiques

En effet, comme pour les opérateurs mathématiques, les opérateurs logiques ont une priorité (revoyez le chapitre 6 si cela ne vous dit rien)

C'est dans le chapitre 5 que cette question est abordée.

Chapitre 7 : La structure if

Si la condition n'est pas vérifiée, le bloc d'instruction est passé et le programme recommence immédiatement à la suite du bloc d'instruction délimité par l'instruction if.

Paraphrase de l'explication suivante donnée trois lignes plus haut.

L'instruction if permet d'exécuter un bloc d'instructions si une condition est vérifiée ou de le passer si ce n'est pas le cas.

.

Dès lors, hors d'une instruction if suivie de plusieurs instructions else if (le tout éventuellement terminé par une instruction else), un seul bloc d'instruction sera exécuté.

Le « hors » paraît hors de propos.

else if (heure >= 7 && heure <= 12)

Il faut mettre 11, sinon, le else if (heure == 12) ne pourra jamais s'exécuter.

  • si le score est supérieur ou égal à 5000 et que le score est inférieur à 9000, afficherz : « tu es sur la bonne voie ! » ;
  • sinon, affichez : «

IT'S OVER NINE… (pardon, je me suis emporté… ^^ )

Chapitre 7 : L'instruction switch

printf("Quelle note as-tu obtenue ? "); (première occurrence)

C'est un détail, mais précisez « sur 5 » : les notes sont usuellement sur 20, donc vous avez 3 chances sur 4 que l'utilisateur entre une note improbable.

Chapitre 8 : Correction

1
2
3
4
5
6
7
8
9
    if (an > 1582)
    {
        njours += ((an - 1) / 4);
        njours -= ((an - 1) / 100);
        njours += ((an - 1) / 400);
        njours += 2;
    }
    else
        njours += ((an - 1) / 4);

Dans la mesure où njours += ((an - 1) / 4); est présent dans les deux possibilités, il serait plus élégant de le sortir du bloc conditionnel. En outre, ça rappellerait qu'un else n'est pas toujours nécessaire.

En outre, le calcul du nombre de jours à ajouter en fonction du mois où l'on est est assez fastidieux et long. Il s'agit sans doute de la méthode la plus évidente, je le reconnais volontiers. Je me permets cependant de vous proposer cette solution alternative, qui fait usage de deux autres notions abordées en cours, l'opérateur ternaire et le cast de type.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
float jourssup = (mois - 1) * 30.5;
int estbisextile = (an > 1582) ? (an % 4 == 0 && (an % 100 != 0 || an % 400 == 0)) : (an % 4 == 0);

if ((mois - 1) % 2 == 0)
    jourssup -= 0.5;

if (mois - 1 == 1)
    jourssup++;

if ((mois - 1) % 2 == 1 && (mois - 1) < 7)
    jourssup--;

if ((mois - 1) != 1 && !estbisextile)
    jourssup--;

if (mois - 1 == 0)
    jourssup = 0;

njours += (int) jourssup;

Pour vous convaincre de l'efficacité de la méthode, voici un tableau du nombre de jours cumulés à la fin de chaque mois.

Valeur moyenne 30,5 61,0 91,5 122,0 152,5 183,0 213,5 244,0 274,5 305,0 335,5 366,0
Année ordinaire 31 59 90 120 151 181 212 243 273 304 334 365
Année bissextile 31 60 91 121 152 182 213 244 274 305 335 366

Chapitre 9 : La boucle while

puts("nombre = ");

La fonction puts est inconnue du lecteur à ce stade du cours.

Chapitre 9 : La boucle do-while

Il me semble important que vous métiez un exemple concret de cas où la boucle do-while apporte vraiment quelque chose et n'est pas une facétie du langage, parce qu'un débutant a de fortes chances de se demander à quoi elle sert en pratique.

Chapitre 9 : Exercices

1
2
3
        km += 5;
        printf("%u %u\n", km, km * 8 / 5);
    } while(km < 30);

Ça me paraît peu élégant. J'aurais plutôt fait comme ça.

1
2
3
        km++;
        printf("%u %u\n", km * 5, km * 8);
    } while(km * 5 < 30);

Mais bon, c'est un détail.

1
puts("Veuillez entrez un nombre : ");

Cf. supra.

1
    if (c == 'e' || c == 'E')

Vous ne comptez donc pas les -e- accentués ? Un mot comme « répétition » va passer entre les mailles du filet. ^^

Chapitre 10 : L'instruction continue

Afin d'améliorer un peu l'exemple précédent, nous pourrions passer les cas où le diviseur testé est un multiple de deux (puisque si un des deux nombres n'est pas divisible par deux, il ne peut pas l'être par quatre, par exemple).

Tel que votre code est écrit, la divisibilité commune par 2 n'est jamais testée, donc avec 112 et 568 en entrée, le résultat sera faux.

Chapitre 11

J'ai vu que vous essayez d'être assez exhaustifs sur les sujets que vous abordez dans chaque chapitre, du coup, je m'étonne que vous ne parliez pas des fonctions inline. Ou est-ce que cela n'existe pas en C89 ?

Chapitre 12 : Préparation

Les puissances

Il est assez simple de se passer de la fonction pow, à condition de n'accepter que les exposants entiers : la fonction puissance devient alors une boucle contenant des multiplications de la base par elle-même. C'est d'ailleurs comme ça (enfin, par une fonction récursive, mais c'est l'idée) qu'elle est définie dans la bibliothèque standard du Haskell.

La factorielle

Ne pas oublier que par convention, $0! = 1$.

Chapitre 12 : Correction

Si l'opérateur utilisé est q, alors nous quittons la boucle et par la même occasion le programme. Notez que nous n'avons pas pu effectuer cette vérification dans le corps de l'instruction switch qui suit puisque l'instruction break nous aurait fait quitter celui-ci et non la boucle.

Cela étant, vous auriez très bien pu l'intégrer au switch et sortir du tout grâce à un return, puisque le programme ne fait rien après la boucle infinie. Mais c'est un détail.

Chapitre 13 : Introduction

Ce chapitre est la suite directe du précédent

Du chapitre 11, vu que le TP est venu s'intercaler.

Chapitre 13 : Portée et masquage

Au niveau d'un fichier

Dans le chapitre sur les fonctions, vous avez déjà abondamment parlé des variables globales : il faudrait rappeler que c'est strictement la même chose dont vous parlez ici, pour ne pas donner l'impression qu'il y a deux phénomènes distincts.

Chapitre 13 : Diviser pour mieux régner

Dans le chapitre précédent, nous avions, entre autres, créé une fonction triple() que nous avons placée dans le même fichier que la fonction main().

C'était dans l'extrait précédent.

+3 -0

ben… Quel pavé ! :p
Merci infiniment pour le temps que tu as consacré à cette relecture et pour tes propositions. Également, toutes mes plus plates excuses pour la quantité astronomique de fautes d'orthographe. :-°

EDIT : si je ne dis rien au sujet d'une correction, c'est qu'elle a été appliquée (sauf si c'était une question de détail, là je l'ai peut être passée).

Orthographe

Remarque générale : vous mélangez allègrement guillemets droits simples et apostrophes typographiques ; il faudrait utiliser ces dernières dans tout le texte.

Dominus Carnufex

Ça, c'est en partie de ma faute et cela va être très gênant à modifier… Il va falloir que je regarde du côté du système d'imporation et d'exportation pour pouvoir modifier cela en ligne de commande.

Autre remarque générale : il faut vous mettre d'accord pour savoir si vous vouvoyez un lecteur unique ou si vous vous adressez à un groupe de lecteurs.

Dominus Carnufex

La confusion est dûe à une erreur d'accord (qui est désormais corrigée), nous vouvoyons un groupe de lecteurs.

Un point à la fin de « etc. » (qui fusionne avec le point de fin de phrase si vous adoptez mon conseil précédent) et surtout pas d'italique.

Dominus Carnufex

Les termes latins ne sont pas censés être en italique ?

Quinquies repetita placent, mais je vous ai suggéré de supprimer la phrase qui contient celle-là, donc ça compte pas vraiment. ^^

Dominus Carnufex

Je ne vois pas de suggestion visant à supprimer une phrase.

voici un code écrit en C (que nous apprendrons à connaître) : Et le même en langage machine (plus précisémment pour un processeur de la famille x86-64) :

Un point à la place des doubles points.

Dominus Carnufex

Ouch ! J'ai utilisé cette typographie dans tout le cours. >_<

Mise en forme et fond

Ce n'est pas très important, et un vrai lecteur ne s'en rendra sans doute pas compte, mais les conseils que vous donnez pour débuter recouvrent largement ceux que vous donnez pour continuer à apprendre dans la conclusion générale.

Dominus Carnufex

Effectivement, mais bon, le cœur de l'enseignement n'est-il pas la répétition ? :-°

Chapitre 1 : La programmation, qu’est-ce que c’est ?

Notre ordinateur est conçu, câblé, et peut traiter certaines instructions de bases, précâblées dans ses circuits,

Le début de cette phrase (jusqu'à « câblé ») est assez obscur, et je ne peux vous proposer de correction, ne sachant pas ce que vous cherchez à dire.

Dominus Carnufex

J'ai modifié cette phrase en : « [n]otez qu'il n’est pas possible de créer des instructions. Ces dernières sont imprimées dans les circuits de l’ordinateur ce qui fait qu'il ne peut en gérer qu'un nombre précis et qu’il ne vous est donc pas loisible d'en construire de nouvelles (sauf cas particuliers vraiment tordus) » (elle est désormais au sein d'un bloc d’information).

Autant vous dire que créer des programmes de cette façon revient à se tirer une balle dans le pied.

N'hésitez surtout pas à mettre un lien vers mon cours sur l'assembleur, pour ceux qui voudraient se rendre compte à quel point cette affirmation est juste. :D

Dominus Carnufex

C'est fait. ^^

Chapitre 2 : Windows

Ensuite, cliquez sur « paramètres systèmes avancés ». Dans la nouvelle fenêtre qui s'ouvre, allez dans « paramètres systèmes avancés »

Il y a donc un menu « paramètres systèmes avancés » dans une fenêtre qui porte déjà ce même nom ?

Ben quoi ? C'est Windows, hein ! :-°
Plus sérieusement, c'est corrigé. J'en ai profité pour revoir un peu la typographie (le mélange de guillemets et d'italique ne me semblait pas terrible à la relecture).

Également, c'est un détail, mais pour Windows comme pour OS X, vous indiquez comment lancer le terminal, mais par pour les Unixoïdes. Or, quelqu'un qui a besoin qu'on lui apprenne cd ou mkdir ne saura pas nécessairement lancer un terminal voire n'en aura jamais entendu parler.

Dominus Carnufex

J'ai ajouté une petite indication au cas où.

Chapitre 2 : Mac OS X

Référez-vous à l'introduction dédiée à GNU/Linux, *BSD et les autres Unixoïdes.

Il y a pas mal de redites entre les différentes sections, du coup, il serait peut-être plus judicieux de regrouper les trois OS ensemble et de ne donner les différences que point par point. Ce qui permettrait de donner quelques explications supplémentaires, comme le fait que c'est toujours GCC qui est utilisé en sous-main, mais comme il vient de GNU/Linux, il est emballé sous les autres OS ; ou encore, expliquer vite fait les commandes ésotériques de configuration, qui sont globalement les mêmes sur les 3 OS.

Dominus Carnufex

De ce côté, je prefère conserver la séparation actuelle.

Voici un exemple de programme en console :

Comme exemple de programme GUI, vous prenez un vrai logiciel complet de la vraie vie, et comme exemple de programme en ligne de commande, vous prenez un jeu de bas étage qu'on n'utilise même pas en vrai mais uniquement comme exercice de cours : ce faisant, vous donnez une mauvaise image des programmes en ligne de commande, et vous risquez que votre lecteur se demande si ça vaut la peine de se fader 22 chapitres (que vous avez annoncés comme difficiles) pour en arriver juste là. Du coup, vous devriez prendre comme exemple de vrais logiciels complets tels qu'on peut en utiliser : parted, zip et unzip, voire ssh ou un navigateur en mode texte. Ça permettrait de montrer qu'on peut faire des choses fantastiques juste en ligne de commande.

J'ai remplacer l'exemple de programme par un début de partie sous GNU Chess. Présenter un programme comme un navigateur serait mentir car ils recourent à des bibliothèques comme Ncurses ou Libcaca (qui ne seront pas présentées dans ce cours).

Chapitre 2 : Première rencontre

zcc main.c

Sous Windows, c'est zcc.bat qu'il s'appelle, vous n'avez pas créé d'alias (si c'est seulement possible).

Dominus Carnufex

Il n'est pas nécessaire de créer d'alias, Windows recherche l'exécutable demandé parmis les fichiers d'extension .exe et .bat (entre autres, je penses qu'il y aussi les DLL).

J'insisterais un peu plus sur la nécessité et l'utilité des commentaires, mais je suis un grand commentateur, et on a pu voir que ce n'est pas forcément le cas de tout le monde, donc peut-être êtes-vous plus dans le camp des sceptiques. :)

Dominus Carnufex

Je préfère rester plutôt évasif sur ce sujet étant donné que cela dépend un peu de chacun (et que je ne suis pas un grand commentateur, j'avoue :p ).

Je trouve tout le passage sur la mémoire beaucoup trop détaillé pour vos besoins, même si je me doute que mewtwo a dû se faire plaisir là-dessus. Quel besoin a-t-on de connaître les registres ? Un programmeur C ne les utilisera jamais. Quel besoin aussi d'insister sur la différence entre RAM et HDD ? Les OS modernes virtualisent tellement la mémoire que même à un niveau aussi bas que le C on ne peut jamais savoir où se situe physiquement la mémoire qu'on utilise. Tout le passage sur les adresses et les références paraît déplacé à ce stade, il ne sera guère utile qu'au moment de parler des pointeurs : à ce niveau de connaissance, l'explication de l'étiquette est amplement suffisante. Et moins rébarbative pour votre lecteur novice total. ^^

Dominus Carnufex

Je pense qu'il est toujours bon d'en parler ne fut-ce que pour la culture générale. Après cela va peut être trop dans le détail, effectivement. À voir avec Mewtow

Peut-être mettre un paragraphe sur l'utilité du typage statique ? Je sais que quand j'ai commencé le C, je trouvais que ce système était une contrainte inutile par rapport à un typage dynamique à la PHP, et je ne doute pas que d'autres débutants auront la même réaction.

Dominus Carnufex

Hmm… Cela semble être une bonne idée, oui. Nous allons nous pencher là-dessus.

Comme sur la question de la mémoire, je trouve cette présentation des choses très proche du matériel plus contre-productive qu'autre chose. Les OS ont la main-mise totale sur la communication avec le matériel, et le programmeur C ne sera guère amené à communiquer qu'avec des abstractions fournies par son OS : vos lecteurs n'enverront jamais la moindre information à leur écran, dans le meilleur des cas, ils écriront dans STDOUT. D'ailleurs vous revenez dessus en fin d'intro : on va écrire quelque chose dans la console, et pas ailleurs !

Dominus Carnufex

J'ai remplacé le terme écran par console dans l'extrait afin d'être plus clair.

Chapitre 7 : La structure if

Si la condition n'est pas vérifiée, le bloc d'instruction est passé et le programme recommence immédiatement à la suite du bloc d'instruction délimité par l'instruction if.

Paraphrase de l'explication suivante donnée trois lignes plus haut.

L'instruction if permet d'exécuter un bloc d'instructions si une condition est vérifiée ou de le passer si ce n'est pas le cas.

Dominus Carnufex

C'est vrai qu'il y a répétition, mais cela me semble acceptable puisqu'il s'agit de reprendre l'explication en présentant la syntaxe de l'instruction.

En outre, le calcul du nombre de jours à ajouter en fonction du mois où l'on est est assez fastidieux et long. Il s'agit sans doute de la méthode la plus évidente, je le reconnais volontiers. Je me permets cependant de vous proposer cette solution alternative, qui fait usage de deux autres notions abordées en cours, l'opérateur ternaire et le cast de type.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
float jourssup = (mois - 1) * 30.5;
int estbisextile = (an > 1582) ? (an % 4 == 0 && (an % 100 != 0 || an % 400 == 0)) : (an % 4 == 0);

if ((mois - 1) % 2 == 0)
    jourssup -= 0.5;

if (mois - 1 == 1)
    jourssup++;

if ((mois - 1) % 2 == 1 && (mois - 1) < 7)
    jourssup--;

if ((mois - 1) != 1 && !estbisextile)
    jourssup--;

if (mois - 1 == 0)
    jourssup = 0;

njours += (int) jourssup;

Pour vous convaincre de l'efficacité de la méthode, voici un tableau du nombre de jours cumulés à la fin de chaque mois.

Valeur moyenne 30,5 61,0 91,5 122,0 152,5 183,0 213,5 244,0 274,5 305,0 335,5 366,0
Année ordinaire 31 59 90 120 151 181 212 243 273 304 334 365
Année bissextile 31 60 91 121 152 182 213 244 274 305 335 366

Dominus Carnufex

Nous pourrions proposé une deuxième correction, cela ne mange pas de pain.
Maintenant, il y a un point qui me chiffonne : pourquoi soustraire 0.5 étant donné que seules des unités entières sont ajoutées par après ?
Aussi, concernant l'opérateur ternaire, je ne sais pas si c'est un bon exemple d'utilisation (l'expression est un peu longue et plutôt lourde).

Il me semble important que vous métiez un exemple concret de cas où la boucle do-while apporte vraiment quelque chose et n'est pas une facétie du langage, parce qu'un débutant a de fortes chances de se demander à quoi elle sert en pratique.

Chapitre 9 : Exercices

1
2
3
        km += 5;
        printf("%u %u\n", km, km * 8 / 5);
    } while(km < 30);

Ça me paraît peu élégant. J'aurais plutôt fait comme ça.

1
2
3
        km++;
        printf("%u %u\n", km * 5, km * 8);
    } while(km * 5 < 30);

Dominus Carnufex

Oui, mais dans ce cas c'est incorrect. :-°

1
    if (c == 'e' || c == 'E')

Vous ne comptez donc pas les -e- accentués ? Un mot comme « répétition » va passer entre les mailles du filet. ^^

Dominus Carnufex

Là, tu mets le doigt sur un gros problème en C : la représentation des chaînes de caractères et les différents encodages.
Ceci fera l'objet d'un (ou plusieurs) chapitres dans la future partie 3.

Chapitre 11

J'ai vu que vous essayez d'être assez exhaustifs sur les sujets que vous abordez dans chaque chapitre, du coup, je m'étonne que vous ne parliez pas des fonctions inline. Ou est-ce que cela n'existe pas en C89 ?

Dominus Carnufex

En effet, c'est un ajout de la norme C99. ;)

Chapitre 12 : Préparation

Les puissances

Il est assez simple de se passer de la fonction pow, à condition de n'accepter que les exposants entiers : la fonction puissance devient alors une boucle contenant des multiplications de la base par elle-même. C'est d'ailleurs comme ça (enfin, par une fonction récursive, mais c'est l'idée) qu'elle est définie dans la bibliothèque standard du Haskell.

Dominus Carnufex

C'est exact, mais nous avons besoin de présenter cette fonction pour aborder la gestion d'erreur avec la variable errno un peu plus loin.

+0 -0

Voici mes justifications concernant le passage sur la mémoire, dans le chapitre sur les variables.

Concernant les explications sur les registres, les premières versions du tutoriel évoquaient le mot-clé register. Mais on peut l'enlever à l'heure actuelle. On peut peut-être sabrer un peu dans les explications (notamment avec la citation, toussa).

Évoquer la présence du disque dur ne me parait pas inutile, vu qu'on parlera un peu des fichiers plus tard, et que faire la distinction entre disque dur et RAM peut aider vis à vis de ça.

Les explications sur les cases mémoires et octets sont utiles pour comprendre en détail la notion de taille des types.

Pour les explications sur les adresses, elle sont utilisées dans les chapitres sur les pointeurs, tableaux et structures. Or, les extraits de ces chapitres qui ont besoin de la notion d'adresse sont, soit très chargés, soit parlent de notions peu intuitives et pour lesquels il vaut mieux donc limiter le nombre d'informations. Dans ces conditions, mieux vaut déplacer les explications sur les adresses ailleurs que dans le chapitre sur les pointeurs/tableaux/structures : le chapitre sur les variables est le meilleur choix, vu que cela permet d'expliquer ce qui se cache derrière les noms de variables (remplacent les références).

De plus, on fait référence à la notion d'adresse dans le chapitre sur les I/O, pour scanf. Ce n'est pas forcément nécessaire, mais c'est un petit plus pour la compréhension.

Et j'ai quelques autres raisons un peu plus techniques.

+0 -0

Voici la suite de ma relecture, consacrée à la partie 2. Mais avant tout, un retour sur tes réponses.

Également, toutes mes plus plates excuses pour la quantité astronomique de fautes d'orthographe. :-°

Vous faciliteriez grandement le travail de relecture si vous commenciez par vérifier vous-même tous les cas où :

  • vous confondez infinitif (manger) et participe passé (mangé), voire présent P5 (mangez) ;
  • vous mélangez singulier et pluriel, des noms et adjectifs (grand / grands) comme des verbes (ils mange au lieu de ils mangent) ;
  • vous confondez pluriel des noms et pluriels des verbes (ils parcours au lieu de ils parcourent) ;
  • vous confondez les homophones usuels (et/est, peu/peut, qu'elle/quelle, son/sont, etc. voir le Bled pour la liste complète ^^ ).

Rien qu'avec ça vous élimineriez la majorité des fautes. :D

Les termes latins ne sont pas censés être en italique ?

Pas quand ils sont d'usage tellement courant en français qu'ils ont pleinement intégré la langue (par exemple, « etc. », « a priori », « ad hoc », mais « hic et nunc » et « urbi et orbi »).

Je ne vois pas de suggestion visant à supprimer une phrase.

C'est plus bas, dans les remarques que tu as prises en compte.

Ouch ! J'ai utilisé cette typographie dans tout le cours. >_<

Je sais, t'es pas le seul à faire ça…

Il n'est pas nécessaire de créer d'alias, Windows recherche l'exécutable demandé parmis les fichiers d'extension .exe et .bat (entre autres, je penses qu'il y aussi les DLL).

OK, j'ignorais. Ça fait tellement longtemps que j'ai pas touché à Windows… ^^

Nous pourrions proposé une deuxième correction, cela ne mange pas de pain.
Maintenant, il y a un point qui me chiffonne : pourquoi soustraire 0.5 étant donné que seules des unités entières sont ajoutées par après ?

Je ne sais pas trop comment la conversion de double à int réagit face à un nombre situé exactement entre deux entiers, donc je préfère régler le cas moi-même que me reposer sur la machine.

Aussi, concernant l'opérateur ternaire, je ne sais pas si c'est un bon exemple d'utilisation (l'expression est un peu longue et plutôt lourde).

On peut le présenter sur trois lignes, ça sera plus lisible et permettra de supprimer quelques parenthèses.

Oui, mais dans ce cas c'est incorrect. :-°

On m'aurait menti ? $n \times 5 \times \lfrac 8 5$ serait donc différent de $n \times 8$ ? :P

Chapitre 15 : Présentation

Pour que cela fonctionne, le seul moyen est de fournir au programme une référence vers la zone allouée.

Cette phrase serait plus claire en disant « Pour que cela fonctionne, le seul moyen est que le système d'exploitation fournisse au programme une référence vers la zone allouée. ».

Chapitre 15 : Utilisation

La syntaxe pour déclarer un pointeur est la suivante :

Vous devriez signaler que la position de l'astérisque n'a pas d'importance du moment qu'elle est entre le type et le nom : int *ptr, int * ptr et int* ptr ont tous trois le même résultat, et si le premier est le plus courant, j'ai déjà rencontré les deux autres dans des codes. Ça peut être bien que vos lecteurs ne soient pas effarouchés si ça leur arrive. :)

Chapitre 15 : Un peu de mémoire

(nous verrons plus tard ce qu'est une macrofonction lorsque nous aborderons le préprocesseur)

Cette notion n'est pas abordée par la suite. Il est sûrement prévu qu'elle apparaisse dans la partie 3, mais pour une validation partielle sans cette dernière partie, il faut formuler l'annonce autrement.

Chapitre 16 : Définition, initialisation et utilisation

L'exemple ci-dessous initialise le membre heures à 1, minutes à 45 et secondes à 30.

30.560 si j'en crois le code en-dessous.

Chapitre 16 : Portée et déclarations

Les structures interdépendantes

Structure qui pointe sur elle-même

Il serait sans doute bon de donner un exemple concret de cas où une telle construction est nécessaire, parce que ça reste assez ésotérique, en l'état.

Chapitre 16 : Un peu de mémoire

La macrofonction offsetof

Je ne comprends pas pourquoi la contrainte d'alignement est différente d'un type à l'autre. La taille de bus mémoire est censée être la même tout le temps, c'est bien pour ça qu'on a besoin de bourrage, non ? Alors pourquoi un double a besoin d'être aligné à 8 alors qu'un short se contente de 2 ?

Chapitre 17 : Les tableaux simples (à une dimension)

struct temps tab[2] = { { 12, 45, 50.6401 }, { 13, 30, 35.480 } } ;

Il y a un chiffre après la virgule de trop dans 50.6401.

Chapitre 17 : Les tableaux multidimensionnels

d'une grille de Sudoku qui est organisée en trois lignes et en trois colonnes

Chez moi, les Sudoku font 9 sur 9 ou, à la rigueur, 15 sur 15…

Et ainsi de suite jusqu'à ce que mort s'en suive…

La norme n'impose donc pas de limite de pronfondeur, à la manière des 31 arguments d'une fonction ou 127 membres d'une strucutre ?

Chapitre 18 : Afficher et récupérer une chaîne de caractères

Heureusement, il nous est possible de préciser à scanf() que des données ne nous intéressent pas en plaçant le symbole * juste après symbole *.

La deuxième astérisque devrait être un symbole pourcentage.

Chapitre 18 : Manipulation des chaînes de caractères

Les trois petits points à la fin du prototype de la fonction signifie que celle-ci attend un nombre variable d'arguments. Nous verrons ce mécanisme plus en détail un peu plus tard.

Même remarque que pour les macrofonctions.

Chapitre 18 : Exercices

Compter les parenthèses

Pourquoi int main(void) { se retrouve-t-il sur trois lignes ? Idem pour strtok : pourquoi le début de la fonction est-il sur trois lignes ?

Remarque générale sur ce chapitre : c'est sans doute parce que je commence à fatiguer, mais celui-là m'a paru vraiment rébarbatif. Votre choix d'être plutôt une référence qu'un vrai cours fait sentir ses limites sur un sujet comme celui-là. Cette remarque s'applique aussi au chapitre 20 sur les fichiers, qui est encore plus fastidieux.

Chapitre 19 : La notion d'objet

La différence entre les types tient simplement en la manière dont ils répartissent les données au sein de ces objets, ce qui est appelé leur représentation (celle-ci sera abordée lors de chapitres ultérieurs).

Même remarque que pour les macrofonctions.

Chapitre 21

Quand vous vérifiez si un joueur a gagné, vous vérifiez si dans une des directions se trouve un alignement d'exactement 4 jetons du joueur. Or, un joueur peut parvenir à créer un alignement de 5 voire plus jetons à lui : la situation est rare, mais je l'ai déjà rencontrée en partie réelle. Et dans votre programme, le joueur n'aurait pas gagné.

La même remarque s'applique à la fonction ia() du deuxième exercice.

Je précise que je n'ai pas intégralement relu les codes proposés comme je le fais ailleurs : ils sont vraiment longs et j'ai pas la foi. ^^

Chapitre 22 : Fin d'un programme

Une image mémoire est en fait un fichier contenant l'état des registres et de la mémoire d'un pogramme lors de la survenance d'un problème. Nous reviendrons sur ce sujet un peu plus tard lorsque nous parlerons du déboguage.

Même remarque que pour les macrofonctions.

+1 -0

Vous faciliteriez grandement le travail de relecture si vous commenciez par vérifier vous-même tous les cas où :

  • vous confondez infinitif (manger) et participe passé (mangé), voire présent P5 (mangez) ;
  • vous mélangez singulier et pluriel, des noms et adjectifs (grand / grands) comme des verbes (ils mange au lieu de ils mangent) ;
  • vous confondez pluriel des noms et pluriels des verbes (ils parcours au lieu de ils parcourent) ;
  • vous confondez les homophones usuels (et/est, peu/peut, qu'elle/quelle, son/sont, etc. voir le Bled pour la liste complète ^^ ).

Dominus Carnufex

On va essayer de regarder cela (je dois avouer ne pas vraiment avoir pris le temps de relire mes textes pour ce qui est de l'orthographe…). D'ailleurs, j'ai une question (peut-être stupide) qui me trotte dans la tête depuis un certain temps. Dans les phrases du genre un identificateur de fonction, une ligne de commande ou encore une structure de donnée, faut-il mettre le dernier mot au pluriel (donc ici fonction, commande et donnée) ?

Les termes latins ne sont pas censés être en italique ?

Pas quand ils sont d'usage tellement courant en français qu'ils ont pleinement intégré la langue (par exemple, « etc. », « a priori », « ad hoc », mais « hic et nunc » et « urbi et orbi »).

Dominus Carnufex

Ok, c'est noté, merci. ;)

Je ne sais pas trop comment la conversion de double à int réagit face à un nombre situé exactement entre deux entiers, donc je préfère régler le cas moi-même que me reposer sur la machine.

Dominus Carnufex

Qu'entends-tu par « un nombre situé exactement entre deux entiers » ?
Parce que, pour ce qui est du C, le passage d'un type flottant vers un type entier se réalise en laissant tomber la partie fractionnaire, c'est tout. Un problème se pose uniquement si la valeur du nombre flottant dépasse la capacité du type entier de destination.

Aussi, concernant l'opérateur ternaire, je ne sais pas si c'est un bon exemple d'utilisation (l'expression est un peu longue et plutôt lourde).

On peut le présenter sur trois lignes, ça sera plus lisible et permettra de supprimer quelques parenthèses.

Dominus Carnufex

Cela reste relativement lourd (et proche d'une structure if dans ce cas). Cependant, c'est vrai que c'est assez fréquent comme construction.

Oui, mais dans ce cas c'est incorrect. :-°

On m'aurait menti ? $n \times 5 \times \frac 8 5$ serait donc différent de $n \times 8$ ? :P

Dominus Carnufex

Hum… Au temps pour moi, j'ai lu ton exemple un peu rapidement. :-°

Chapitre 15 : Un peu de mémoire

(nous verrons plus tard ce qu'est une macrofonction lorsque nous aborderons le préprocesseur)

Cette notion n'est pas abordée par la suite. Il est sûrement prévu qu'elle apparaisse dans la partie 3, mais pour une validation partielle sans cette dernière partie, il faut formuler l'annonce autrement.

Dominus Carnufex

J'ai précisé que celle-ci serait vue dans la troisième partie du cours afin que le lecteur sache que cela ne serait présenté que dans une prochaine version du cours.

Chapitre 16 : Portée et déclarations

Les structures interdépendantes

Structure qui pointe sur elle-même

Il serait sans doute bon de donner un exemple concret de cas où une telle construction est nécessaire, parce que ça reste assez ésotérique, en l'état.

Dominus Carnufex

Le soucis, c'est qu'un des exemples les plus parlant est une liste chaînée et qu'il est encore trop tôt pour présenter ces dernières.

Chapitre 16 : Un peu de mémoire

La macrofonction offsetof

Je ne comprends pas pourquoi la contrainte d'alignement est différente d'un type à l'autre. La taille de bus mémoire est censée être la même tout le temps, c'est bien pour ça qu'on a besoin de bourrage, non ? Alors pourquoi un double a besoin d'être aligné à 8 alors qu'un short se contente de 2 ?

Dominus Carnufex

L'objectif de l'alignement est d'éviter qu'une donnée soit à cheval sur deux ou plusieurs mots (un mot étant une suite de multiplets correspondant à la taille maximale du bus). Or, un short de deux octets tiendra forcément dans un mot de huit octets s'il a une adresse multiple de deux.

Chapitre 17 : Les tableaux simples (à une dimension)

struct temps tab[2] = { { 12, 45, 50.6401 }, { 13, 30, 35.480 } } ;

Il y a un chiffre après la virgule de trop dans 50.6401.

Dominus Carnufex

Comment ça « en trop » ? Ce n'est pas symétrique, c'est ça ? :p

Et ainsi de suite jusqu'à ce que mort s'en suive…

La norme n'impose donc pas de limite de pronfondeur, à la manière des 31 arguments d'une fonction ou 127 membres d'une strucutre ?

Dominus Carnufex

Pour les tableaux, non, il ne me semble pas. Par contre, il est possible de buter sur deux limites :

  • la longueur maximale d'une ligne (qui est de minimum 509 caractères) ;
  • la taille maximale d'un objet (qui est de minium 32767 multiplets).

Chapitre 18 : Exercices

Compter les parenthèses

Pourquoi int main(void) { se retrouve-t-il sur trois lignes ? Idem pour strtok : pourquoi le début de la fonction est-il sur trois lignes ?

Dominus Carnufex

Parce qu'il s'agit de mon style par défaut et que j'ai oublié de modifier cela en éditant le chapitre. :-°

Remarque générale sur ce chapitre : c'est sans doute parce que je commence à fatiguer, mais celui-là m'a paru vraiment rébarbatif. Votre choix d'être plutôt une référence qu'un vrai cours fait sentir ses limites sur un sujet comme celui-là. Cette remarque s'applique aussi au chapitre 20 sur les fichiers, qui est encore plus fastidieux.

Dominus Carnufex

Ce sont effectivement les deux chapitres les plus lourds du cours. Je réfléchissais à éventuellement scinder celui sur les fichiers en deux.

Chapitre 21

Quand vous vérifiez si un joueur a gagné, vous vérifiez si dans une des directions se trouve un alignement d'exactement 4 jetons du joueur. Or, un joueur peut parvenir à créer un alignement de 5 voire plus jetons à lui : la situation est rare, mais je l'ai déjà rencontrée en partie réelle. Et dans votre programme, le joueur n'aurait pas gagné.

Dominus Carnufex

C'est bien vu, je n'y avais pas pensé. :)

La même remarque s'applique à la fonction ia() du deuxième exercice.

Dominus Carnufex

Vu la manière dont est programmée l'IA, il n'est pas possible qu'elle créée des lignes de plus de quatres jetons.

Je précise que je n'ai pas intégralement relu les codes proposés comme je le fais ailleurs : ils sont vraiment longs et j'ai pas la foi. ^^

Dominus Carnufex

Y a pas de soucis, le travail que tu as réalisé des déjà énorme.
Un grand merci à toi. ;)

+0 -0

D'ailleurs, j'ai une question (peut-être stupide) qui me trotte dans la tête depuis un certain temps. Dans les phrases du genre un identificateur de fonction, une ligne de commande ou encore une structure de donnée, faut-il mettre le dernier mot au pluriel (donc ici fonction, commande et donnée) ?

Je peux pas te donner de réponse générale, parce que ça peut dépendre du contexte, mais globalement, il faut te demander combien le premier mot contient du deuxième mot. Par exemple, en ligne de commande, chaque ligne contient ordinairement une commande (fût-elle complexe), donc « commande » au singulier. Au contraire, une structure contiendra généralement des données, donc « structure de données ». Chaque identificateur identifie une seule fonction, donc « identificateur de fonction ».

De même, on dira « un tas de briques », parce qu'il y a plusieurs briques dans un tas. Parfois le cas est ambigu : on peut dire « mur de briques », si on considère les briques comme objets individuels, ou « mur de brique », si on considère la brique comme matière. Mais c'est assez rare.

Sachant que si tu dois mettre la locution au pluriel, c'est le premier mot qui prend la marque : « identificateurs de fonction ».

Qu'entends-tu par « un nombre situé exactement entre deux entiers » ?
Parce que, pour ce qui est du C, le passage d'un type flottant vers un type entier se réalise en laissant tomber la partie fractionnaire, c'est tout. Un problème se pose uniquement si la valeur du nombre flottant dépasse la capacité du type entier de destination.

OK, y'a pas de problème, alors. On peut en effet zapper le passage où on enlève 0,5 et donc remonter le cast int à l'initialisation de jourssup.

L'objectif de l'alignement est d'éviter qu'une donnée soit à cheval sur deux ou plusieurs mots (un mot étant une suite de multiplets correspondant à la taille maximale du bus). Or, un short de deux octets tiendra forcément dans un mot de huit octets s'il a une adresse multiple de deux.

OK. Je comprends mieux.

Comment ça « en trop » ? Ce n'est pas symétrique, c'est ça ? :p

Oui, c'est le bordel ! >_< Pis du coup, ça fait plus des millisecondes, tout ça…

Parce qu'il s'agit de mon style par défaut et que j'ai oublié de modifier cela en éditant le chapitre. :-°

C'est du propre… :P

Vu la manière dont est programmée l'IA, il n'est pas possible qu'elle créée des lignes de plus de quatres jetons.

Pas faux.

Y a pas de soucis, le travail que tu as réalisé des déjà énorme.
Un grand merci à toi. ;)

De rien. Fallait bien qu'au moins une personne le lise de fond en comble, un tutoriel sur le C va forcément attirer du monde. :)

+0 -0

D'ailleurs, j'ai une question (peut-être stupide) qui me trotte dans la tête depuis un certain temps. Dans les phrases du genre un identificateur de fonction, une ligne de commande ou encore une structure de donnée, faut-il mettre le dernier mot au pluriel (donc ici fonction, commande et donnée) ?

Je peux pas te donner de réponse générale, parce que ça peut dépendre du contexte, mais globalement, il faut te demander combien le premier mot contient du deuxième mot. Par exemple, en ligne de commande, chaque ligne contient ordinairement une commande (fût-elle complexe), donc « commande » au singulier. Au contraire, une structure contiendra généralement des données, donc « structure de données ». Chaque identificateur identifie une seule fonction, donc « identificateur de fonction ».

De même, on dira « un tas de briques », parce qu'il y a plusieurs briques dans un tas. Parfois le cas est ambigu : on peut dire « mur de briques », si on considère les briques comme objets individuels, ou « mur de brique », si on considère la brique comme matière. Mais c'est assez rare.

Sachant que si tu dois mettre la locution au pluriel, c'est le premier mot qui prend la marque : « identificateurs de fonction ».

Dominus Carnufex

Merci pour cette explication.
J'y vois désormais plus clair sur ce point. :)

+0 -0

Je relaye une petite remarque déjà effectuée sur progdupeu.pl :

Nuki a écrit :

Bonjour, j'ai quelques amis s'étant récemment découvert une perspective dans l'informatique, qui ont vu dans 42 un chemin. Comme j'imagine (epitech-like) qu'ils devront faire du C, j'ai tout de suite eu le réflexe de leur envoyer ce tutoriel que j'avais trouvé riche et bien rédigé.

Beaucoup trouvent que la partie sur les tableaux multi-dimensionnels "complexe & floue", notamment à cause d'une petite coquille :

int tableau[][3] = {{1, 2, 3, 4, 5}, {6, 7, 8}};

Merci pour votre travail et à bientôt :)

Merci.

Salut,

Je te remercie de ton retour, cependant le cours présent sur Pdp n'est pas à jour par rapport à celui présent sur ce site (qui a été grandement modifié). Aussi, l'erreur que tu indiques n'est plus présente dans le cours remanié. ;)

+0 -0

X-Cross-Posting

Juste une petite remarque, est-ce que vous avez moyen de changer l'horrible "Prog du peuple" en "Progdupeupl" dans la petite bannière d'intro. ? L'URL sur le nouveau domaine est par contre bienvenue ! Merci beaucoup et bon courage pour la suite de la rédaction. <3

+0 -0

Juste une petite remarque, est-ce que vous avez moyen de changer l'horrible "Prog du peuple" en "Progdupeupl" dans la petite bannière d'intro. ? L'URL sur le nouveau domaine est par contre bienvenue ! Merci beaucoup et bon courage pour la suite de la rédaction. <3

MicroJoe

C'est noté, je changerai cela dès que le cours sera de nouveau éditable (petit problème suite à une importation). La modification ne sera toutefois visible que lors de la prochaine mise à jour de la beta (ou suite à la validation, c'est selon). ;)

+0 -0

Salut, je pense qu'il serait intéressant de reparler du mot clé const dans le chapitre sur les pointeurs en expliquant à quel élément il s'applique (à ce qui est à gauche à part si const est le plus à gauche auquel cas il s'applique à ce qui est à droite) et d'expliquer la différence entre ces codes :

1
2
3
4
5
6
a = 23;

const int *b = &a /* Un pointeur sur un entier constant */
int const *c = &a /* Pareil que précédemment */
int *const d = &a /* Un pointeur constant sur un entier */
const int *const e = &a /* Un pointeur constant sur un entier constant */

Et il faudrait donc également expliquer que si on déclare une variable constante, il faut déclarer un pointeur sur cette variable en tant que pointeur constant ou sinon on pourra changer la valeur de la variable constante en passant par le pointeur de cette manière :

1
2
3
const int a = 32;
int *p = &a;
*p = 43; /* a vaut maintenant 43 */

Mais peut-être qu'il y a des options de compilation pour empêcher cela (je n'en suis pas sûr). Quelqu'un confirme ?

EDIT : après test, pedantic permet bien d'obtenir un avertissement dans ce cas. Désolé s'il y a des fautes (autant d'orthographe qu'en C).

+1 -0

const et volatile s'applique sur ce qui les précède. S'il n'y a rien avant, on inverse et on recommence.

PS: ce n'est pas un warning mais une erreur de compilation que l'on récolte sur le second exemple de code. Qui plus est, a est une constante (potentiellement en ROM, ou chargé directement en paramètre dans les instructions assembleurs), et pas juste une variable non modifiable.

const et volatile s'applique sur ce qui les précède. S'il n'y a rien avant, on inverse et on recommence.

J'ai compris le début mais quand tu dis on recommence, ça veut dire quoi ?

PS: ce n'est pas un warning mais une erreur de compilation que l'on récolte sur le second exemple de code. Qui plus est, a est une constante (potentiellement en ROM, ou chargé directement en paramètre dans les instructions assembleurs), et pas juste une variable non modifiable.

Avec les bonnes options de compilations on obtient une erreur. Je viens de tester pour être sûr : avec -Wall ou -pedantic, on obtient bien un warning et j'obtiens l'erreur en rajoutant -Werror (ce qui est bien normal). Mais ce que tu dis là m'intéresses, si elle est potentiellement chargée en ROM, on va droit à la catastrophe avec le code que j'ai donné. Alors ça m'interpelle que j'obtiens seulement un warning.

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte