446,227 Members | 1,315 Online Need help? Post your question and get tips & solutions from a community of 446,227 IT Pros & Developers. It's quick & easy.

# K&R2, section1.6, exercise 1-13

 P: n/a this programme runs without any error but it does not do what i want it to do: ------------- PROGRAMME -------------- /* K&R2, section 1.6 Arrays; Exercise 1-13. STATEMENT: Write a program to print a histogram of the lengths of words in its input. It is easy to draw the histogram with the bars horizontal; a vertical orientation is more challenging. Method: 1.) we will store lenth of each wordn an array. 2.) for keeping simplicity, array size is 1000, i.e. it can hold only 1000 words. 3.) after EOF is encountered then the "a Hostogram of starts ( * ) "will be printed on the screen. 4.) each line of histogram will contain number of "stars" == length of that word. */ #include #define IN 1 #define OUT 0 #define MAXWORDS 1000 int main() { int c; int i = 0; int aindex = 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; } else if(state == OUT) { lwords[aindex++] = nc; ++nw; state = IN; } } printf("---------- printing HISTOGRAM -----------\n"); for(i = 0; i < aindex; ++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 ---------- printing HISTOGRAM ----------- [arch@voodo kr2]\$ Mar 21 '07 #1
19 Replies

 P: n/a I don't recall if you are supposed to have access to ispunct() and isspace() by that point in the book (K&R2 1.6) or not. Functions isn't until 1.7 but we have been using some of the library functions right from the get-go. But for a word counter, they (the is*() functions and strtok()) seem like natural tools. Also, the evil and cantankerous strtok() can be used. A simple way to start might be to use the previous incarnation of the word-count program on page 20. Mar 21 '07 #2

 P: n/a On Mar 21, 11:42 am, "user923005"

 P: n/a Change the code like this, maybe you can get you want. if(c == ' ' || c == '\t' || c == '\n') { state = OUT; --nc; } if(state == OUT) { lwords[aindex++] = nc; ++nw; state = IN; nc = 0; } Mar 21 '07 #4

 P: n/a On Mar 21, 1:27 pm, "Gawain"

 P: n/a On Mar 21, 1:30 pm, "arnuld"

 P: n/a On Mar 21, 2:24 pm, p_cricket_...@yahoo.co.in wrote: That should work .. Gawain has suggested two changes: 1. "else if" changed to "if" SORRY, i overlooked "if". i thought it was same as my code "else if". 2. assign "nc = 0" under the above condition. i did that with "else if" and it did not work. Did you try with both these changes ? with this code changed to "if" and "nc = 0". it works :-) except of a problem. here is the output: [arch@voodo kr2]\$ ./a.out like---------- printing HISTOGRAM ----------- [arch@voodo kr2]\$ ./a.out like ---------- printing HISTOGRAM ----------- **** [arch@voodo kr2]\$ ./a.out like this about a ---------- printing HISTOGRAM ----------- **** **** ***** * [arch@voodo kr2]\$ it produces extra "newlines" for "tabs" entered. how can i make it consistent ? PS: My apologies if this post does not appear properly. Right now, my google interface is not displaying the cursor as I type :-( i thought i was the only one who is facing this weired problem. i got company now :-) Mar 21 '07 #7

 P: n/a i checked the solution at this page: http://clc-wiki.net/wiki/K%26R2_solu..._1:Exercise_13 it is way-way complicated for me to understand. any help ? Mar 21 '07 #8

 P: n/a arnuld said: i checked the solution at this page: http://clc-wiki.net/wiki/K%26R2_solu..._1:Exercise_13 it is way-way complicated for me to understand. any help ? Which part don't you understand? -- Richard Heathfield "Usenet is a strange place" - dmr 29/7/1999 http://www.cpax.org.uk email: rjh at the above domain, - www. Mar 21 '07 #9

 P: n/a On Mar 21, 6:16 pm, Richard Heathfield

 P: n/a arnuld said: >On Mar 21, 6:16 pm, Richard Heathfield Which part don't you understand? nearly, 90% of the solution. it is weired, something like a "syntax- mess". i will ask in parts: 1.) what exactly these variables are doing: long lengtharr[MAXWORDLEN + 1]; /* i know this is an array */ int firstletter = 1; long thisval = 0; long maxval = 0; int thisidx = 0; int done = 0; 2.) what is this code doing: if(wordlen 0) /* i know what this line is doing */ { thisval = ++lengtharr[wordlen - 1]; Here, we've counted the number of letters in the word. We've already checked that it does not exceed the maximum length we're catering for, so we want to record its length in the array of word length counts. For example, let's say it's five letters long. Then we want to increase (by one) the number of five-letter words we've counted so far. The right place in the array is 'length of word, minus one' (because array indices start at 0, not 1). That explains wordlen - 1. We use that as an index into the array: lengtharr[wordlen - 1]; We want to add 1 to it: ++lengtharr[wordlen - 1]; and we want to know whether this new value has exceeded our currently stored maximum count. Because we'll need to use the expression twice, it's convenient to store it in an object: thisval = ++lengtharr[wordlen - 1]; If it has exceeded the currently stored maximum, then obviously we have a new maximum. (We need this value later, so that we know how to start displaying our data.) The following code accomplishes this: if(thisval maxval) { maxval = thisval; -- Richard Heathfield "Usenet is a strange place" - dmr 29/7/1999 http://www.cpax.org.uk email: rjh at the above domain, - www. Mar 21 '07 #11

 P: n/a On Mar 21, 7:34 pm, Richard Heathfield

 P: n/a arnuld said: >On Mar 21, 7:34 pm, Richard Heathfield Here, we've counted the number of letters in the word. We've alreadychecked that it does not exceed the maximum length we're cateringfor, so we want to record its length in the array of word lengthcounts. this array stores length of all the words and in array, each element corresponds to length of an input word. right ? lengtharr counts all the words of length 1. lengtharr counts all the words of length 2. lengtharr counts all the words of length 3. lengtharr counts all the words of length 4. lengtharr counts all the words of length 5. etc, except that lengtharr[MAXWORDLEN] counts all the words of length *greater* than MAXWORDLEN. So if MAXWORDLEN is 10, as in the example, then an input like this: Once upon a time there was a wonderfully obscure little programming language called C which was so amazingly powerful that it could do six impossible things before breakfast which is quite a stunning achievement for such a tiny language and who knows what it might be able to accomplish if thaumaturgically inclined philosophers were to grant it mystical powers would be processed like this: 'Once' has length 4, so wordlen - 1 is 3, so we increment lengtharr. lengtharr now looks like this: { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 } ^ | lengtharr counts words of length 4 'upon' has length 4, so wordlen - 1 is 3, so we increment lengtharr. lengtharr now looks like this: { 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0 } ^ | lengtharr counts words of length 4 The '2' means "we have met 2 words of length 4" 'a' has length 1, so wordlen - 1 is 0, so we increment lengtharr. lengtharr now looks like this: { 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0 } ^ | lengtharr counts words of length 1 The '1' means "we have met 1 word of length 1" 'time' has length 4, so wordlen - 1 is 3, so we increment lengtharr. lengtharr now looks like this: { 1, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0 } ^ | lengtharr counts words of length 4 The '3' means "we have met 3 words of length 4" Work the rest of the example yourself. >Forexample, let's say it's five letters long. Then we want to increase(by one) the number of five-letter words we've counted so far. why we want to increase the length of an input ? We're not. We're COUNTING the words that have that length. When we encounter another word of that length, we add one to the count, not to the length! -- Richard Heathfield "Usenet is a strange place" - dmr 29/7/1999 http://www.cpax.org.uk email: rjh at the above domain, - www. Mar 21 '07 #13

 P: n/a On 21 Mar, 14:06, "arnuld"

 P: n/a On Mar 21, 7:59 pm, Richard Heathfield

 P: n/a 1. histogram isto be treated as matrix of stars and spaces. 2. where no. of columns is number of words and hieght is the word length of longest word 3. then go on printing either space or star depending on index Mar 21 '07 #16

 P: n/a On 21 Mar 2007 05:57:40 -0700, "arnuld" i checked the solution at this page: http://clc-wiki.net/wiki/K%26R2_solu..._1:Exercise_13 it is way-way complicated for me to understand. How about the following (simple) solution? #include #define IN 1 #define OUT 0 #define MAXLEN 20 /* max. length of a word */ /* Lengths of words (histogram with the bars horizontal) */ int main(void) { int c, i, j, state, len, overflow, h[MAXLEN+1]; for (i = 1; i <= MAXLEN; ++i) /* h is not used */ h[i] = 0; len = 0; overflow = 0; state = OUT; while ((c = getchar()) != EOF) { if (c == ' ' || c == '\n' || c == '\t') { if (state == IN) { state = OUT; if (len <= MAXLEN) /* max. index is MAXLEN */ ++h[len]; else ++overflow; len = 0; } } else { if (state == OUT) state = IN; if (c != '.' && c != '!' && c != '?' && c != ':' && c != ',' && c != ';') len++; } } printf("\n"); for (i = 1; i <= MAXLEN; ++i) { printf("%2d : ", i); for (j = 0; j < h[i]; ++j) printf("*"); printf("\n"); } if (overflow 0) { if (overflow == 1) printf("\n1 word has more than %d characters.\n", MAXLEN); else printf("\n%d words have more than %d characters.\n", overflow, MAXLEN); } return 0; } G. H. -- E-mail: infosimple-linede Mar 21 '07 #17

 P: n/a On 20 Mar 2007 23:26:16 -0700, "arnuld" this programme runs without any error but it does not do what i wantit to do: What did you want? What did you get? What is the difference between the two if it is not immediately obvious? >------------- PROGRAMME --------------/* K&R2, section 1.6 Arrays; Exercise 1-13.STATEMENT:Write a program to print a histogram of the lengths of words in itsinput.It is easy to draw the histogram with the bars horizontal; a verticalorientation is more challenging. Method:1.) we will store lenth of each wordn an array.2.) for keeping simplicity, array size is 1000, i.e. it can hold only 1000 words.3.) after EOF is encountered then the "a Hostogram of starts ( * )"will be printed on the screen.4.) each line of histogram will contain number of "stars" == lengthof that word. It may be a language issue but the usual interpretation of this exercise is produce a histogram that shows how many 1 letter words, how many two letter words, etc were in the input. What you are producing is a histogram that shows the length of first word, length of second word, etc. >*/ snip code Remove del for email Mar 22 '07 #18

 P: n/a On Mar 22, 6:37 am, Barry Schwarz #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]\$ It may be a language issue but the usual interpretation of this exercise is produce a histogram that shows how many 1 letter words, how many two letter words, etc were in the input. that K&R2 did not tell. YES, it was a language issue. i interpreted it differently. What you are producing is a histogram that shows the length of first word, length of second word, etc. that is what exactly i thought that statement of exercise means. thanks for telling what K&R actually meant. Mar 22 '07 #19

 P: n/a On 21 Mar 2007 21:11:22 -0700, "arnuld" On Mar 22, 6:37 am, Barry Schwarz What did you want? What did you get? What is the difference betweenthe two if it is not immediately obvious? what i WANTED:I want it to produce a "horizontal histogram" which tells how manycharacters were in the 1st word, how many characters were in thesecond word by writing equal number of stars at the output. i want todiscard ant newlines, extra spaces (more than 1 space between thewords), tabs an newlines.what i GOT:it prints histogram BUT it also prints each extra space & tab as a"newline in output". You are not handling sequential spaces properly. Follow the comments in numerical order. >DIFFERENCE: each extra space, tab and newline appears in the outputwhich must not be there.---------- PROGRAMME -------/* K&R2, section 1.6 Arrays; Exercise 1-13.STATEMENT:Write a program to print a histogram of the lengths of words in itsinput.It is easy to draw the histogram with the bars horizontal; a verticalorientation is more challenging. Method:1.) we will store lenth 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 the Hostogram will be printed*/#include #define IN 1#define OUT 0#define MAXWORDS 1000int 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; For your second set of input, you appear to have 'l', 'i', 'k', 'e' followed by several spaces. > while( ((c = getchar()) != EOF) && (nw <= MAXWORDS) ) { ++nc; if(c == ' ' || c == '\t' || c == '\n') 1 - When you process the first space after the e... 2 - When you process the second space after the e... > { state = OUT; --nc; 1 - you set nc to 4 ... 2 - you set nc to 0 ... > } if(state == OUT) { lwords[arr_index++] = nc; 1 - and set lwords to 4. 2 - and set lwords to 0. > ++nw; Side issue: are nw and arr_index ever different? > 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) 3 - When i is 0... 4 - When i is 1, j is not less that  so the for loop exits and you print no asterisks ... > putchar('*'); 3 - you output 4 asterisks ... 4 - but you do print a '\n' resulting in a blank line. > putchar('\n'); 3 - followed by a '\n'. } return 0;} -------- OUTPUT ----------[arch@voodo kr2]\$ gcc -std=c99 -pedantic -Wall -Wextra ex_1-13.c[arch@voodo kr2]\$ ./a.outlike this---------- printing HISTOGRAM -----------********[arch@voodo kr2]\$ ./a.outlike this---------- printing HISTOGRAM -----------********[arch@voodo kr2]\$ ./a.outlike this---------- printing HISTOGRAM -----------**** ****[arch@voodo kr2]\$ ./a.outlike ---------- printing HISTOGRAM -----------**** [arch@voodo kr2]\$ >It may be a language issue but the usual interpretation of thisexercise is produce a histogram that shows how many 1 letter words,how many two letter words, etc were in the input. that K&R2 did not tell. YES, it was a language issue. i interpreted itdifferently. > What you areproducing is a histogram that shows the length of first word, lengthof second word, etc. that is what exactly i thought that statement of exercise means.thanks for telling what K&R actually meant. Remove del for email Mar 23 '07 #20

### This discussion thread is closed

Replies have been disabled for this discussion. 