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] != '\0')
{
++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] = '\0';
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]) != '\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è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] != '\0')
{
++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] = '\0';
return i;
}
void copier(char vers[], char de[])
{
int i;
i = 0;
while((vers[i] = de[i]) != '\0')
{
++i;
}
}
--=-=-=
Content-Type: application/pgp-signature
--BEGIN PGP SIGNATURE--
Version: GnuPG v1.4.10 (GNU/Linux)
iEUEARECAAYFAkvxsNkACgkQqaQ3xfqJSILFEQCVFCOrJWCI/MeHTG2wWs3RRTaP
hgCeMBp+KdSorHILkR8MSYnLCoPOsZs=
z6m
--END PGP SIGNATURE--
--=-=-=--
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] != '\0')
{
++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] = '\0';
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]) != '\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è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] != '\0')
{
++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] = '\0';
return i;
}
void copier(char vers[], char de[])
{
int i;
i = 0;
while((vers[i] = de[i]) != '\0')
{
++i;
}
}
--=-=-=
Content-Type: application/pgp-signature
--BEGIN PGP SIGNATURE--
Version: GnuPG v1.4.10 (GNU/Linux)
iEUEARECAAYFAkvxsNkACgkQqaQ3xfqJSILFEQCVFCOrJWCI/MeHTG2wWs3RRTaP
hgCeMBp+KdSorHILkR8MSYnLCoPOsZs=
z6m
--END PGP SIGNATURE--
--=-=-=--

Poser une question


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.
Content-Transfer-Encoding: quoted-printable
Samuel DEVULDER writes:
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.
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-----
--=-=-=--