Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > need some help with this histogram of words program........

Reply
Thread Tools

need some help with this histogram of words program........

 
 
Ceriousmall
Guest
Posts: n/a
 
      02-07-2011
I've had a go at it again and this is the result so feel free to
comment.......
I think this should be ok now and i can move on to the next chapter of
the book....

/* copyright 2011 Ceriousmall. . . .

Program prints a histogram of the length of words in its input */

#include <stdio.h>

#define TRUE 1 /* state of mark or mark_scale */
#define FALSE 0 /* state of mark or marker_sale */
#define LIMIT 20 /* horizontal scale & word size limits */
#define VERLIMIT 1000 /* verticle scale limit */

main()
{
int c, nchar;
int i, x, mark_scale;
int mark[LIMIT+1];
long wordlength[LIMIT+1];

nchar = 0;
mark_scale = FALSE;

for (i = 0; i <= LIMIT; ++i) {
wordlength[i] = 0;
mark[i] = FALSE;
}
while ((c=getchar()) != EOF) {
if (c == ' ' || c == '\n' || c == '\t') {
if (nchar > 0 && nchar < LIMIT)
++wordlength[nchar];
else if (nchar >= LIMIT)
++wordlength[LIMIT];
nchar = 0;
}
else
++nchar;
}
for (i = VERLIMIT; i > 0; --i) {
for (x = 1; x <= LIMIT; ++x)
if (wordlength[x] == i)
mark_scale = TRUE;

if (mark_scale != FALSE)
printf("%4d|", i);

for (x = 1; x <= LIMIT; ++x)
if (wordlength[x] == i) {
printf("%3c", '*');
mark[x] = TRUE;
}
else if (mark[x] == FALSE)
printf("%3c", ' ');
else
printf("%3c", '*');
printf("\n");
}
printf(" +---------------------------");
printf("---------------------------------\n");
printf(" ");

for (i = 1; i <= LIMIT; ++i)
printf("%3d", i);

printf("++\n");

return 0;
}

_____________________________________________)_
Ceriously
I'm really beginning to C the code now. . . . .
 
Reply With Quote
 
 
 
 
Ceriousmall
Guest
Posts: n/a
 
      02-07-2011
I made only one change and that's in the way the horizontal scale is
printed.......
thus.....................
printf(" +");
for (i = 1; i <= LIMIT*3; ++i)
printf("-");

printf("\n ");
for (i = 1; i <= LIMIT; ++i)
printf("%3d", i);

printf("++\n");

return 0;
 
Reply With Quote
 
 
 
 
Ceriousmall
Guest
Posts: n/a
 
      02-12-2011
On Feb 11, 4:51*pm, "io_x" <(E-Mail Removed)> wrote:
> "Ceriousmall" <> ha scritto nel messaggionews:(E-Mail Removed)...
> your code i did not understand much but
> your program has a bug for me
> if the input is somethig like
> aaaa\n
> hh^Z
> where <ctrl-z>==^Z is the end of the input
> it not find the 2 letter word hh
>
> *1| * * * * * *
> * +------------------------------------------------------------
> * * *1 *2 *3 *4 *5 *6 *7 *8 *9 10 11 12 13 14 15 16 17 18 19 20++
>
> instead this is my prog output with the same input:
> * +-------------------- -------------------
> *1:
> *2:-
> *3:
> *4:-
> *5:
> *etc
> there are 2 words (for the thefinition of word in text file)
> one of 2 char and one of 4 chars




Ok......... that's very interesting.........I'm forced to revisit that
code................
 
Reply With Quote
 
Ceriousmall
Guest
Posts: n/a
 
      02-13-2011
On Feb 11, 4:51*pm, "io_x" <(E-Mail Removed)> wrote:
> "Ceriousmall" <> ha scritto nel messaggionews:(E-Mail Removed)...
> your code i did not understand much but
> your program has a bug for me
> if the input is somethig like
> aaaa\n
> hh^Z
> where <ctrl-z>==^Z is the end of the input
> it not find the 2 letter word hh
>
> *1| * * * * * *
> * +------------------------------------------------------------
> * * *1 *2 *3 *4 *5 *6 *7 *8 *9 10 11 12 13 14 15 16 17 18 19 20++
>
> instead this is my prog output with the same input:
> * +-------------------- -------------------
> *1:
> *2:-
> *3:
> *4:-
> *5:
> *etc
> there are 2 words (for the thefinition of word in text file)
> one of 2 char and one of 4 char

..
..
..
Ok this is my revisited code, I believe this should solve the bug as
stated above............

/* Program prints a histogram of the length of words in its input */

#include <stdio.h>

#define TRUE 1
#define FALSE 0
#define LIMIT 20 /* horizontal scale & word size limits */
#define VERLIMIT 1000 /* verticle scale limit */

int main(void)
{
int c, i, x;
int nchar, mark_scale, terminate;
int mark[LIMIT+1];
long wordlength[LIMIT+1];

nchar = 0;
mark_scale = FALSE;
terminate = FALSE;

for (i = 0; i <= LIMIT; ++i) {
wordlength[i] = 0;
mark[i] = FALSE;
}
while ((c = getchar()) && terminate == FALSE) {
if (c >= '0' && c <= '9')
printf("digit %d not valid for a word. . .\n", c-'0');
else if (c == ' ' || c == '\n' || c == '\t') {
if (nchar > 0 && nchar < LIMIT)
++wordlength[nchar];
else if (nchar >= LIMIT)
++wordlength[LIMIT];
nchar = 0;
}
else
++nchar;
if (c == EOF)
terminate = TRUE;
}
for (i = VERLIMIT; i >= 1; --i) {
for (x = 1; x <= LIMIT; ++x)
if (wordlength[x] == i)
mark_scale = TRUE;

if (mark_scale != FALSE)
printf("%4d|", i);

for (x = 1; x <= LIMIT; ++x)
if (wordlength[x] == i) {
printf("%3c", '▄');
mark[x] = TRUE;
}
else if (mark[x] == FALSE)
printf("%3c", ' ');
else
printf("%3c", '▄');
printf("\n");
}
printf(" +");
for (i = 1; i <= LIMIT*3; ++i)
printf("-");

printf("\n ");
for (i = 1; i <= LIMIT; ++i)
printf("%3d", i);

printf("++\n");

return 0;
}


_______________________________________________
Ceriously
I'm really beginning to C the code now. . . . .
 
Reply With Quote
 
Ian Collins
Guest
Posts: n/a
 
      02-13-2011
On 02/13/11 07:35 PM, Ceriousmall wrote:
> ..
> Ok this is my revisited code, I believe this should solve the bug as
> stated above............
>
> /* Program prints a histogram of the length of words in its input */
>
> #include<stdio.h>
>
> #define TRUE 1
> #define FALSE 0
> #define LIMIT 20 /* horizontal scale& word size limits */
> #define VERLIMIT 1000 /* verticle scale limit */
>
> int main(void)
> {
> int c, i, x;
> int nchar, mark_scale, terminate;
> int mark[LIMIT+1];
> long wordlength[LIMIT+1];
>
> nchar = 0;
> mark_scale = FALSE;
> terminate = FALSE;


A lot of these are only used within a loop, declaring them at the start
of the loop would make the code easier to read.

> for (i = 0; i<= LIMIT; ++i) {
> wordlength[i] = 0;
> mark[i] = FALSE;
> }
> while ((c = getchar())&& terminate == FALSE) {
> if (c>= '0'&& c<= '9')
> printf("digit %d not valid for a word. . .\n", c-'0');


Why? Try running the program with the source as the input!

> else if (c == ' ' || c == '\n' || c == '\t') {


Why not use isspace(c)?

> if (nchar> 0&& nchar< LIMIT)
> ++wordlength[nchar];
> else if (nchar>= LIMIT)
> ++wordlength[LIMIT];
> nchar = 0;
> }
> else
> ++nchar;
> if (c == EOF)
> terminate = TRUE;


You should test for EOF as early as possible, in the while condition
would be best.

> }
> for (i = VERLIMIT; i>= 1; --i) {


Given a large value for VERLIMIT, this will print a lot of blank lines.
it might be better to track the maximum count in a bucket and use that
here.

--
Ian Collins
 
Reply With Quote
 
Ike Naar
Guest
Posts: n/a
 
      02-13-2011
On 2011-02-13, Ian Collins <(E-Mail Removed)> wrote:
> On 02/13/11 07:35 PM, Ceriousmall wrote:
>> else if (c == ' ' || c == '\n' || c == '\t') {

>
> Why not use isspace(c)?


It's not the same.
isspace() also includes carriage return, form feed and vertical tab.
 
Reply With Quote
 
Ian Collins
Guest
Posts: n/a
 
      02-13-2011
On 02/13/11 10:34 PM, Ike Naar wrote:
> On 2011-02-13, Ian Collins<(E-Mail Removed)> wrote:
>> On 02/13/11 07:35 PM, Ceriousmall wrote:
>>> else if (c == ' ' || c == '\n' || c == '\t') {

>>
>> Why not use isspace(c)?

>
> It's not the same.
> isspace() also includes carriage return, form feed and vertical tab.


All of which separate words.

--
Ian Collins
 
Reply With Quote
 
Ben Bacarisse
Guest
Posts: n/a
 
      02-13-2011
Ian Collins <(E-Mail Removed)> writes:

> On 02/13/11 07:35 PM, Ceriousmall wrote:

<snip>
>> else if (c == ' ' || c == '\n' || c == '\t') {

>
> Why not use isspace(c)?


Ceriousmall seems to be on chapter 1. The isxxx macros are not
introduced until later. Indeed, K&R use c == ' ' || c == '\n' || c ==
'\t' in a word counting example in chapter 1 so it is the obvious choice
at this stage.

<snip>
--
Ben.
 
Reply With Quote
 
Ceriousmall
Guest
Posts: n/a
 
      02-13-2011
On Feb 13, 10:45*am, Ben Bacarisse <(E-Mail Removed)> wrote:
> Ian Collins <(E-Mail Removed)> writes:
> > On 02/13/11 07:35 PM, Ceriousmall wrote:

> <snip>
> >> * * * * * * * *else if (c == ' ' || c == '\n' || c == '\t') {

>
> > Why not use isspace(c)?

>
> Ceriousmall seems to be on chapter 1. *The isxxx macros are not
> introduced until later. *Indeed, K&R use c == ' ' || c == '\n' || c ==
> '\t' in a word counting example in chapter 1 so it is the obvious choice
> at this stage.
>
> <snip>
> --
> Ben.


..
..
..
Thank U Ben indeed.... page 28 Character arrays to be
precise............... this forum is my link too other C programmers
and all the help is greatly appreciated....
 
Reply With Quote
 
Ben Bacarisse
Guest
Posts: n/a
 
      02-13-2011
Ceriousmall <(E-Mail Removed)> writes:

> On Feb 11, 4:51┬*pm, "io_x" <(E-Mail Removed)> wrote:
>> "Ceriousmall" <> ha scritto nel messaggionews:(E-Mail Removed)...
>> your program has a bug for me
>> if the input is somethig like
>> aaaa\n
>> hh^Z
>> where <ctrl-z>==^Z is the end of the input
>> it not find the 2 letter word hh

<snip>
> Ok this is my revisited code, I believe this should solve the bug as
> stated above............


The end result is worse, I think.

<snip>
> while ((c = getchar()) && terminate == FALSE) {
> if (c >= '0' && c <= '9')
> printf("digit %d not valid for a word. . .\n", c-'0');
> else if (c == ' ' || c == '\n' || c == '\t') {
> if (nchar > 0 && nchar < LIMIT)
> ++wordlength[nchar];
> else if (nchar >= LIMIT)
> ++wordlength[LIMIT];
> nchar = 0;
> }
> else
> ++nchar;
> if (c == EOF)
> terminate = TRUE;


First, using an assignment in a larger expression but where the value is
to be ignored is very peculiar. It's likely to confuse people. What is
more, a null byt will terminate the loop which might surprise the user
even more.

Secondly, putting the ch = getchar() test *before* the other half of the
&& means that, on some systems, EOF no longer works. After detecting
EOF you try to read again. It's best to do any more input once you've
seen EOF and you can do that by switching the && order:

terminate == FALSE && (c = getchar())

However you should really put the c = getchar() at the start of the loop
body.

If you do that, you'll see that ch == EOF exactly mirrors the value of
'terminate' so there is no need for that exatr variable. Instead you
could write:

ch = 0; /* anything but EOF */
while (ch != EOF) {
ch = getchar();
/* The rest of your body but without the last 'if' */
}

But, finally, C has a loop for exactly this kind of pattern: do
.... while. So I'd write:

do {
ch = getchar();
/* The rest of your body but without the last 'if' */
} while (ch != EOF) {

The end result is simpler.

Rather then just say┬*"use a do loop" I've tried to show you can be
thinking about your programs be showing you a sequences of small
improvements.

<snip>
--
Ben.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Replace stop words (remove words from a string) BerlinBrown Python 6 01-17-2008 02:37 PM
D80 histogram vs histogram on computer Martin S°rensen Digital Photography 14 12-19-2007 09:41 PM
Words Words utab C++ 6 02-16-2006 07:00 PM
Non-noise words are incorrectly recognised as noise words. Peter Str°iman ASP .Net 1 08-23-2005 01:26 PM
Re: A little bit of help regarding my linked list program required. - "words.c" - "words.c" Richard Heathfield C Programming 7 10-05-2003 02:38 PM



Advertisments