modified "histogram" exercise from K&R2


A

arnuld

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; ++j)
putchar('*');

putchar('\n');
}

return 0;

}

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

****
[[email protected] kr2]$ ./a.out
like this
---------- printing HISTOGRAM -----------
****

****
[[email protected] kr2]$ ./a.out
like

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

[[email protected] kr2]$
 
Ad

Advertisements

R

Richard Heathfield

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 = %d\n", i, lwords);
for(j = 0; j < lwords; ++j)
putchar('*');

putchar('\n');
}

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

arnuld

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 = %d\n", i, lwords);
for(j = 0; j < lwords; ++j)
putchar('*');

putchar('\n');
}


this is the output now:

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

i = 2 lwords = 3
***
[[email protected] 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:

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

ab ab



a
---------- printing HISTOGRAM -----------
i = 0 lwords = 4
****
i = 1 lwords = 2
**
i = 2 lwords = 2
**
i = 3 lwords = 1
*
[[email protected] 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.
 
A

arnuld

(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 = 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 -------------
[[email protected] kr2]$ gcc -std=c99 -pedantic -Wall -Wextra ex_1-13-
histogram-horizontal.c
[[email protected] kr2]$ ./a.out
like this

and this
|1|
|2|
|3| *
|4| ***
|5|
|6|
|7|
|8|
|9|
|10|
[[email protected] kr2]$
 
B

Barry Schwarz

On Mar 22, 2:28 pm, Richard Heathfield <[email protected]> wrote:
(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 = 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 -------------
[[email protected] kr2]$ gcc -std=c99 -pedantic -Wall -Wextra ex_1-13-
histogram-horizontal.c
[[email protected] kr2]$ ./a.out
like this

and this
|1|
|2|
|3| *
|4| ***
|5|
|6|
|7|
|8|
|9|
|10|
[[email protected] kr2]$


Remove del for email
 
Ad

Advertisements

A

arnuld

for(i = 0; i < MAXWORDLEN; ++i)
arr_of_len = 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.

Will i and k ever be different? Why use two?

sorry, that "k" was left-over here unintentionally from this
programme's previous version.

If you use %2d, your 1-digit and 2-digit values will line up.

that's the best thing i liked :)
 
Ad

Advertisements


Top