By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
455,127 Members | 1,211 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 455,127 IT Pros & Developers. It's quick & easy.

modified "histogram" exercise from K&R2

P: n/a
this is a programme that counts the "lengths" of each word and then
prints that many of stars(*) on the output . it is a modified form of
K&R2 exercise 1-13. the programme runs without any compile-error BUT
it has a semantic BUG:

what i WANT:

I want it to produce a "horizontal histogram" which tells how many
characters were in the 1st word, how many characters were in the
second word by writing equal number of stars, *, at the output. i
want to
discard ant newlines, extra spaces (more than 1 space between the
words), tabs an newlines.

what i GOT:

it prints histogram BUT it also prints each extra space, tab and
newline as a
"newline in output".

DIFFERENCE: each extra space, tab and newline appears in the output
which must not be there.

---------- PROGRAMME -------

Method:

1.) we will store length of each word in an array.
2.) for keeping simplicity, array size is 1000, i.e.
it can hold only 1000 words.
3.) after EOF is encountered then a horizontal Hostogram
will be printed
*/

#include <stdio.h>

#define IN 1
#define OUT 0
#define MAXWORDS 1000

int main()
{
int c;
int i = 0;
int arr_index = 0;
int j = 0; /* "i,j,count" are general index counters */

int nc = 0; /* length of word or number of characters in a word */

int lwords[MAXWORDS + 1];

int nw = 0; /* number of words */

/* length of each word is stored in this array
and will be printed in the end */

int state = IN;

while( ((c = getchar()) != EOF) && (nw <= MAXWORDS) )
{
++nc;

if(c == ' ' || c == '\t' || c == '\n')
{
state = OUT;
--nc;
}

if(state == OUT)
{
lwords[arr_index++] = nc;
++nw;
state = IN;
nc = 0;
}

}

printf("---------- printing HISTOGRAM -----------\n");

/* printf("arr_index: %d\n", arr_index); */
for(i = 0; i < arr_index; ++i)
{
for(j = 0; j < lwords[i]; ++j)
putchar('*');

putchar('\n');
}

return 0;

}

-------- OUTPUT ----------
[arch@voodo kr2]$ gcc -std=c99 -pedantic -Wall -Wextra ex_1-13.c
[arch@voodo kr2]$ ./a.out
like this
---------- printing HISTOGRAM -----------
****
****
[arch@voodo kr2]$ ./a.out
like this
---------- printing HISTOGRAM -----------
****

****
[arch@voodo kr2]$ ./a.out
like this
---------- printing HISTOGRAM -----------
****

****
[arch@voodo kr2]$ ./a.out
like

---------- printing HISTOGRAM -----------
****

[arch@voodo kr2]$

Mar 22 '07 #1
Share this Question
Share on Google+
5 Replies


P: n/a
arnuld said:
this is a programme that counts the "lengths" of each word and then
prints that many of stars(*) on the output . it is a modified form of
K&R2 exercise 1-13. the programme runs without any compile-error BUT
it has a semantic BUG:
Here's your printing loop, with an extra printf added. It won't solve
your problem for you, but it will help you to understand what's going
on, and /that/ will help you to solve your problem:

for(i = 0; i < arr_index; ++i)
{
printf("i = %d, lwords[i] = %d\n", i, lwords[i]);
for(j = 0; j < lwords[i]; ++j)
putchar('*');

putchar('\n');
}

(Incidentally, your program claims to generate a histogram. It doesn't.
That isn't what a histogram *is*.)

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
Mar 22 '07 #2

P: n/a
On Mar 22, 2:28 pm, Richard Heathfield <r...@see.sig.invalidwrote:
arnuld said:
this is a programme that counts the "lengths" of each word and then
prints that many of stars(*) on the output . it is a modified form of
K&R2 exercise 1-13. the programme runs without any compile-error BUT
it has a semantic BUG:

Here's your printing loop, with an extra printf added. It won't solve
your problem for you, but it will help you to understand what's going
on, and /that/ will help you to solve your problem:

for(i = 0; i < arr_index; ++i)
{
printf("i = %d, lwords[i] = %d\n", i, lwords[i]);
for(j = 0; j < lwords[i]; ++j)
putchar('*');

putchar('\n');
}
this is the output now:

[arch@voodo kr2]$ ./a.out
like and
---------- printing HISTOGRAM -----------
i = 0 lwords[i] = 4
****
i = 1 lwords[i] = 0

i = 2 lwords[i] = 3
***
[arch@voodo kr2]$
so i see, inside while this loop was not working properly:

if(state == OUT)
{
lwords[arr_index++] = nc;
++nw;
state = IN;
nc = 0;
}
only the 1st 2 lines in the loop caused the trouble, so i added a
"check" for spaces:

if(c != ' ' || c != '\t' || c != '\n')
{
lwords[arr_index++] = nc;
++nw;
}

state = IN;
nc = 0;
}
but this also did not work. even thought i have stopped "tabs,
newlines and extra spaces but still i can see them as newlines in
output.

so i thought '\t' || 'n' || ' ' will always get nc == 0, hence tried
this approach:

if(state == OUT)
{
if(nc != 0)
{
lwords[arr_index++] = nc;
++nw;
}

state = IN;
nc = 0;
}
}
and it worked correctly:

[arch@voodo kr2]$ gcc -std=c99 -pedantic -Wall -Wextra ex_1-13.c
[arch@voodo kr2]$ ./a.out
like and
---------- printing HISTOGRAM -----------
i = 0 lwords[i] = 4
****
i = 1 lwords[i] = 3
***
[arch@voodo kr2]$ ./a.out
like

ab ab

a
---------- printing HISTOGRAM -----------
i = 0 lwords[i] = 4
****
i = 1 lwords[i] = 2
**
i = 2 lwords[i] = 2
**
i = 3 lwords[i] = 1
*
[arch@voodo kr2]$
(Incidentally, your program claims to generate a histogram. It doesn't.
That isn't what a histogram *is*.)
OK, a histogram is like a graph with x and y axis, like your solution
at CLC-Wiki for exercise 1-13 but at the present, that is beyond my
level of understanding. i can read it but can not write it, no matter
how may times i read this.

perhaps, as i said in other thread, your solution for that exercise
needs a section like "documentation for newbies". i understood some
part of it after you gave me LONG and CLEAR explanation but i can't
ask every time to write such explanations for me and suck all of your
precious time. it is only and only me who did not understand that
solution. i checked all the archives of comp.lang.c. nobody asked this
solution before. i am the only one and i really *hate* it eating the
family/personal time of people like you.

you solved the trouble. thanks for the "printf" statement. i also
thought of that but i was always putting it inside the "while" loop
and that generated error every time i tried. (i used to use such
"printing to screen" statements in debugging trivial Lisp code i used
to write)
thank you.

Mar 22 '07 #3

P: n/a
On Mar 22, 2:28 pm, Richard Heathfield <r...@see.sig.invalidwrote:
(Incidentally, your program claims to generate a histogram. It doesn't.
That isn't what a histogram *is*.)
OK...

how about this horizontal histogram. got any improvement ?

--------- PROGRAMME ------------
/* K&R2, section 1.6 Arrays, exercise 1-13

STATEMENT:
write a programme to print a histogram of the lengths
of words in ts input.
METHOD to solve the problem:

1.) we will create an array which will hold a number corrsponding to
how many times a that specific length occurs.

2.) for simplicity, we will not consider words with length 10. any
words
having more than 10 characters will be discarded.

3.) First we will attempt a horizontal histogram

*/

#include <stdio.h>

#define MAXWORDLEN 10
#define IN 1
#define OUT 0
int main()
{
int c = EOF;
int i = 0;
int j = 0;
int k = 0;
int arr_of_len[MAXWORDLEN + 1];
int state = IN;
int nc = 0;
for(i = 0; i < MAXWORDLEN; ++i)
arr_of_len[i] = 0;

while((c = getchar()) != EOF)
{
++nc;

if(c == ' ' || c == '\t' || c == '\n')
{
state = OUT;
--nc;
}

if(state == OUT)
{
if(nc != 0 && nc <= MAXWORDLEN)
++arr_of_len[nc];

state = IN;
nc = 0;
}
}

for(i=1, k=1; i <= MAXWORDLEN; ++i, ++k)
{
printf("|%d| ", i);
for(j = 0; j < arr_of_len[k]; ++j)
putchar('*');

putchar('\n');
}
return 0;
}

---------- OUTPUT -------------
[arch@voodo kr2]$ gcc -std=c99 -pedantic -Wall -Wextra ex_1-13-
histogram-horizontal.c
[arch@voodo kr2]$ ./a.out
like this

and this
|1|
|2|
|3| *
|4| ***
|5|
|6|
|7|
|8|
|9|
|10|
[arch@voodo kr2]$
Mar 22 '07 #4

P: n/a
On 22 Mar 2007 05:35:48 -0700, "arnuld" <ge*********@gmail.comwrote:
>On Mar 22, 2:28 pm, Richard Heathfield <r...@see.sig.invalidwrote:
>(Incidentally, your program claims to generate a histogram. It doesn't.
That isn't what a histogram *is*.)

OK...

how about this horizontal histogram. got any improvement ?

--------- PROGRAMME ------------
/* K&R2, section 1.6 Arrays, exercise 1-13

STATEMENT:
write a programme to print a histogram of the lengths
of words in ts input.
METHOD to solve the problem:

1.) we will create an array which will hold a number corrsponding to
how many times a that specific length occurs.

2.) for simplicity, we will not consider words with length 10. any
words
having more than 10 characters will be discarded.

3.) First we will attempt a horizontal histogram

*/

#include <stdio.h>

#define MAXWORDLEN 10
#define IN 1
#define OUT 0
int main()
{
int c = EOF;
int i = 0;
int j = 0;
int k = 0;
int arr_of_len[MAXWORDLEN + 1];
int state = IN;
int nc = 0;
for(i = 0; i < MAXWORDLEN; ++i)
arr_of_len[i] = 0;
You have left the last element of the array indeterminate.
>
while((c = getchar()) != EOF)
{
++nc;

if(c == ' ' || c == '\t' || c == '\n')
{
state = OUT;
--nc;
}

if(state == OUT)
{
if(nc != 0 && nc <= MAXWORDLEN)
++arr_of_len[nc];
If nc == MAXWORDLEN, this will invoke undefined behavior.
>
state = IN;
nc = 0;
}
}

for(i=1, k=1; i <= MAXWORDLEN; ++i, ++k)
Will i and k ever be different? Why use two?
{
printf("|%d| ", i);
If you use %2d, your 1-digit and 2-digit values will line up.
for(j = 0; j < arr_of_len[k]; ++j)
putchar('*');

putchar('\n');
}
return 0;
}

---------- OUTPUT -------------
[arch@voodo kr2]$ gcc -std=c99 -pedantic -Wall -Wextra ex_1-13-
histogram-horizontal.c
[arch@voodo kr2]$ ./a.out
like this

and this
|1|
|2|
|3| *
|4| ***
|5|
|6|
|7|
|8|
|9|
|10|
[arch@voodo kr2]$

Remove del for email
Mar 23 '07 #5

P: n/a
On Mar 23, 5:43 am, Barry Schwarz <schwa...@doezl.netwrote:
On 22 Mar 2007 05:35:48 -0700, "arnuld" <geek.arn...@gmail.comwrote:
for(i = 0; i < MAXWORDLEN; ++i)
arr_of_len[i] = 0;

You have left the last element of the array indeterminate.
thanks, i will use: i <= MAXWORDLEN

if(nc != 0 && nc <= MAXWORDLEN)
++arr_of_len[nc];

If nc == MAXWORDLEN, this will invoke undefined behavior.
after changing the loop-condition above,as advised by you, it
successfully prints the words of 10 characters.

for(i=1, k=1; i <= MAXWORDLEN; ++i, ++k)

Will i and k ever be different? Why use two?
sorry, that "k" was left-over here unintentionally from this
programme's previous version.

{
printf("|%d| ", i);

If you use %2d, your 1-digit and 2-digit values will line up.
that's the best thing i liked :-)

Mar 23 '07 #6

This discussion thread is closed

Replies have been disabled for this discussion.