question K&R exo 1-17

Le
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éhension.

Le chapitre 1-9 présente les tableaux de caractères et propose pl=
usieurs
exercices sur ce sujet. Le premier (n°1-16) consiste en la révisi=
on du
programme du chapitre (détection 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érieurement.

Le second (1-17) consiste en l'écriture d'un programme qui affiche les
lignes qui sont plus longues que 80 caractères.

Puisqu'il ne s'agit plus de conserver la ligne la plus longue, mais
d'afficher les lignes de plus de 80 caractères, j'ai repris en partie =
le
précédent programme sans la fonction "copier".

(Voir le programme complet en APPENDICE B)

Or, chose étrange, si je fais ceci :

[
tant que TAILLE DE LA LIGNE est supérieure à 1 CARACTÈRE
si TAILLE DE LA LIGNE est supérieure à 80 CARACTÈRES
IMPRIMER "[TAILLE] : LIGNE"
]

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

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

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

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

Tout fonctionne !

En l'état actuel je suis incapable d'en comprendre la raison. Si une =
âme
charitable pouvait m'aider, je lui en serai fort reconnaissant ;)

À bientôt !

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éjà rencontrée */
char ligne[MAXLIGNE]; /* ligne d'entrée courante */
char pluslongue[MAXLIGNE]; /* on sauve ici la ligne la plus longue */

max = 0;

while((l = lireligne(ligne, MAXLIGNE)) > 1)
{
if (l > max)
{
max = l;
copier(pluslongue, ligne);
}
}
if (max > 0) /* il y avait une 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] != '')
{
++i;
}

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

return i;
}


/* lireligne : lit une ligne dans s, retourne sa longueur
s : chaîne
lim : taille max. */

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

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

if (c == '')
{
s[i] = c;
++i;
}

s[i] = '';

return i;
}

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

void copier(char vers[], char de[])
{
int i;

i = 0;
while((vers[i] = de[i]) != '')
{
++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ères */

int main(int argc, char *argv[])
{
int l; /* longueur de la ligne courante */
int mini = MINI; /* longueur minimale du texte pour être affichÃ=
©e */
char ligne[MAXLIGNE];
char pluslongue[MAXLIGNE];

while((l = 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] != '')
{
++i;
}

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

return i;
}

/* lireligne : lit une ligne dans s, retourne sa longueur
s : chaîne
lim : taille max. */

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

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

if (c == '')
{
s[i] = c;
++i;
}

s[i] = '';

return i;
}

void copier(char vers[], char de[])
{
int i;

i = 0;
while((vers[i] = de[i]) != '')
{
++i;
}
}

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

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

iEUEARECAAYFAkvxsNkACgkQqaQ3xfqJSILFEQCVFCOrJWCI/MeHTG2wWs3RRTaP
hgCeMBp+KdSorHILkR8MSYnLCoPOsZs=
z6m
--END PGP SIGNATURE--
--=-=-=--
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
Samuel DEVULDER
Le #22131261
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.
Jean-Baptiste Bourgoin
Le #22136471
--=-=- 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-----
--=-=-=--
Publicité
Poster une réponse
Anonyme