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

question K&R exo 1-17

2 réponses
Avatar
Jean-Baptiste Bourgoin
--=-=-=
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: quoted-printable

Bonjour,

Je suis actuellement en train d'apprendre le C avec le K&R.

Tout se passe, si ce n'est que je butte sur une incompr=C3=A9hension.

Le chapitre 1-9 pr=C3=A9sente les tableaux de caract=C3=A8res et propose pl=
usieurs
exercices sur ce sujet. Le premier (n=C2=B01-16) consiste en la r=C3=A9visi=
on du
programme du chapitre (d=C3=A9tection de la ligne la plus longue) afin qu'il
affiche la longueur exacte des lignes.

Voir le programme en APPENDICE A.

Ce programme dispose d'une fonction "copier" qui sauvegarde la ligne la
plus plongue afin de pouvoir l'afficher ult=C3=A9rieurement.

Le second (1-17) consiste en l'=C3=A9criture d'un programme qui affiche les
lignes qui sont plus longues que 80 caract=C3=A8res.

Puisqu'il ne s'agit plus de conserver la ligne la plus longue, mais
d'afficher les lignes de plus de 80 caract=C3=A8res, j'ai repris en partie =
le
pr=C3=A9c=C3=A9dent programme sans la fonction "copier".

(Voir le programme complet en APPENDICE B)

Or, chose =C3=A9trange, si je fais ceci :

[
tant que TAILLE DE LA LIGNE est sup=C3=A9rieure =C3=A0 1 CARACT=C3=88RE
si TAILLE DE LA LIGNE est sup=C3=A9rieure =C3=A0 80 CARACT=C3=88RES
IMPRIMER "[TAILLE] : LIGNE"
]

while((l =3D lireligne(ligne, MAXLIGNE)) > 1)
{
if (l > mini)
{
printf("[%d] : %s", tailleligne(pluslongue), pluslongue);
}
}

J'ai le droit =C3=A0 une belle erreur de segmentation !

Mais si j'ajouter la fonction de copie, et copie la ligne dans un autre
tableau :

while((l =3D lireligne(ligne, MAXLIGNE)) > 1)
{
if (l > mini)
{
copier(pluslongue, ligne);
printf("[%d] : %s", tailleligne(pluslongue), pluslongue);
}
}

Tout fonctionne !

En l'=C3=A9tat actuel je suis incapable d'en comprendre la raison. Si une =
=C3=A2me
charitable pouvait m'aider, je lui en serai fort reconnaissant ;)

=C3=80 bient=C3=B4t !

Jean-Baptiste

APPENDICE A :

/* Last modified Time-stamp: <Ye Wenbin 2007-12-30 16:29:58>
* @(#)kr-01-16.c
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXLIGNE 1000 /* longueur max des lignes */

int lireligne(char ligne[], int maxligne);
int tailleligne(char tligne[]);
void copier(char vers[], char de[]);

int main(int argc, char *argv[])
{
int l; /* longueur de la ligne courante */
int max; /* longueur maximale d=C3=A9j=C3=A0 rencontr=C3=A9e */
char ligne[MAXLIGNE]; /* ligne d'entr=C3=A9e courante */
char pluslongue[MAXLIGNE]; /* on sauve ici la ligne la plus longue */

max =3D 0;

while((l =3D lireligne(ligne, MAXLIGNE)) > 1)
{
if (l > max)
{
max =3D l;
copier(pluslongue, ligne);
}
}
if (max > 0) /* il y avait une ligne */
{
printf("[%d] : %s", tailleligne(pluslongue), pluslongue);
}
=20=20
return 0;
}

/* tailleligne : calcule la taille de la ligne */

int tailleligne(char tligne[])
{
int i;

while(tligne[i] !=3D '\0')
{
++i;
}

i =3D i -1; /* afin de ne pas compter le retour chariot */

return i;
}


/* lireligne : lit une ligne dans s, retourne sa longueur
s : cha=C3=AEne
lim : taille max. */

int lireligne(char s[], int lim)
{
int c, i;

for (i=3D 0; i < lim -1 && (c =3D getchar()) !=3D EOF && c !=3D '\n' ; ++=
i)
{
s[i] =3D c;
}

if (c =3D=3D '\n')
{
s[i] =3D c;
++i;
}

s[i] =3D '\0';

return i;
}

/* copier : copie 'de' dans 'vers';
suppose que vers est assez longue */

void copier(char vers[], char de[])
{
int i;
=20=20
i =3D 0;
while((vers[i] =3D de[i]) !=3D '\0')
{
++i;
}
}


APPENDICE B

/* Last modified Time-stamp: <Ye Wenbin 2007-12-30 16:29:58>
* @(#)kr-01-17.c
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXLIGNE 1000
#define MINI 80

int lireligne(char ligne[], int maxligne);
int tailleligne(char tligne[]);
void copier(char vers[], char de[]);

/* affiche toutes les lignes plus longues que 80 caract=C3=A8res */

int main(int argc, char *argv[])
{
int l; /* longueur de la ligne courante */
int mini =3D MINI; /* longueur minimale du texte pour =C3=AAtre affich=C3=
=A9e */
char ligne[MAXLIGNE];
char pluslongue[MAXLIGNE];

while((l =3D lireligne(ligne, MAXLIGNE)) > 1)
{
if (l > mini)
{
copier(pluslongue, ligne);
printf("[%d] : %s", tailleligne(pluslongue), pluslongue);
}
}

return 0;
}

/* tailleligne : calcule la taille de la ligne */

int tailleligne(char tligne[])
{
int i;

while(tligne[i] !=3D '\0')
{
++i;
}

i =3D i -1; /* afin de ne pas compter le retour chariot */

return i;
}

/* lireligne : lit une ligne dans s, retourne sa longueur
s : cha=C3=AEne
lim : taille max. */

int lireligne(char s[], int lim)
{
int c, i;

for (i=3D 0; i < lim -1 && (c =3D getchar()) !=3D EOF && c !=3D '\n' ; ++=
i)
{
s[i] =3D c;
}

if (c =3D=3D '\n')
{
s[i] =3D c;
++i;
}

s[i] =3D '\0';

return i;
}

void copier(char vers[], char de[])
{
int i;
=20=20
i =3D 0;
while((vers[i] =3D de[i]) !=3D '\0')
{
++i;
}
}

--=-=-=
Content-Type: application/pgp-signature

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)

iEUEARECAAYFAkvxsNkACgkQqaQ3xfqJSILFEQCVFCOrJWCI/MeHTG2wWs3RRTaP
hgCeMBp+KdSorHILkR8MSYnLCoPOsZs=
=7A6m
-----END PGP SIGNATURE-----
--=-=-=--

2 réponses

Avatar
Samuel DEVULDER
Jean-Baptiste Bourgoin a écrit :

while((l = lireligne(ligne, MAXLIGNE)) > 1)
{
if (l > mini)
{
printf("[%d] : %s", tailleligne(pluslongue), pluslongue);
}
}

J'ai le droit à une belle erreur de segmentation !



Ben oui, pluslongue n'est pas initialisée!! tailleligne(pluslongue) va
lire bien au delà de la limite du tableau ==> segfault/coredump ou
erreur 0xC0000005 suivant les systèmes (et meme guru méditation,
3bombes, etc pour les nostalgiques),

Il te manque un joli: "pluslongue[0] = '';" avant le while() pour que
ca ne déborde pas quand tu fais le printf().

Cela dit, ca n'est pas non plus bon, car cela signifie que tu n'affiche
pas la ligne qui vient d'être lue, mais un tableau représentant une
chaine vide, et qui n'est jamais mis à jour. Je pense que tu devrais
plutôt faire un printf sur "ligne" au lieu de "pluslongue" pour réussir
cet exercice.

sam.
Avatar
Jean-Baptiste Bourgoin
--=-=- Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: quoted-printable

Samuel DEVULDER writes:

Jean-Baptiste Bourgoin a écrit :

while((l = lireligne(ligne, MAXLIGNE)) > 1)
{
if (l > mini)
{
printf("[%d] : %s", tailleligne(pluslongue), pluslongue);
}
}

J'ai le droit à une belle erreur de segmentation !



Ben oui, pluslongue n'est pas initialisée!! tailleligne(pluslongue) va
lire bien au delà de la limite du tableau ==> segfault/coredump ou
erreur 0xC0000005 suivant les systèmes (et meme guru méditation,
3bombes, etc pour les nostalgiques),



Arf, merci ! La plupart de mes erreurs sont des oublis
d'initialisation. Je ne les vois même pas ! Il me faut perdre mes
habitudes avec Perl et Emacs LISP.

Il te manque un joli: "pluslongue[0] = '';" avant le while() pour
que ca ne déborde pas quand tu fais le printf().

Cela dit, ca n'est pas non plus bon, car cela signifie que tu
n'affiche pas la ligne qui vient d'être lue, mais un tableau
représentant une chaine vide, et qui n'est jamais mis à jour. J e pense
que tu devrais plutôt faire un printf sur "ligne" au lieu de
"pluslongue" pour réussir cet exercice.

sam.



Yes, merci beaucoup :)

--=-=- Content-Type: application/pgp-signature

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)

iEYEARECAAYFAkvzBI0ACgkQqaQ3xfqJSIJ6oACfRSwwxN+O3GsaciUw2R0sIPb3
Y0QAnivBbtNblIn58nIgPLpfxkePUnUx
=S44+
-----END PGP SIGNATURE-----
--=-=-=--