Reputation: 49
So what I'm trying to do is to make a histogram of the frequency of a, b, c, d, and others. I was wondering why when I give the program an input of say abcde
, other
is counted more than one time when e
only occurs once.
The output I'm looking for with input abcde
is
a:x
b:x
c:x
d:x
other:x
The actual K&R exercise is to print a histogram of the different characters that appear in an input. My code appears to be extremely inefficient, so I want to know if am I in the right direction to answering the exercise. Any guidance would be appreciated. The code is below.
#include <stdio.h>
main()
{
int i, c, na, nb, nc, nd, nother;
na = nb = nc = nd = nother = 0;
while( (c = getchar()) != EOF ) {
if(c == 'a')
na++;
if(c == 'b')
nb++;
if(c == 'c')
nc++;
if(c == 'd')
nd++;
else nother++;
}
printf("a:");
for(i == 0; i < na; i++) {
putchar('x');
}
printf("\nb:");
for(i = 0; i < nb; i++) {
putchar('x');
}
printf("\nc:");
for(i = 0; i < nc; i++) {
putchar('x');
}
printf("\nd:");
for(i = 0;i < nc; i++) {
putchar('x');
}
printf("\nother:");
for(i = 0;i < nother; i++){
putchar('x');
}
}
Upvotes: 3
Views: 2729
Reputation: 821
The Answer Book encourages the use of character classification functions provided by the standard library in order to identify printable characters from control characters and whitespaces.
Using them not only put the different types of characters into well-defined groups but also in case of this particular exercise can be used for the detailed representation of the final report.
For example, in the reading loop, isprint
function makes it possible to count the total number of printable characters as
int printable = 0;
while ( (c = getchar()) != EOF )
if ( isprint(c) )
++printable;
and at the same time discourages the programmer from formulating something like
if (c >= ' ' && c <= '~')
In fact, the possibilities are limitless. The following is a modified version of The Answer Book's solution.
#include <stdio.h>
#include <ctype.h>
#define MAXHIST 15 /* max length of histogram */
#define MAXCHAR 128 /* max different characters */
int main()
{
int c,
i,
len, /* length of each bar */
maxvalue, /* maximum value of cc[] */
cc[MAXCHAR], /* char frequency counters */
totalc, /* total chars of input */
whitec, /* whitespaces chars */
digitc, /* numeric chars */
upperc, /* uppercase chars */
lowerc, /* lowercase chars */
punctc; /* punctuation marks */
totalc = whitec = digitc =
upperc = lowerc = punctc = 0;
for (int i = 0; i < MAXCHAR; ++i)
cc[i] = 0;
while ((c = getchar()) != EOF)
if(c >= 0 && c < MAXCHAR) {
++cc[c];
++totalc;
if (isspace(c)) ++whitec;
else if (isdigit(c)) ++digitc;
else if (isalpha(c)) {
if (isupper(c)) ++upperc;
else ++lowerc;
}
else if (ispunct(c)) ++punctc;
}
maxvalue = 0;
for (i = 0; i < MAXCHAR; ++i)
if (cc[i] > maxvalue)
maxvalue = cc[i];
printf("\n%s - %s - %s\n", "ASCII", "CH", "Freq");
printf("~~~~~~~~~~~~~~~~~~~~\n");
for (i = 0; i < MAXCHAR; ++i) {
if (cc[i] == 0)
continue;
if (isprint(i))
printf("%5d - %2c - %5d : ", i, i, cc[i]);
else
printf("%5d - - %5d : ", i, cc[i]);
if (cc[i] > 0) {
if ((len = cc[i] * MAXHIST / maxvalue) <= 0)
len = 1;
} else
len = 0;
while (len > 0) {
putchar('*');
--len;
}
putchar('\n');
}
printf("\n*** Detailed report ***\n");
printf("Total # of chars : %4d\n"
"Total # of whitespaces: %4d\n"
"Total # of numbers : %4d\n"
"Total # of letters : %4d (%4d upper + %4d lower)\n"
"Total # of puncts : %4d",
totalc, whitec, digitc,
upperc + lowerc, upperc, lowerc,
punctc);
}
Sample Input (The OP's first paragraph)
so what I'm trying to do is to make a histogram of the frequency of a,b,c,d and others. I was wondering why when I give the program an input of say "abcde", 'other' is counted more than one time when 'e' only occurs once.
Sample Output
ASCII - CH - Freq
~~~~~~~~~~~~~~~~~~~~
32 - - 43 : ***************
34 - " - 2 : *
39 - ' - 5 : *
44 - , - 4 : *
46 - . - 2 : *
73 - I - 3 : *
97 - a - 12 : ****
98 - b - 2 : *
99 - c - 7 : **
100 - d - 6 : **
101 - e - 18 : ******
102 - f - 4 : *
103 - g - 5 : *
104 - h - 10 : ***
105 - i - 8 : **
107 - k - 1 : *
108 - l - 1 : *
109 - m - 6 : **
110 - n - 14 : ****
111 - o - 18 : ******
112 - p - 2 : *
113 - q - 1 : *
114 - r - 10 : ***
115 - s - 8 : **
116 - t - 13 : ****
117 - u - 4 : *
118 - v - 1 : *
119 - w - 6 : **
121 - y - 5 : *
*** Detailed report ***
Total # of chars : 221
Total # of whitespaces: 43
Total # of numbers : 0
Total # of letters : 165 ( 3 upper + 162 lower)
Total # of puncts : 13
Upvotes: 0
Reputation: 7647
#include <stdio.h>
main() {
int c, i, n, nc;
nc = '~' - ' '; // range of ascii values to count
int ndigit[nc];
for (i = 0; i < nc; ++i)
ndigit[i] = 0;
while ((c = getchar()) != EOF) {
++ndigit[c-' '];
if (c == '\n') {
for (i = 0; i < nc; i++)
if (ndigit[i] != 0) {
printf("%c: ", i + ' ');
for (n = 0; n < ndigit[i]; n++) {
printf("-");
}
printf("\n");
}
for (i = 0; i < nc; ++i)
ndigit[i] = 0;
}
}
}
Sample input:
aa bbb cccc x
Output:
: ---
a: --
b: ---
c: ----
x: -
Upvotes: 0
Reputation: 2087
#include<stdio.h>
main()
{
int charcount[95],c,i=0,max=0;
for(i=0;i<95;++i) /*Setting every array point to zero*/
{
charcount[i]=0;
}
while((c=getchar())!=EOF) /*Frequency of each character*/
{
++charcount[c-32];
}
for(i=0;i<95;++i) /*For character count of the longest word*/
{
if(max<charcount[i])
max=charcount[i];
}
printf("\n");
for(i=max;i>=0;--i) /*Printing the Vertical Histogram*/
{
for(c=0;c<95;++c)
{
if(charcount[c]!=0)
{
if((charcount[c]-i)<0)
{
printf(" ");
}
else if(i==0)printf("==");
else printf(" X");
}
}
printf("\n");
}
for(i=0;i<95;++i) /*Printing the Characters below the Histogram for reference*/
{
if(charcount[i]!=0)
{
if(i==0)printf("sp "); /*We would write "sp" that stands for space*/
else printf("%c ",i+32);
}
}
printf("\n");
}
VERTICAL ALIGNMENT
The OUTPUT looks like this: "This is not Sparta", yelled the soldier. The messenger walked away. :)
X
X
X X
X X
X X
X X
X X X X
X X X X X
X X X X X X X X X X
X X X X X X X X X X X X X X X X X
X X X X X X X X X X X X X X X X X X X X X X X X X
==================================================
sp " ) , . : S T a d e g h i k l m n o p r s t w y
Upvotes: 0
Reputation: 13
First a little code to find out the characters for your system:
#include<stdio.h>
int main()
{
int i;
for(i=0; i < 128; ++i){
printf("%3d ", i);
putchar(i);
printf("\n");
}
}
This will give you the 32 to 127 range. Then this works
#include <stdio.h>
/*Write a program to print a histogram of the frequencies of different characters
in its input.*/
#define FIRST_CHAR 32 //characters start from here
#define LAST_CHAR 127 // and last till here
#define NUM_CHAR (LAST_CHAR - FIRST_CHAR) + 1 // total ~96
main()
{
int i;
int nchars[NUM_CHAR];
for(i = 0; i < NUM_CHAR; ++i)
nchars[i] = 0;
int input;
while( (input=getchar()) != EOF)
if( (input >= FIRST_CHAR) && (input <= LAST_CHAR) )
++nchars[input- FIRST_CHAR]; //input minus first char
//will give pos in index.
int z;
char A = ' '; //a char used
for(z=0; z < NUM_CHAR; ++z){ //for
printf("%2c", A); //printing
++A; //list of letters
int counter = 0; //use a counter to keep track of how many *'s printed
for(i=0; i < nchars[z]; i++){
if(counter < 70){ //keep printing if less that 70
printf("*");
++counter;}
else{
printf(">>>"); //else just print >>> and be done with it
counter = 0;
break;} //breaks the nearest loop or switch
}
printf("\n");}
}
Upvotes: 0
Reputation: 21793
Two problems.
First problem:
if(c== 'a')
na++;
if(c== 'b')
nb++;
if(c== 'c')
nc++;
if(c== 'd')
nd++;
else nother++;
This is not one else-if chain, so it can do multiple different things. For example:
If the character is a, it hits the c == 'a'
if branch and also the 'it's not c == 'd'
' else branch (because a is not equal to 'd', it progresses to the else part and increments nother).
Fix it as follows:
if(c== 'a')
na++;
else if(c== 'b')
nb++;
else if(c== 'c')
nc++;
else if(c== 'd')
nd++;
else nother++;
Second problem:
for(i==0;i<na;i++){
should of course be
for(i=0;i<na;i++){
Upvotes: 5