Ça fait longtemps que j'ai plus posté ici, et pour cause j'ai arrété le
C jusqu'à avoir un meilleur bouquin que le dernier que j'avais.
J'ai donc acheté le K&R (The C Programming Language : ANSI C) et je
fais donc les exercices du tutorial pour me remettre d'applomb.
L'exercice que j'avais à faire est donc le suivant :
Exercise 1-13. Write a program to print a histogram of the lengths of
words. It is easy to draw the histogram with the bars horizontal; a
vertical orientation is more challenging.
WLF-VH.c -- is an acronym for Word Lengths Frequencies - Vertical
Histogram. Like the acronym (badly) said, this program
will display a vertical histogram representing the
number of occurences found for each length of word
starting from 1 char to 30 chars.
Usage : Launch the program and put some words in.
You can replace the input by a file, just do :
program < File
Note : - This program is the result of an exercice of the K&R
(1.13, The C Programming Language : Second Edition)
I can't use pointers, functions, structures...
- This program is, unfortunately, limited to 30 chars by
word so the histogram can fit on a lot of terminals.
- The maximum is limited to 50 occurences of each length
because it's troublesome to display the histogram after
that limit.
- The use of int can lead to overflows but that's just a
exercice of the tutorial...
- An array begin at 0, so the last cell of length is :
length[49]. To store a length of 50 chars, we must
do : length[nchar-1];
/* In and Outside a word */
#define IN 1
#define OUT 0
/* The maximum number of chars allowed in a word */
#define SIZE_LIMIT 30
/* The maximal number of occurences for each length */
#define FREQ_LIMIT 50
int main ( void )
{
/* The input storage variable : Store 1 char at time */
int c;
/* The input state : Check whether we are in a word or not */
int state;
/* The number of chars */
long int nchar;
/* A counter */
int i;
/* The highest frequency (number of occurences) */
long int max;
/* Words lengths */
long int lengths[SIZE_LIMIT];
for (i = 0; i < SIZE_LIMIT; i++)
lengths[i] = 0;
max = 0;
nchar = 0;
state = OUT;
c = 0;
/* We read the whole input to store the lengths of words */
while ((c = getchar()) != EOF)
{
/* If we find a char...*/
if (c != ' ' && c != '\n' && c != '\t')
{
/* And we were outside a word, we toggle "state" and
we begin to measure the length of word */
if (state == OUT)
{
state = IN;
++nchar;
}
/* Else we continue to measure */
else
++nchar;
}
/* If we come outside a word, store the length of the word
where we came from and reset 'nchar'. (See Note 4) */
else if (state == IN)
{
state = OUT;
/* Verify the word length */
if (nchar <= SIZE_LIMIT)
++lengths[nchar-1];
else if (nchar > SIZE_LIMIT)
printf("Word too big (more than 50 chars),"
" skipping this one.\n");
else if (nchar < 0)
printf("We got an overflow... word to big, skipping "
"this one.\n");
nchar = 0;
}
}
/* Now get the 'max'imal frequency in lengths[50] */
for (i = 0; i < SIZE_LIMIT; i++)
{
/* Try to detect overflows before affecting max */
if (lengths[i] < 0)
{
printf("An overflow has been detected for the words of %d "
"chars. Re-calibrating the frequency to %d.\n",
i, FREQ_LIMIT);
lengths[i] = 50;
}
if (max < lengths[i])
max = lengths[i];
}
/* Restrict "max" to FREQ_LIMIT */
if (max > FREQ_LIMIT)
{
printf("The real maximum is %ld, but we must restrict the "
"size of the histogram.\n", max);
max = FREQ_LIMIT;
}
else if ( max < 0 )
{
printf("We got an overflow, we will put max to %d...\n",
FREQ_LIMIT);
max = FREQ_LIMIT;
}
/* The last phase. Description :
- max is :
- The current frequency displayed
- The current line number
- At line 48, to display a '|' for words found more than 48
times, we must check if the frequency of this length is superior
or equal to "max".
*/
for (; max > 0; max--)
{
/* Print the current frequency displayed on this line */
printf("%3ld", max);
/* See "The Last phase" */
for (i = 0; i < SIZE_LIMIT; i++)
if (lengths[i] >= max)
printf(" |");
else
printf(" ");
/* One frequency per line */
putchar('\n');
}
/* The foot of the histogram */
printf("f/n");
for (i = 1; i <= SIZE_LIMIT; i++)
printf("%3d", i);
putchar('\n');
return 0;
}
Voilà, si vous avez des suggestions, des remarques constructives :D.
Je rappelle que c'est un exercice du chapitre 1 d'introduction, je suis
donc limité dans les fonctions :).
Cette action est irreversible, confirmez la suppression du commentaire ?
Signaler le commentaire
Veuillez sélectionner un problème
Nudité
Violence
Harcèlement
Fraude
Vente illégale
Discours haineux
Terrorisme
Autre
Tobias Oed
Eddahbi Karim wrote:
Salut,
Ça fait longtemps que j'ai plus posté ici,
Moi non plus!
et pour cause j'ai arrété le C jusqu'à avoir un meilleur bouquin que le dernier que j'avais.
Moi c'est a cause de stroustroup.
J'ai donc acheté le K&R (The C Programming Language : ANSI C) et je fais donc les exercices du tutorial pour me remettre d'applomb.
L'exercice que j'avais à faire est donc le suivant :
Exercise 1-13. Write a program to print a histogram of the lengths of words. It is easy to draw the histogram with the bars horizontal; a vertical orientation is more challenging.
WLF-VH.c -- is an acronym for Word Lengths Frequencies - Vertical Histogram. Like the acronym (badly) said, this program will display a vertical histogram representing the number of occurences found for each length of word starting from 1 char to 30 chars.
Usage : Launch the program and put some words in. You can replace the input by a file, just do : program < File
Note : - This program is the result of an exercice of the K&R (1.13, The C Programming Language : Second Edition) I can't use pointers, functions, structures... - This program is, unfortunately, limited to 30 chars by word so the histogram can fit on a lot of terminals. - The maximum is limited to 50 occurences of each length because it's troublesome to display the histogram after that limit. - The use of int can lead to overflows but that's just a exercice of the tutorial... - An array begin at 0, so the last cell of length is : length[49]. To store a length of 50 chars, we must do : length[nchar-1];
/* In and Outside a word */ #define IN 1 #define OUT 0
/* The maximum number of chars allowed in a word */ #define SIZE_LIMIT 30
/* The maximal number of occurences for each length */ #define FREQ_LIMIT 50
int main ( void ) {
/* The input storage variable : Store 1 char at time */ int c;
/* The input state : Check whether we are in a word or not */ int state;
/* The number of chars */ long int nchar;
/* A counter */ int i;
/* The highest frequency (number of occurences) */ long int max;
/* Words lengths */ long int lengths[SIZE_LIMIT];
Tres mauvais choix du nom de variable. histogram ou n_occurences
for (i = 0; i < SIZE_LIMIT; i++) lengths[i] = 0;
max = 0; nchar = 0; state = OUT; c = 0;
/* We read the whole input to store the lengths of words */ while ((c = getchar()) != EOF) { /* If we find a char...*/ if (c != ' ' && c != 'n' && c != 't') { /* And we were outside a word, we toggle "state" and we begin to measure the length of word */ if (state == OUT) { state = IN; ++nchar; }
/* Else we continue to measure */ else ++nchar;
C'est bien complique. Je remplacerai tout le if avec STATE=IN; ++nchar; [* voir plus bas]
}
/* If we come outside a word, store the length of the word where we came from and reset 'nchar'. (See Note 4) */ else if (state == IN) { state = OUT;
/* Verify the word length */ if (nchar <= SIZE_LIMIT) ++lengths[nchar-1];
[**]
else if (nchar > SIZE_LIMIT) printf("Word too big (more than 50 chars),"
Tu t'embrouille tout seul entre tes 2 limites. SIZE_MAX c'est 30. Utilise un %d pour imprimer cette valeur (c'est tout l'interet de la macro: le nombre magique est a un seul endroit).
" skipping this one.n"); else if (nchar < 0) printf("We got an overflow... word to big, skipping " "this one.n");
Ca arrive quand ca? Quand un mot est plus grand que LONG_MAX? Peu probabale. De plus l'overfolow sur les entier signes n'est pas garanti (il me semble). Meme si c'etait garanti que fait ton code si nchar redevient positif? Pour palier a ca, il vaudrait mieux remplacer le ++n_char; [*] par un if (n_char <= SIZE_LIMIT){ ++n_char; }
nchar = 0; } }
/* Now get the 'max'imal frequency in lengths[50] */ for (i = 0; i < SIZE_LIMIT; i++) {
/* Try to detect overflows before affecting max */ if (lengths[i] < 0) { printf("An overflow has been detected for the words of %d " "chars. Re-calibrating the frequency to %d.n", i, FREQ_LIMIT);
c'est pour detecter le cas ou il y plus de LONG_MAX occurences de mots d'une certaine longueur? meme probleme que plus haut. Refait [**] pour eviter l'overflow des le depart.
lengths[i] = 50; }
if (max < lengths[i]) max = lengths[i]; }
/* Restrict "max" to FREQ_LIMIT */ if (max > FREQ_LIMIT) { printf("The real maximum is %ld, but we must restrict the " "size of the histogram.n", max); max = FREQ_LIMIT; } else if ( max < 0 ) {
condition impossible.
printf("We got an overflow, we will put max to %d...n", FREQ_LIMIT); max = FREQ_LIMIT; }
/* The last phase. Description : - max is : - The current frequency displayed - The current line number - At line 48, to display a '|' for words found more than 48 times, we must check if the frequency of this length is superior or equal to "max". */
comprends rien au commentaire. D'ou il sort le 48?
for (; max > 0; max--) { /* Print the current frequency displayed on this line */ printf("%3ld", max);
/* See "The Last phase" */ for (i = 0; i < SIZE_LIMIT; i++) if (lengths[i] >= max) printf(" |"); else printf(" ");
/* One frequency per line */ putchar('n'); }
/* The foot of the histogram */ printf("f/n");
for (i = 1; i <= SIZE_LIMIT; i++) printf("%3d", i);
putchar('n');
return 0;
}
Voilà, si vous avez des suggestions, des remarques constructives :D.
C'est tres louable d'essayer de gerer les overflow mais s'il y a risque d'overflows il est souvent plus simple de l'eviter au depart plustot que d'essayer de le detecter plus tard.
Je rappelle que c'est un exercice du chapitre 1 d'introduction, je suis donc limité dans les fonctions :).
N'empeche tu pourrait ecrire tes propres fonctions. Comme celle ci pour trouver le max de longeur:
int array_max(int x[],int n){ int i; int max = x[0]; for(i = 0; i < n; i++){ if (x[i] > max){ max = x; } } return max; }
A oui, j'oubliais: Met des accolades.
a+ Tob.
Eddahbi Karim wrote:
Salut,
Ça fait longtemps que j'ai plus posté ici,
Moi non plus!
et pour cause j'ai arrété le
C jusqu'à avoir un meilleur bouquin que le dernier que j'avais.
Moi c'est a cause de stroustroup.
J'ai donc acheté le K&R (The C Programming Language : ANSI C) et je
fais donc les exercices du tutorial pour me remettre d'applomb.
L'exercice que j'avais à faire est donc le suivant :
Exercise 1-13. Write a program to print a histogram of the lengths of
words. It is easy to draw the histogram with the bars horizontal; a
vertical orientation is more challenging.
WLF-VH.c -- is an acronym for Word Lengths Frequencies - Vertical
Histogram. Like the acronym (badly) said, this program
will display a vertical histogram representing the
number of occurences found for each length of word
starting from 1 char to 30 chars.
Usage : Launch the program and put some words in.
You can replace the input by a file, just do :
program < File
Note : - This program is the result of an exercice of the K&R
(1.13, The C Programming Language : Second Edition)
I can't use pointers, functions, structures...
- This program is, unfortunately, limited to 30 chars by
word so the histogram can fit on a lot of terminals.
- The maximum is limited to 50 occurences of each length
because it's troublesome to display the histogram after
that limit.
- The use of int can lead to overflows but that's just a
exercice of the tutorial...
- An array begin at 0, so the last cell of length is :
length[49]. To store a length of 50 chars, we must
do : length[nchar-1];
/* In and Outside a word */
#define IN 1
#define OUT 0
/* The maximum number of chars allowed in a word */
#define SIZE_LIMIT 30
/* The maximal number of occurences for each length */
#define FREQ_LIMIT 50
int main ( void )
{
/* The input storage variable : Store 1 char at time */
int c;
/* The input state : Check whether we are in a word or not */
int state;
/* The number of chars */
long int nchar;
/* A counter */
int i;
/* The highest frequency (number of occurences) */
long int max;
/* Words lengths */
long int lengths[SIZE_LIMIT];
Tres mauvais choix du nom de variable. histogram ou n_occurences
for (i = 0; i < SIZE_LIMIT; i++)
lengths[i] = 0;
max = 0;
nchar = 0;
state = OUT;
c = 0;
/* We read the whole input to store the lengths of words */
while ((c = getchar()) != EOF)
{
/* If we find a char...*/
if (c != ' ' && c != 'n' && c != 't')
{
/* And we were outside a word, we toggle "state" and
we begin to measure the length of word */
if (state == OUT)
{
state = IN;
++nchar;
}
/* Else we continue to measure */
else
++nchar;
C'est bien complique. Je remplacerai tout le if avec
STATE=IN;
++nchar; [* voir plus bas]
}
/* If we come outside a word, store the length of the word
where we came from and reset 'nchar'. (See Note 4) */
else if (state == IN)
{
state = OUT;
/* Verify the word length */
if (nchar <= SIZE_LIMIT)
++lengths[nchar-1];
[**]
else if (nchar > SIZE_LIMIT)
printf("Word too big (more than 50 chars),"
Tu t'embrouille tout seul entre tes 2 limites. SIZE_MAX c'est 30. Utilise un %d pour
imprimer cette valeur (c'est tout l'interet de la macro: le nombre magique est a un
seul endroit).
" skipping this one.n");
else if (nchar < 0)
printf("We got an overflow... word to big, skipping "
"this one.n");
Ca arrive quand ca? Quand un mot est plus grand que LONG_MAX? Peu probabale. De plus
l'overfolow sur les entier signes n'est pas garanti (il me semble). Meme si c'etait
garanti que fait ton code si nchar redevient positif?
Pour palier a ca, il vaudrait mieux remplacer le ++n_char; [*] par un
if (n_char <= SIZE_LIMIT){
++n_char;
}
nchar = 0;
}
}
/* Now get the 'max'imal frequency in lengths[50] */
for (i = 0; i < SIZE_LIMIT; i++)
{
/* Try to detect overflows before affecting max */
if (lengths[i] < 0)
{
printf("An overflow has been detected for the words of %d "
"chars. Re-calibrating the frequency to %d.n",
i, FREQ_LIMIT);
c'est pour detecter le cas ou il y plus de LONG_MAX occurences de mots d'une
certaine longueur? meme probleme que plus haut. Refait [**] pour eviter l'overflow
des le depart.
lengths[i] = 50;
}
if (max < lengths[i])
max = lengths[i];
}
/* Restrict "max" to FREQ_LIMIT */
if (max > FREQ_LIMIT)
{
printf("The real maximum is %ld, but we must restrict the "
"size of the histogram.n", max);
max = FREQ_LIMIT;
}
else if ( max < 0 )
{
condition impossible.
printf("We got an overflow, we will put max to %d...n",
FREQ_LIMIT);
max = FREQ_LIMIT;
}
/* The last phase. Description :
- max is :
- The current frequency displayed
- The current line number
- At line 48, to display a '|' for words found more than 48
times, we must check if the frequency of this length is superior
or equal to "max".
*/
comprends rien au commentaire. D'ou il sort le 48?
for (; max > 0; max--)
{
/* Print the current frequency displayed on this line */
printf("%3ld", max);
/* See "The Last phase" */
for (i = 0; i < SIZE_LIMIT; i++)
if (lengths[i] >= max)
printf(" |");
else
printf(" ");
/* One frequency per line */
putchar('n');
}
/* The foot of the histogram */
printf("f/n");
for (i = 1; i <= SIZE_LIMIT; i++)
printf("%3d", i);
putchar('n');
return 0;
}
Voilà, si vous avez des suggestions, des remarques constructives :D.
C'est tres louable d'essayer de gerer les overflow mais s'il y a risque d'overflows
il est souvent plus simple de l'eviter au depart plustot que d'essayer de le
detecter plus tard.
Je rappelle que c'est un exercice du chapitre 1 d'introduction, je suis
donc limité dans les fonctions :).
N'empeche tu pourrait ecrire tes propres fonctions.
Comme celle ci pour trouver le max de longeur:
int array_max(int x[],int n){
int i;
int max = x[0];
for(i = 0; i < n; i++){
if (x[i] > max){
max = x;
}
}
return max;
}
et pour cause j'ai arrété le C jusqu'à avoir un meilleur bouquin que le dernier que j'avais.
Moi c'est a cause de stroustroup.
J'ai donc acheté le K&R (The C Programming Language : ANSI C) et je fais donc les exercices du tutorial pour me remettre d'applomb.
L'exercice que j'avais à faire est donc le suivant :
Exercise 1-13. Write a program to print a histogram of the lengths of words. It is easy to draw the histogram with the bars horizontal; a vertical orientation is more challenging.
WLF-VH.c -- is an acronym for Word Lengths Frequencies - Vertical Histogram. Like the acronym (badly) said, this program will display a vertical histogram representing the number of occurences found for each length of word starting from 1 char to 30 chars.
Usage : Launch the program and put some words in. You can replace the input by a file, just do : program < File
Note : - This program is the result of an exercice of the K&R (1.13, The C Programming Language : Second Edition) I can't use pointers, functions, structures... - This program is, unfortunately, limited to 30 chars by word so the histogram can fit on a lot of terminals. - The maximum is limited to 50 occurences of each length because it's troublesome to display the histogram after that limit. - The use of int can lead to overflows but that's just a exercice of the tutorial... - An array begin at 0, so the last cell of length is : length[49]. To store a length of 50 chars, we must do : length[nchar-1];
/* In and Outside a word */ #define IN 1 #define OUT 0
/* The maximum number of chars allowed in a word */ #define SIZE_LIMIT 30
/* The maximal number of occurences for each length */ #define FREQ_LIMIT 50
int main ( void ) {
/* The input storage variable : Store 1 char at time */ int c;
/* The input state : Check whether we are in a word or not */ int state;
/* The number of chars */ long int nchar;
/* A counter */ int i;
/* The highest frequency (number of occurences) */ long int max;
/* Words lengths */ long int lengths[SIZE_LIMIT];
Tres mauvais choix du nom de variable. histogram ou n_occurences
for (i = 0; i < SIZE_LIMIT; i++) lengths[i] = 0;
max = 0; nchar = 0; state = OUT; c = 0;
/* We read the whole input to store the lengths of words */ while ((c = getchar()) != EOF) { /* If we find a char...*/ if (c != ' ' && c != 'n' && c != 't') { /* And we were outside a word, we toggle "state" and we begin to measure the length of word */ if (state == OUT) { state = IN; ++nchar; }
/* Else we continue to measure */ else ++nchar;
C'est bien complique. Je remplacerai tout le if avec STATE=IN; ++nchar; [* voir plus bas]
}
/* If we come outside a word, store the length of the word where we came from and reset 'nchar'. (See Note 4) */ else if (state == IN) { state = OUT;
/* Verify the word length */ if (nchar <= SIZE_LIMIT) ++lengths[nchar-1];
[**]
else if (nchar > SIZE_LIMIT) printf("Word too big (more than 50 chars),"
Tu t'embrouille tout seul entre tes 2 limites. SIZE_MAX c'est 30. Utilise un %d pour imprimer cette valeur (c'est tout l'interet de la macro: le nombre magique est a un seul endroit).
" skipping this one.n"); else if (nchar < 0) printf("We got an overflow... word to big, skipping " "this one.n");
Ca arrive quand ca? Quand un mot est plus grand que LONG_MAX? Peu probabale. De plus l'overfolow sur les entier signes n'est pas garanti (il me semble). Meme si c'etait garanti que fait ton code si nchar redevient positif? Pour palier a ca, il vaudrait mieux remplacer le ++n_char; [*] par un if (n_char <= SIZE_LIMIT){ ++n_char; }
nchar = 0; } }
/* Now get the 'max'imal frequency in lengths[50] */ for (i = 0; i < SIZE_LIMIT; i++) {
/* Try to detect overflows before affecting max */ if (lengths[i] < 0) { printf("An overflow has been detected for the words of %d " "chars. Re-calibrating the frequency to %d.n", i, FREQ_LIMIT);
c'est pour detecter le cas ou il y plus de LONG_MAX occurences de mots d'une certaine longueur? meme probleme que plus haut. Refait [**] pour eviter l'overflow des le depart.
lengths[i] = 50; }
if (max < lengths[i]) max = lengths[i]; }
/* Restrict "max" to FREQ_LIMIT */ if (max > FREQ_LIMIT) { printf("The real maximum is %ld, but we must restrict the " "size of the histogram.n", max); max = FREQ_LIMIT; } else if ( max < 0 ) {
condition impossible.
printf("We got an overflow, we will put max to %d...n", FREQ_LIMIT); max = FREQ_LIMIT; }
/* The last phase. Description : - max is : - The current frequency displayed - The current line number - At line 48, to display a '|' for words found more than 48 times, we must check if the frequency of this length is superior or equal to "max". */
comprends rien au commentaire. D'ou il sort le 48?
for (; max > 0; max--) { /* Print the current frequency displayed on this line */ printf("%3ld", max);
/* See "The Last phase" */ for (i = 0; i < SIZE_LIMIT; i++) if (lengths[i] >= max) printf(" |"); else printf(" ");
/* One frequency per line */ putchar('n'); }
/* The foot of the histogram */ printf("f/n");
for (i = 1; i <= SIZE_LIMIT; i++) printf("%3d", i);
putchar('n');
return 0;
}
Voilà, si vous avez des suggestions, des remarques constructives :D.
C'est tres louable d'essayer de gerer les overflow mais s'il y a risque d'overflows il est souvent plus simple de l'eviter au depart plustot que d'essayer de le detecter plus tard.
Je rappelle que c'est un exercice du chapitre 1 d'introduction, je suis donc limité dans les fonctions :).
N'empeche tu pourrait ecrire tes propres fonctions. Comme celle ci pour trouver le max de longeur:
int array_max(int x[],int n){ int i; int max = x[0]; for(i = 0; i < n; i++){ if (x[i] > max){ max = x; } } return max; }
A oui, j'oubliais: Met des accolades.
a+ Tob.
Antoine Leca
[Remarque: je n'ai pas compilé ton programme]
En , Eddahbi Karim va escriure:
/* The number of chars */ long int nchar;
Pourquoi des long ?
/* A counter */ int i;
L'intérêt du commentaire ? Bon, je pinaille.
max = 0;
Déplace cette initialisation juste avant la boucle où elle doit servir (ou mieux, sépare cette fonction en deux...)
/* If we find a char...*/ if (c != ' ' && c != 'n' && c != 't')
isspace()m, ce qui te donnera l'idée d'utiliser ! isalpha()...
if (nchar <= SIZE_LIMIT) ++lengths[nchar-1];
L'intérêt de soustraire 1 ? Chercher à tromper celui qui viendrait après maintenir le programme ?
else if (nchar > SIZE_LIMIT) printf("Word too big (more than 50 chars)," " skipping this one.n");
Et le jour où tu changes la constante, le message d'erreur devient obsolète... Si tu vois ce que je veux dire ;-)
else if (nchar < 0) printf("We got an overflow... word to big, skipping " "this one.n");
Le test est plutôt rigolo (avec nchar long), mais en plus on peut le prendre en défaut, si on fait la boucle et si on revient dans les négatifs...
/* Try to detect overflows before affecting max */ if (lengths[i] < 0)
Je me demande comment cela peut arriver (avec des longs), mais bon, c'est bien de contrôler cela. Même remarque que ci-dessus, le débordement peut exister alors même que le compteur est positif, si « on fait le tour ».
else if ( max < 0 )
Quel cas de figure peut produire cela ?
for (; max > 0; max--)
On est dans la boucle des lignes...
/* Print the current frequency displayed on this line */ printf("%3ld", max);
Ici on imprime l'étiquette de la fréquence actuelle, bien
for (i = 0; i < SIZE_LIMIT; i++)
On boucle (sur la même ligne) sur les fréquences
printf(" |");
... puis on imprime l'histogramme, chaque case sur 3 caractères, bien.
for (i = 1; i <= SIZE_LIMIT; i++) printf("%3d", i);
Maintenant, la boucle des longueurs de mots. Chjaque longueur sur 3 caractères. Mais on a pas laissé au début l'équivalent pour l'étiquette, donc tout est décalé de 1: la première valeur (1) s'affiche sous la colonne des étiquettes, le 2 sous le premier histogramme, etc. et sous le dernier histogramme il n'y a rien.
Remarque que tu si « corriges » en écrivant for (i = 0; i <= SIZE_LIMIT; i++) tu vas avoir un résultat apparement correct, mais c'est pire, parce que tu joues avec le fait que tu stockes la fréquence des mots de longueur L dans length[L-1]: résultat, celui qui essayes de corriger quelque chose est admissible d'office à l'infirmerie pour mal de crâne carabiné...
Faire un for(...0; ...<...) puis un for(...1; ...<=...), c'est vraiment cherché à rendre le programme incompréhensible.
En espérant que cela aide.
Antoine
[Remarque: je n'ai pas compilé ton programme]
En 20040221032141.05c18137.installation_fault_association@yahoo.com,
Eddahbi Karim va escriure:
/* The number of chars */
long int nchar;
Pourquoi des long ?
/* A counter */
int i;
L'intérêt du commentaire ? Bon, je pinaille.
max = 0;
Déplace cette initialisation juste avant la boucle où elle doit servir (ou
mieux, sépare cette fonction en deux...)
/* If we find a char...*/
if (c != ' ' && c != 'n' && c != 't')
isspace()m, ce qui te donnera l'idée d'utiliser ! isalpha()...
if (nchar <= SIZE_LIMIT)
++lengths[nchar-1];
L'intérêt de soustraire 1 ? Chercher à tromper celui qui viendrait après
maintenir le programme ?
else if (nchar > SIZE_LIMIT)
printf("Word too big (more than 50 chars),"
" skipping this one.n");
Et le jour où tu changes la constante, le message d'erreur devient
obsolète... Si tu vois ce que je veux dire ;-)
else if (nchar < 0)
printf("We got an overflow... word to big, skipping "
"this one.n");
Le test est plutôt rigolo (avec nchar long), mais en plus on peut le prendre
en défaut, si on fait la boucle et si on revient dans les négatifs...
/* Try to detect overflows before affecting max */
if (lengths[i] < 0)
Je me demande comment cela peut arriver (avec des longs), mais bon, c'est
bien de contrôler cela. Même remarque que ci-dessus, le débordement peut
exister alors même que le compteur est positif, si « on fait le tour ».
else if ( max < 0 )
Quel cas de figure peut produire cela ?
for (; max > 0; max--)
On est dans la boucle des lignes...
/* Print the current frequency displayed on this line */
printf("%3ld", max);
Ici on imprime l'étiquette de la fréquence actuelle, bien
for (i = 0; i < SIZE_LIMIT; i++)
On boucle (sur la même ligne) sur les fréquences
printf(" |");
... puis on imprime l'histogramme, chaque case sur 3 caractères, bien.
for (i = 1; i <= SIZE_LIMIT; i++)
printf("%3d", i);
Maintenant, la boucle des longueurs de mots. Chjaque longueur sur 3
caractères. Mais on a pas laissé au début l'équivalent pour l'étiquette,
donc tout est décalé de 1: la première valeur (1) s'affiche sous la colonne
des étiquettes, le 2 sous le premier histogramme, etc. et sous le dernier
histogramme il n'y a rien.
Remarque que tu si « corriges » en écrivant
for (i = 0; i <= SIZE_LIMIT; i++)
tu vas avoir un résultat apparement correct, mais c'est pire, parce que tu
joues avec le fait que tu stockes la fréquence des mots de longueur L dans
length[L-1]: résultat, celui qui essayes de corriger quelque chose est
admissible d'office à l'infirmerie pour mal de crâne carabiné...
Faire un for(...0; ...<...) puis un for(...1; ...<=...), c'est vraiment
cherché à rendre le programme incompréhensible.
Déplace cette initialisation juste avant la boucle où elle doit servir (ou mieux, sépare cette fonction en deux...)
/* If we find a char...*/ if (c != ' ' && c != 'n' && c != 't')
isspace()m, ce qui te donnera l'idée d'utiliser ! isalpha()...
if (nchar <= SIZE_LIMIT) ++lengths[nchar-1];
L'intérêt de soustraire 1 ? Chercher à tromper celui qui viendrait après maintenir le programme ?
else if (nchar > SIZE_LIMIT) printf("Word too big (more than 50 chars)," " skipping this one.n");
Et le jour où tu changes la constante, le message d'erreur devient obsolète... Si tu vois ce que je veux dire ;-)
else if (nchar < 0) printf("We got an overflow... word to big, skipping " "this one.n");
Le test est plutôt rigolo (avec nchar long), mais en plus on peut le prendre en défaut, si on fait la boucle et si on revient dans les négatifs...
/* Try to detect overflows before affecting max */ if (lengths[i] < 0)
Je me demande comment cela peut arriver (avec des longs), mais bon, c'est bien de contrôler cela. Même remarque que ci-dessus, le débordement peut exister alors même que le compteur est positif, si « on fait le tour ».
else if ( max < 0 )
Quel cas de figure peut produire cela ?
for (; max > 0; max--)
On est dans la boucle des lignes...
/* Print the current frequency displayed on this line */ printf("%3ld", max);
Ici on imprime l'étiquette de la fréquence actuelle, bien
for (i = 0; i < SIZE_LIMIT; i++)
On boucle (sur la même ligne) sur les fréquences
printf(" |");
... puis on imprime l'histogramme, chaque case sur 3 caractères, bien.
for (i = 1; i <= SIZE_LIMIT; i++) printf("%3d", i);
Maintenant, la boucle des longueurs de mots. Chjaque longueur sur 3 caractères. Mais on a pas laissé au début l'équivalent pour l'étiquette, donc tout est décalé de 1: la première valeur (1) s'affiche sous la colonne des étiquettes, le 2 sous le premier histogramme, etc. et sous le dernier histogramme il n'y a rien.
Remarque que tu si « corriges » en écrivant for (i = 0; i <= SIZE_LIMIT; i++) tu vas avoir un résultat apparement correct, mais c'est pire, parce que tu joues avec le fait que tu stockes la fréquence des mots de longueur L dans length[L-1]: résultat, celui qui essayes de corriger quelque chose est admissible d'office à l'infirmerie pour mal de crâne carabiné...
Faire un for(...0; ...<...) puis un for(...1; ...<=...), c'est vraiment cherché à rendre le programme incompréhensible.
En espérant que cela aide.
Antoine
Eddahbi Karim
On Mon, 23 Feb 2004 15:04:19 +0100 "Antoine Leca" wrote:
Note : Bon, j'ai un problème de gestion avec certains charsets sur mon lecteur de news.
[Remarque: je n'ai pas compil_ ton programme]
/* The number of chars */ long int nchar;
Pourquoi des long ?
Ça permet de limiter les problèmes avec les overflows. Je pourrais utiliser un unsigned, mais on est pas censé l'avoir appris à ce niveau là.
J'essais de faire les problèmes avec les outils qu'on donne.
max = 0;
D_place cette initialisation juste avant la boucle o_ elle doit servir (ou mieux, s_pare cette fonction en deux...)
/* If we find a char...*/ if (c != ' ' && c != 'n' && c != 't')
isspace()m, ce qui te donnera l'id_e d'utiliser ! isalpha()...
T'es pas censé connaitre isspace et isalpha à ce moment là :). C'est bien ctype.h pour ce type de gestion mais je le fais avec les outils que l'on donne ;).
if (nchar <= SIZE_LIMIT) ++lengths[nchar-1];
L'int_r_t de soustraire 1 ? Chercher _ tromper celui qui viendrait apr_s maintenir le programme ?
Si le mot fait 50 caractères et je stocke dans lengths[50], je vais faire un overflow... Le -1 vient du fait que on compte à partir de 0 dans les arrays.
else if (nchar > SIZE_LIMIT) printf("Word too big (more than 50 chars)," " skipping this one.n");
Et le jour o_ tu changes la constante, le message d'erreur devient obsol_te... Si tu vois ce que je veux dire ;-)
Bien vu ! Je corrige...
else if (nchar < 0) printf("We got an overflow... word to big, skipping " "this one.n");
Le test est plut_t rigolo (avec nchar long), mais en plus on peut le prendre en d_faut, si on fait la boucle et si on revient dans les n_gatifs...
Il peut faire un tour complet effectivement, je vais tenter de limiter le nombre à la boucle car je peux pas prévenir d'un tour complet.
/* Try to detect overflows before affecting max */ if (lengths[i] < 0)
Je me demande comment cela peut arriver (avec des longs), mais bon, c'est bien de contr_ler cela. M_me remarque que ci-dessus, le d_bordement peut exister alors m_me que le compteur est positif, si _ on fait le tour _.
Effectivement...
else if ( max < 0 )
Quel cas de figure peut produire cela ?
Aucun, c'est un test que j'avais mis au début et que j'aurais du enlevé...
for (; max > 0; max--)
On est dans la boucle des lignes...
Tu veux que je renomme max en line ?
[snip]
Maintenant, la boucle des longueurs de mots. Chjaque longueur sur 3 caract_res. Mais on a pas laiss_ au d_but l'_quivalent pour l'_tiquette, donc tout est d_cal_ de 1: la premi_re valeur (1) s'affiche sous la colonne des _tiquettes, le 2 sous le premier histogramme, etc. et sous le dernier histogramme il n'y a rien.
Non non non, y'a eu un printf("f/n") Juste au dessus qui fait 3 caractères. J'avoue que ça parait trompeur mais j'ai pas fait exprès de l'appeler 'n' :). C'est pas un printf("fn") ! Donc ça fait :
ETQ | f/n 1
Remarque que tu si _ corriges _ en _crivant for (i = 0; i <= SIZE_LIMIT; i++) tu vas avoir un r_sultat apparement correct, mais c'est pire, parce que tu joues avec le fait que tu stockes la fr_quence des mots de longueur L dans length[L-1]: r_sultat, celui qui essayes de corriger quelque chose est admissible d'office _ l'infirmerie pour mal de cr_ne carabin_...
Pourquoi démarrer à 0 ? On affiche les longueurs affichées auparavant. Or, on stocke pas les mots ayant 0 caractères car un mot de 0 caractères n'est pas un mot :)
Faire un for(...0; ...<...) puis un for(...1; ...<=...), c'est vraiment cherch_ _ rendre le programme incompr_hensible.
On calcule d'abord sur des arrays puis sur un compteur aussi...
En esp_rant que cela aide.
Je vais quand même tenter de revoir la chose :)
Antoine
Karim
-- -- ThE_TemPLaR
On Mon, 23 Feb 2004 15:04:19 +0100
"Antoine Leca" <root@localhost.gov> wrote:
Note : Bon, j'ai un problème de gestion avec certains charsets sur mon
lecteur de news.
[Remarque: je n'ai pas compil_ ton programme]
/* The number of chars */
long int nchar;
Pourquoi des long ?
Ça permet de limiter les problèmes avec les overflows. Je pourrais
utiliser un unsigned, mais on est pas censé l'avoir appris à ce niveau
là.
J'essais de faire les problèmes avec les outils qu'on donne.
max = 0;
D_place cette initialisation juste avant la boucle o_ elle doit servir
(ou mieux, s_pare cette fonction en deux...)
/* If we find a char...*/
if (c != ' ' && c != 'n' && c != 't')
isspace()m, ce qui te donnera l'id_e d'utiliser ! isalpha()...
T'es pas censé connaitre isspace et isalpha à ce moment là :).
C'est bien ctype.h pour ce type de gestion mais je le fais avec les
outils que l'on donne ;).
if (nchar <= SIZE_LIMIT)
++lengths[nchar-1];
L'int_r_t de soustraire 1 ? Chercher _ tromper celui qui viendrait
apr_s maintenir le programme ?
Si le mot fait 50 caractères et je stocke dans lengths[50], je vais
faire un overflow...
Le -1 vient du fait que on compte à partir de 0 dans les arrays.
else if (nchar > SIZE_LIMIT)
printf("Word too big (more than 50 chars),"
" skipping this one.n");
Et le jour o_ tu changes la constante, le message d'erreur devient
obsol_te... Si tu vois ce que je veux dire ;-)
Bien vu !
Je corrige...
else if (nchar < 0)
printf("We got an overflow... word to big, skipping "
"this one.n");
Le test est plut_t rigolo (avec nchar long), mais en plus on peut le
prendre en d_faut, si on fait la boucle et si on revient dans les
n_gatifs...
Il peut faire un tour complet effectivement, je vais tenter de limiter
le nombre à la boucle car je peux pas prévenir d'un tour complet.
/* Try to detect overflows before affecting max */
if (lengths[i] < 0)
Je me demande comment cela peut arriver (avec des longs), mais bon,
c'est bien de contr_ler cela. M_me remarque que ci-dessus, le
d_bordement peut exister alors m_me que le compteur est positif, si _
on fait le tour _.
Effectivement...
else if ( max < 0 )
Quel cas de figure peut produire cela ?
Aucun, c'est un test que j'avais mis au début et que j'aurais du
enlevé...
for (; max > 0; max--)
On est dans la boucle des lignes...
Tu veux que je renomme max en line ?
[snip]
Maintenant, la boucle des longueurs de mots. Chjaque longueur sur 3
caract_res. Mais on a pas laiss_ au d_but l'_quivalent pour
l'_tiquette, donc tout est d_cal_ de 1: la premi_re valeur (1)
s'affiche sous la colonne des _tiquettes, le 2 sous le premier
histogramme, etc. et sous le dernier histogramme il n'y a rien.
Non non non, y'a eu un printf("f/n") Juste au dessus qui fait 3
caractères.
J'avoue que ça parait trompeur mais j'ai pas fait exprès de l'appeler
'n' :).
C'est pas un printf("fn") !
Donc ça fait :
ETQ |
f/n 1
Remarque que tu si _ corriges _ en _crivant
for (i = 0; i <= SIZE_LIMIT; i++)
tu vas avoir un r_sultat apparement correct, mais c'est pire, parce
que tu joues avec le fait que tu stockes la fr_quence des mots de
longueur L dans length[L-1]: r_sultat, celui qui essayes de corriger
quelque chose est admissible d'office _ l'infirmerie pour mal de cr_ne
carabin_...
Pourquoi démarrer à 0 ? On affiche les longueurs affichées auparavant.
Or, on stocke pas les mots ayant 0 caractères car un mot de 0 caractères
n'est pas un mot :)
Faire un for(...0; ...<...) puis un for(...1; ...<=...), c'est
vraiment cherch_ _ rendre le programme incompr_hensible.
On calcule d'abord sur des arrays puis sur un compteur aussi...
On Mon, 23 Feb 2004 15:04:19 +0100 "Antoine Leca" wrote:
Note : Bon, j'ai un problème de gestion avec certains charsets sur mon lecteur de news.
[Remarque: je n'ai pas compil_ ton programme]
/* The number of chars */ long int nchar;
Pourquoi des long ?
Ça permet de limiter les problèmes avec les overflows. Je pourrais utiliser un unsigned, mais on est pas censé l'avoir appris à ce niveau là.
J'essais de faire les problèmes avec les outils qu'on donne.
max = 0;
D_place cette initialisation juste avant la boucle o_ elle doit servir (ou mieux, s_pare cette fonction en deux...)
/* If we find a char...*/ if (c != ' ' && c != 'n' && c != 't')
isspace()m, ce qui te donnera l'id_e d'utiliser ! isalpha()...
T'es pas censé connaitre isspace et isalpha à ce moment là :). C'est bien ctype.h pour ce type de gestion mais je le fais avec les outils que l'on donne ;).
if (nchar <= SIZE_LIMIT) ++lengths[nchar-1];
L'int_r_t de soustraire 1 ? Chercher _ tromper celui qui viendrait apr_s maintenir le programme ?
Si le mot fait 50 caractères et je stocke dans lengths[50], je vais faire un overflow... Le -1 vient du fait que on compte à partir de 0 dans les arrays.
else if (nchar > SIZE_LIMIT) printf("Word too big (more than 50 chars)," " skipping this one.n");
Et le jour o_ tu changes la constante, le message d'erreur devient obsol_te... Si tu vois ce que je veux dire ;-)
Bien vu ! Je corrige...
else if (nchar < 0) printf("We got an overflow... word to big, skipping " "this one.n");
Le test est plut_t rigolo (avec nchar long), mais en plus on peut le prendre en d_faut, si on fait la boucle et si on revient dans les n_gatifs...
Il peut faire un tour complet effectivement, je vais tenter de limiter le nombre à la boucle car je peux pas prévenir d'un tour complet.
/* Try to detect overflows before affecting max */ if (lengths[i] < 0)
Je me demande comment cela peut arriver (avec des longs), mais bon, c'est bien de contr_ler cela. M_me remarque que ci-dessus, le d_bordement peut exister alors m_me que le compteur est positif, si _ on fait le tour _.
Effectivement...
else if ( max < 0 )
Quel cas de figure peut produire cela ?
Aucun, c'est un test que j'avais mis au début et que j'aurais du enlevé...
for (; max > 0; max--)
On est dans la boucle des lignes...
Tu veux que je renomme max en line ?
[snip]
Maintenant, la boucle des longueurs de mots. Chjaque longueur sur 3 caract_res. Mais on a pas laiss_ au d_but l'_quivalent pour l'_tiquette, donc tout est d_cal_ de 1: la premi_re valeur (1) s'affiche sous la colonne des _tiquettes, le 2 sous le premier histogramme, etc. et sous le dernier histogramme il n'y a rien.
Non non non, y'a eu un printf("f/n") Juste au dessus qui fait 3 caractères. J'avoue que ça parait trompeur mais j'ai pas fait exprès de l'appeler 'n' :). C'est pas un printf("fn") ! Donc ça fait :
ETQ | f/n 1
Remarque que tu si _ corriges _ en _crivant for (i = 0; i <= SIZE_LIMIT; i++) tu vas avoir un r_sultat apparement correct, mais c'est pire, parce que tu joues avec le fait que tu stockes la fr_quence des mots de longueur L dans length[L-1]: r_sultat, celui qui essayes de corriger quelque chose est admissible d'office _ l'infirmerie pour mal de cr_ne carabin_...
Pourquoi démarrer à 0 ? On affiche les longueurs affichées auparavant. Or, on stocke pas les mots ayant 0 caractères car un mot de 0 caractères n'est pas un mot :)
Faire un for(...0; ...<...) puis un for(...1; ...<=...), c'est vraiment cherch_ _ rendre le programme incompr_hensible.
On calcule d'abord sur des arrays puis sur un compteur aussi...
WLF-VH.c -- is an acronym for Word Lengths Frequencies - Vertical Histogram. Like the acronym (badly) said, this program will display a vertical histogram representing the number of occurences found for each length of word starting from 1 char to 30 chars.
Usage : Launch the program and put some words in. You can replace the input by a file, just do : program < File
Note : - This program is the result of an exercice of the K&R (1.13, The C Programming Language : Second Edition) I can't use pointers, functions, structures... - This program is, unfortunately, limited to 30 chars by word so the histogram can fit on a lot of terminals. - The maximum is limited to 50 occurences of each length because it's troublesome to display the histogram after that limit. - The use of int can lead to overflows but that's just a exercice of the tutorial...
/* In and Outside a word */ #define IN 1 #define OUT 0
/* The maximum number of chars allowed in a word */ #define SIZE_LIMIT 40
/* The maximal number of occurences for each length */ #define FREQ_LIMIT 50
int main ( void ) {
/* The input storage variable : Store 1 char at time */ int c;
/* The input state : Check whether we are in a word or not */ int state;
/* The number of chars */ long int nchar;
/* A counter */ int i;
/* The highest frequency (number of occurences) */ long int max;
/* Words lengths */ long int lengths[SIZE_LIMIT+1];
for (i = 0; i < (SIZE_LIMIT+1); i++) lengths[i] = 0;
max = 0; nchar = 0; state = OUT; c = 0;
/* We read the whole input to store the lengths of words */ while ((c = getchar()) != EOF) { /* If we find a char...*/ if (c != ' ' && c != 'n' && c != 't') { /* And we were outside a word, we toggle "state" and we begin to measure the length of word */ if (state == OUT) { state = IN; ++nchar;
/* If the word is too big, limit it to the maximum length allowed */ if (nchar > SIZE_LIMIT) nchar = SIZE_LIMIT+1; }
/* Else we continue to measure */ else ++nchar;
/* Word too big : reset it to the maximum allowed */ if (nchar > SIZE_LIMIT) nchar = SIZE_LIMIT+1; }
/* If we come outside a word, store the length of the word where we came from and reset 'nchar'. (See Note 4) */ else if (state == IN) { state = OUT;
/* If a word is too long, warn the user */ if (nchar == SIZE_LIMIT+1) printf("Word out of range... (%d chars)n", SIZE_LIMIT);
++lengths[nchar];
/* If a length has been found too many times, limit it at the maximum of occurences allowed. */ if (lengths[nchar] > FREQ_LIMIT) lengths[nchar] = FREQ_LIMIT;
nchar = 0; } }
/* Now get the 'max'imal frequency in lengths[] */ for (i = 1; i <= SIZE_LIMIT; i++) { if (max < lengths[i]) max = lengths[i]; }
/* The last phase. Description : - max is : - The current frequency displayed - The current line number - At line 48, to display a '|' for words found more than 48 times, we must check if the frequency of this length is superior or equal to "max". */
for (; max > 0; max--) { /* Print the current frequency displayed on this line */ printf("%3ld", max);
/* See "The Last phase" */ for (i = 1; i <= SIZE_LIMIT; i++) if (lengths[i] >= max) printf(" |"); else printf(" ");
/* Prevent a scary display of the histogram */ putchar('n'); }
/* The foot of the histogram */ printf("f/l");
for (i = 1; i <= SIZE_LIMIT; i++) printf("%3d", i);
putchar('n'); printf("f = Frequencies.n" "l = length in chars.n");
WLF-VH.c -- is an acronym for Word Lengths Frequencies - Vertical
Histogram. Like the acronym (badly) said, this program
will display a vertical histogram representing the
number of occurences found for each length of word
starting from 1 char to 30 chars.
Usage : Launch the program and put some words in.
You can replace the input by a file, just do :
program < File
Note : - This program is the result of an exercice of the K&R
(1.13, The C Programming Language : Second Edition)
I can't use pointers, functions, structures...
- This program is, unfortunately, limited to 30 chars by
word so the histogram can fit on a lot of terminals.
- The maximum is limited to 50 occurences of each length
because it's troublesome to display the histogram after
that limit.
- The use of int can lead to overflows but that's just a
exercice of the tutorial...
/* In and Outside a word */
#define IN 1
#define OUT 0
/* The maximum number of chars allowed in a word */
#define SIZE_LIMIT 40
/* The maximal number of occurences for each length */
#define FREQ_LIMIT 50
int main ( void )
{
/* The input storage variable : Store 1 char at time */
int c;
/* The input state : Check whether we are in a word or not */
int state;
/* The number of chars */
long int nchar;
/* A counter */
int i;
/* The highest frequency (number of occurences) */
long int max;
/* Words lengths */
long int lengths[SIZE_LIMIT+1];
for (i = 0; i < (SIZE_LIMIT+1); i++)
lengths[i] = 0;
max = 0;
nchar = 0;
state = OUT;
c = 0;
/* We read the whole input to store the lengths of words */
while ((c = getchar()) != EOF)
{
/* If we find a char...*/
if (c != ' ' && c != 'n' && c != 't')
{
/* And we were outside a word, we toggle "state" and
we begin to measure the length of word */
if (state == OUT)
{
state = IN;
++nchar;
/* If the word is too big, limit it to the
maximum length allowed */
if (nchar > SIZE_LIMIT)
nchar = SIZE_LIMIT+1;
}
/* Else we continue to measure */
else
++nchar;
/* Word too big : reset it to the maximum allowed */
if (nchar > SIZE_LIMIT)
nchar = SIZE_LIMIT+1;
}
/* If we come outside a word, store the length of the word
where we came from and reset 'nchar'. (See Note 4) */
else if (state == IN)
{
state = OUT;
/* If a word is too long, warn the user */
if (nchar == SIZE_LIMIT+1)
printf("Word out of range... (%d chars)n", SIZE_LIMIT);
++lengths[nchar];
/* If a length has been found too many times, limit it
at the maximum of occurences allowed. */
if (lengths[nchar] > FREQ_LIMIT)
lengths[nchar] = FREQ_LIMIT;
nchar = 0;
}
}
/* Now get the 'max'imal frequency in lengths[] */
for (i = 1; i <= SIZE_LIMIT; i++)
{
if (max < lengths[i])
max = lengths[i];
}
/* The last phase. Description :
- max is :
- The current frequency displayed
- The current line number
- At line 48, to display a '|' for words found more than 48
times, we must check if the frequency of this length is superior
or equal to "max".
*/
for (; max > 0; max--)
{
/* Print the current frequency displayed on this line */
printf("%3ld", max);
/* See "The Last phase" */
for (i = 1; i <= SIZE_LIMIT; i++)
if (lengths[i] >= max)
printf(" |");
else
printf(" ");
/* Prevent a scary display of the histogram */
putchar('n');
}
/* The foot of the histogram */
printf("f/l");
for (i = 1; i <= SIZE_LIMIT; i++)
printf("%3d", i);
putchar('n');
printf("f = Frequencies.n"
"l = length in chars.n");
WLF-VH.c -- is an acronym for Word Lengths Frequencies - Vertical Histogram. Like the acronym (badly) said, this program will display a vertical histogram representing the number of occurences found for each length of word starting from 1 char to 30 chars.
Usage : Launch the program and put some words in. You can replace the input by a file, just do : program < File
Note : - This program is the result of an exercice of the K&R (1.13, The C Programming Language : Second Edition) I can't use pointers, functions, structures... - This program is, unfortunately, limited to 30 chars by word so the histogram can fit on a lot of terminals. - The maximum is limited to 50 occurences of each length because it's troublesome to display the histogram after that limit. - The use of int can lead to overflows but that's just a exercice of the tutorial...
/* In and Outside a word */ #define IN 1 #define OUT 0
/* The maximum number of chars allowed in a word */ #define SIZE_LIMIT 40
/* The maximal number of occurences for each length */ #define FREQ_LIMIT 50
int main ( void ) {
/* The input storage variable : Store 1 char at time */ int c;
/* The input state : Check whether we are in a word or not */ int state;
/* The number of chars */ long int nchar;
/* A counter */ int i;
/* The highest frequency (number of occurences) */ long int max;
/* Words lengths */ long int lengths[SIZE_LIMIT+1];
for (i = 0; i < (SIZE_LIMIT+1); i++) lengths[i] = 0;
max = 0; nchar = 0; state = OUT; c = 0;
/* We read the whole input to store the lengths of words */ while ((c = getchar()) != EOF) { /* If we find a char...*/ if (c != ' ' && c != 'n' && c != 't') { /* And we were outside a word, we toggle "state" and we begin to measure the length of word */ if (state == OUT) { state = IN; ++nchar;
/* If the word is too big, limit it to the maximum length allowed */ if (nchar > SIZE_LIMIT) nchar = SIZE_LIMIT+1; }
/* Else we continue to measure */ else ++nchar;
/* Word too big : reset it to the maximum allowed */ if (nchar > SIZE_LIMIT) nchar = SIZE_LIMIT+1; }
/* If we come outside a word, store the length of the word where we came from and reset 'nchar'. (See Note 4) */ else if (state == IN) { state = OUT;
/* If a word is too long, warn the user */ if (nchar == SIZE_LIMIT+1) printf("Word out of range... (%d chars)n", SIZE_LIMIT);
++lengths[nchar];
/* If a length has been found too many times, limit it at the maximum of occurences allowed. */ if (lengths[nchar] > FREQ_LIMIT) lengths[nchar] = FREQ_LIMIT;
nchar = 0; } }
/* Now get the 'max'imal frequency in lengths[] */ for (i = 1; i <= SIZE_LIMIT; i++) { if (max < lengths[i]) max = lengths[i]; }
/* The last phase. Description : - max is : - The current frequency displayed - The current line number - At line 48, to display a '|' for words found more than 48 times, we must check if the frequency of this length is superior or equal to "max". */
for (; max > 0; max--) { /* Print the current frequency displayed on this line */ printf("%3ld", max);
/* See "The Last phase" */ for (i = 1; i <= SIZE_LIMIT; i++) if (lengths[i] >= max) printf(" |"); else printf(" ");
/* Prevent a scary display of the histogram */ putchar('n'); }
/* The foot of the histogram */ printf("f/l");
for (i = 1; i <= SIZE_LIMIT; i++) printf("%3d", i);
putchar('n'); printf("f = Frequencies.n" "l = length in chars.n");
return 0;
}
-- -- ThE_TemPLaR
Eddahbi Karim
Correction :
for (i = 0; i < (SIZE_LIMIT+1); i++) for (i = 0; i =< (SIZE_LIMIT); i++)
-- -- ThE_TemPLaR
Correction :
for (i = 0; i < (SIZE_LIMIT+1); i++)
for (i = 0; i =< (SIZE_LIMIT); i++)
for (i = 0; i < (SIZE_LIMIT+1); i++) for (i = 0; i =< (SIZE_LIMIT); i++)
-- -- ThE_TemPLaR
Tobias Oed
Eddahbi Karim wrote:
Voici une version modifiée :
[snip]
while ((c = getchar()) != EOF) { /* If we find a char...*/ if (c != ' ' && c != 'n' && c != 't') { /* And we were outside a word, we toggle "state" and we begin to measure the length of word */ if (state == OUT) { state = IN; ++nchar;
/* If the word is too big, limit it to the maximum length allowed */ if (nchar > SIZE_LIMIT) nchar = SIZE_LIMIT+1; }
/* Else we continue to measure */ else ++nchar;
/* Word too big : reset it to the maximum allowed */ if (nchar > SIZE_LIMIT) nchar = SIZE_LIMIT+1;
if(state == OUT){ state = IN; }
++n_char;
if(N_CHAR > SIZE_LIMIT){ n_char = SIZE_LIMIT; }
Deja dans la version originale tu a ++n_char dans les 2 brances du if(). Ca complique pour rien. Comme j'ai dit dans ma premiere reponse tu peux te passer du test sur state == OUT et fair le state = IN a tous les passages. Encore plus clair:
if(state == OUT){ state = IN; n_char = 0; }
n_char++;
...
}
/* If we come outside a word, store the length of the word where we came from and reset 'nchar'. (See Note 4) */ else if (state == IN) { state = OUT;
/* If a word is too long, warn the user */ if (nchar == SIZE_LIMIT+1) printf("Word out of range... (%d chars)n", SIZE_LIMIT);
++lengths[nchar];
Boum.
/* If a length has been found too many times, limit it at the maximum of occurences allowed. */ if (lengths[nchar] > FREQ_LIMIT) lengths[nchar] = FREQ_LIMIT;
nchar = 0; } }
/* Now get the 'max'imal frequency in lengths[] */
La je me demende si mon message precedent est bien arrive... a+ Tob
Eddahbi Karim wrote:
Voici une version modifiée :
[snip]
while ((c = getchar()) != EOF)
{
/* If we find a char...*/
if (c != ' ' && c != 'n' && c != 't')
{
/* And we were outside a word, we toggle "state" and
we begin to measure the length of word */
if (state == OUT)
{
state = IN;
++nchar;
/* If the word is too big, limit it to the
maximum length allowed */
if (nchar > SIZE_LIMIT)
nchar = SIZE_LIMIT+1;
}
/* Else we continue to measure */
else
++nchar;
/* Word too big : reset it to the maximum allowed */
if (nchar > SIZE_LIMIT)
nchar = SIZE_LIMIT+1;
if(state == OUT){
state = IN;
}
++n_char;
if(N_CHAR > SIZE_LIMIT){
n_char = SIZE_LIMIT;
}
Deja dans la version originale tu a ++n_char dans les 2 brances du if(). Ca
complique pour rien.
Comme j'ai dit dans ma premiere reponse tu peux te passer du test sur
state == OUT et fair le state = IN a tous les passages.
Encore plus clair:
if(state == OUT){
state = IN;
n_char = 0;
}
n_char++;
...
}
/* If we come outside a word, store the length of the word
where we came from and reset 'nchar'. (See Note 4) */
else if (state == IN)
{
state = OUT;
/* If a word is too long, warn the user */
if (nchar == SIZE_LIMIT+1)
printf("Word out of range... (%d chars)n", SIZE_LIMIT);
++lengths[nchar];
Boum.
/* If a length has been found too many times, limit it
at the maximum of occurences allowed. */
if (lengths[nchar] > FREQ_LIMIT)
lengths[nchar] = FREQ_LIMIT;
nchar = 0;
}
}
/* Now get the 'max'imal frequency in lengths[] */
La je me demende si mon message precedent est bien arrive...
a+ Tob
while ((c = getchar()) != EOF) { /* If we find a char...*/ if (c != ' ' && c != 'n' && c != 't') { /* And we were outside a word, we toggle "state" and we begin to measure the length of word */ if (state == OUT) { state = IN; ++nchar;
/* If the word is too big, limit it to the maximum length allowed */ if (nchar > SIZE_LIMIT) nchar = SIZE_LIMIT+1; }
/* Else we continue to measure */ else ++nchar;
/* Word too big : reset it to the maximum allowed */ if (nchar > SIZE_LIMIT) nchar = SIZE_LIMIT+1;
if(state == OUT){ state = IN; }
++n_char;
if(N_CHAR > SIZE_LIMIT){ n_char = SIZE_LIMIT; }
Deja dans la version originale tu a ++n_char dans les 2 brances du if(). Ca complique pour rien. Comme j'ai dit dans ma premiere reponse tu peux te passer du test sur state == OUT et fair le state = IN a tous les passages. Encore plus clair:
if(state == OUT){ state = IN; n_char = 0; }
n_char++;
...
}
/* If we come outside a word, store the length of the word where we came from and reset 'nchar'. (See Note 4) */ else if (state == IN) { state = OUT;
/* If a word is too long, warn the user */ if (nchar == SIZE_LIMIT+1) printf("Word out of range... (%d chars)n", SIZE_LIMIT);
++lengths[nchar];
Boum.
/* If a length has been found too many times, limit it at the maximum of occurences allowed. */ if (lengths[nchar] > FREQ_LIMIT) lengths[nchar] = FREQ_LIMIT;
nchar = 0; } }
/* Now get the 'max'imal frequency in lengths[] */
La je me demende si mon message precedent est bien arrive... a+ Tob