Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Besoin explication sur la correction d'un exercice du K&R

7 réponses
Avatar
C. Tobini
Bonjour,

Je suis en train de m'initier au C avec le K&R ainsi que la correction
des exercices. J'en suis à un exercice (le 1-20 page 21) où je n'ai pas
de problème avec la structure du code, mais avec le but même de
l'exercice :-)
Malgré l'énoncé, je ne comprends pas très bien où ils veulent en venir,
et à quoi sert réellement la ligne : ne = INCTAB - (pos - 1) % INCTAB
dans le cas où l'on saisit une tabulation.
S'il s'agit de remplacer les tabulations par des espaces, je ne
comprends pas à quoi sert ce calcul.

Merci si vous pouvez m'aider, voici l'énoncé ainsi que la correction du
K&R :

Ecrivez un programme detabuler qui remplace les caractères de tabulation
qu'il reçoit par le nombre d'expaces nécessaires pour atteindre la
prochaine tabulation. Considérez que les tabulations sont positionnées à
intervalle régulier, par exemple toutes les n colonnes.

#include <stdio.h>
#define INCTAB 8

main(){
int c, ne, pos;

ne = 0; /* nombre d'espaces nécessaires*/
pos = 1; /* position des caractères dans le texte */
while ( (c = getchar()) != EOF ) {
if (c == '\t') {
ne = INCTAB - (pos - 1) % INCTAB;
while (ne > 0) {
++pos;
--ne;
}
putchar('\n');
} else if (c == '\n'){
putchar(c);
pos = 1;
} else {
putchar(c);
++pos;
}
}
}

7 réponses

Avatar
Pierre Maurette
Bonjour,

Je suis en train de m'initier au C avec le K&R ainsi que la correction des
exercices. J'en suis à un exercice (le 1-20 page 21) où je n'ai pas de
problème avec la structure du code, mais avec le but même de l'exercice :-)
Malgré l'énoncé, je ne comprends pas très bien où ils veulent en venir, et à
quoi sert réellement la ligne : ne = INCTAB - (pos - 1) % INCTAB dans le cas
où l'on saisit une tabulation.
S'il s'agit de remplacer les tabulations par des espaces, je ne comprends pas
à quoi sert ce calcul.

Merci si vous pouvez m'aider, voici l'énoncé ainsi que la correction du K&R :

Ecrivez un programme detabuler qui remplace les caractères de tabulation
qu'il reçoit par le nombre d'expaces nécessaires pour atteindre la prochaine
tabulation. Considérez que les tabulations sont positionnées à intervalle
régulier, par exemple toutes les n colonnes.

#include <stdio.h>
#define INCTAB 8

main(){
int c, ne, pos;

ne = 0; /* nombre d'espaces nécessaires*/
pos = 1; /* position des caractères dans le texte */
while ( (c = getchar()) != EOF ) {
if (c == 't') {
ne = INCTAB - (pos - 1) % INCTAB;
while (ne > 0) {
++pos;
--ne;
}
putchar('n');
} else if (c == 'n'){
putchar(c);
pos = 1;
} else {
putchar(c);
++pos;
}
}
}


En gros, le modulo calcule la distance depuis la position de tabulation
précédente, et la soustraction donne le nombre de caractères (d'espaces
à ajouter) jusqu'à la suivante. Faites le raisonnement en tabulation
10, c'est à dire que les premiers caractères après le 't' seront en
position 11, 21, 31, etc. (si le premier caractère est en position 1).
Ce que je ne comprends pas, c'est le
putchar('n');
qui suit le bloc while.

--
Pour répondre directement: enlever une lettre sur deux
wwaannaaddoooo -> wanadoo

Pierre Maurette

Avatar
C. Tobini
Bonjour Pierre et merci de votre aide,

Pierre Maurette wrote:
En gros, le modulo calcule la distance depuis la position de tabulation
précédente, et la soustraction donne le nombre de caractères (d'espaces
à ajouter) jusqu'à la suivante. Faites le raisonnement en tabulation 10,
c'est à dire que les premiers caractères après le 't' seront en
position 11, 21, 31, etc. (si le premier caractère est en position 1).


J'avais déjà un problème dans l'ordre de calcul :

INCTAB - (pos - 1) % INCTAB => INCTAB - ( (pos - 1) % INCTAB )

Et j'interprétais ( INCTAB - (pos - 1) ) % INCTAB

Donc en fait on trouve le résidu de la position courante par rapport à
un intervalle de INCTAB et on le soustrait à la prochaine position
correspondant à l'intervalle.

Mon second problème est que je n'avais pas compris ce que l'énoncé
voulait dire par intervalle de tabulation, c'est arbitraire, j'avais
plus vu ça comme ce que fait réellement un shell :-)

Ce que je ne comprends pas, c'est le
putchar('n');
qui suit le bloc while.


J'avais mis sur STDOUT les positions des caractères pour essayer de
comprendre par l'exemple, j'ai oublié d'enlever cette ligne de
'débuggage' :-)

Merci encore.

C. Tobini

Avatar
Pierre Maurette
[...]
J'avais déjà un problème dans l'ordre de calcul :

INCTAB - (pos - 1) % INCTAB => INCTAB - ( (pos - 1) % INCTAB )

Et j'interprétais ( INCTAB - (pos - 1) ) % INCTAB
Personnellement, je parenthèse comme un fou. D'autant qu'il y a des

pièges à cons "historiques". Je crois que c'est le cas des opérateurs
bitwise (pour moi et les autres langages des opérateurs arithmétiques)
qui sont surcotés parce qu'ils servaient au début d'opérateurs
logiques. Donc:
a==b+c est logiquement a == (b + c)
mais:
a==b&c est bizarrement (a == b) & c

Donc en fait on trouve le résidu de la position courante par rapport à un
intervalle de INCTAB et on le soustrait à la prochaine position correspondant
à l'intervalle.

Mon second problème est que je n'avais pas compris ce que l'énoncé voulait
dire par intervalle de tabulation, c'est arbitraire, j'avais plus vu ça comme
ce que fait réellement un shell :-)

Ce que je ne comprends pas, c'est le
putchar('n');
qui suit le bloc while.


J'avais mis sur STDOUT les positions des caractères pour essayer de
comprendre par l'exemple, j'ai oublié d'enlever cette ligne de 'débuggage'
:-)
Assassin ! :-)


--
Pour répondre directement: enlever une lettre sur deux
wwaannaaddoooo -> wanadoo

Pierre Maurette


Avatar
K. Ahausse
"Pierre Maurette" a écrit
dans le message de news:

#include <stdio.h>
#define INCTAB 8

main(){
int c, ne, pos;

ne = 0; /* nombre d'espaces nécessaires*/
pos = 1; /* position des caractères dans le texte */
while ( (c = getchar()) != EOF ) {
if (c == 't') {
ne = INCTAB - (pos - 1) % INCTAB;
while (ne > 0) {
++pos;
--ne;
}
putchar('n');
} else if (c == 'n'){
putchar(c);
pos = 1;
} else {
putchar(c);
++pos;
}
}
}


En gros, le modulo calcule la distance depuis la position de tabulation
précédente, et la soustraction donne le nombre de caractères (d'espaces
à ajouter) jusqu'à la suivante. Faites le raisonnement en tabulation
10, c'est à dire que les premiers caractères après le 't' seront en
position 11, 21, 31, etc. (si le premier caractère est en position 1).
Ce que je ne comprends pas, c'est le
putchar('n');
qui suit le bloc while.


C'est en fait pour remplacer les t saisis par l'utilisateur par des n.

Je pense que le programme d'exemple est plus explicite si l'on rajoute une
ligne :

while (ne > 0) {
++pos;
--ne;



putchar ( '.' ) ;

}



Car la boucle, comme elle est donnée originalement, ne sert à rien !


Avatar
Pierre Maurette
"Pierre Maurette" a écrit
[...]

Ce que je ne comprends pas, c'est le
putchar('n');
qui suit le bloc while.


C'est en fait pour remplacer les t saisis par l'utilisateur par des n.
En fait, c'est un résidu de tentative de débogage ;-) (voir autre

message de l'OP)


Je pense que le programme d'exemple est plus explicite si l'on rajoute une
ligne :

while (ne > 0) {
++pos;
--ne;



putchar ( '.' ) ;

}



Car la boucle, comme elle est donnée originalement, ne sert à rien !
Le bloc est effectivement équivalent à:

pos += INCTAB - ((pos - 1) % INCTAB);
Faudrait voir le programme d'origine. C'est page 21 d'un K&R. Je suis
sûr que vous avez toutes les éditions sur votre table de nuit ;-)

--
Pour répondre directement: enlever une lettre sur deux
wwaannaaddoooo -> wanadoo

Pierre Maurette



Avatar
C. Tobini
Pierre Maurette wrote:
Personnellement, je parenthèse comme un fou.


Je vais prendre le pli aussi !

Assassin ! :-)


C'était pour voir si vous suiviez ;-)

C. Tobini

Avatar
C. Tobini
K. Ahausse wrote:
C'est en fait pour remplacer les t saisis par l'utilisateur par des n.


Oui, mais comme j'ai répondu à Pierre Maurette, je n'avais pas compris
que les tabulations situées à toutes les positions 8 était définies
arbitrairement, pour faire cogiter, du coup je ne comprennais pas la
torture :-)

C. Tobini