Histogram of character frequencies

R

rajash

Hello everyone,

Thanks again for all the suggestions, though I think some people are a
bit fussy in their answers.

Here is a solution to Exercise 1.14. It deals well with control
characters too.

// make histogram of character frequencies

int x[256]; // frequencies

void main()
{
char c;
int i, y=0, z;
while(! feof(stdin) )
if(++x[c=getchar()]>y)
y=x[z=c];
do {
for(i=0; i<256; i++)
if(x>0)
printf("%s", x>y ? " * " : " ");
printf("\n");
} while(y--);
for(i=0; i<256; i++)
if(x>0)
if(i>32)
printf(" %c ", i);
else
printf("%02x ", i);
printf("\n");
}
 
J

Johannes Bauer

int x[256]; // frequencies
Global.

void main()

Illegal.

Either you are pretty dumb or you actually do not read ANY of the
answers which are given to you. I vote for number one.

Greetings anyways,
Johannes
 
S

santosh

Hello everyone,

Thanks again for all the suggestions, though I think some people are a
bit fussy in their answers.

Here is a solution to Exercise 1.14. It deals well with control
characters too.

// make histogram of character frequencies

int x[256]; // frequencies

void main()

You have been told multiple times already that the above is most likely
unportable and pretty bad form.
{
char c;
int i, y=0, z;
while(! feof(stdin) )

You have told multiple times that you test for end-of-file or error
*after* an I/O operation has returned EOF or someother error status.
if(++x[c=getchar()]>y)

getchar() is undefined since you have failed to include the relevant
header (stdio.h). Even if you had done so the above call is still wrong
since getchar() returns an int so that it can return the out of band
value EOF upon end-of-file or error. The character with value zero is a
null character, which you do not normally encounter on interactive
input. You should assign the return value of getchar() to an int object
and test it against EOF before proceeding.
y=x[z=c];

You seem to prefer obfuscation and incorrect code.
do {
for(i=0; i<256; i++)
if(x>0)
printf("%s", x>y ? " * " : " ");
printf("\n");
} while(y--);
for(i=0; i<256; i++)
if(x>0)
if(i>32)
printf(" %c ", i);
else
printf("%02x ", i);
printf("\n");
}


As the other respondent notes you either do not bother to take not of
helpful advice or you are a troll. Unless you show some willingness to
learn from your mistakes you are going to find yourself quickly ignored
by most the group's participants.
 
M

Martin Ambuhl

Hello everyone,

Thanks again for all the suggestions, though I think some people are a
bit fussy in their answers.

You need to redefine "fussy". Your code is broken from the very
beginning. Not including header files or otherwise providing required
declarations of variadic functions (printf), and misusing feof() as the
control condition for your loop is bad enough, but the illiterate
void main()

is a sure way to signal your incompetence to anyone reading your code
(and possibly to the compiler as well).

You have been told about these things and refuse to fix them. This
smacks of an obstinacy in error and inability to learn that suggests you
take up Business Administration or some other brainless pursuit instead
of programming.
 
R

rajash

Johannes said:
int x[256]; // frequencies

Global.

It's completely acceptable to have variables defined at file scope in
C!

Why does everyone have this hangup about this? I took a class in C a
while back and my teacher always used void main() { ... }. I can
confirm that it works fine with both MicroSoft compiler and BorLand.
Either you are pretty dumb or you actually do not read ANY of the
answers which are given to you. I vote for number one.

I read the answers but mostly people only comment on trivial things
that aren't even errors! I'll be glad to have substantial comments on
my code.
 
C

Chad

Johannes said:
(e-mail address removed) schrieb:
int x[256]; // frequencies

It's completely acceptable to have variables defined at file scope in
C!



Why does everyone have this hangup about this? I took a class in C a
while back and my teacher always used void main() { ... }. I can
confirm that it works fine with both MicroSoft compiler and BorLand.


Either you are pretty dumb or you actually do not read ANY of the
answers which are given to you. I vote for number one.

I read the answers but mostly people only comment on trivial things
that aren't even errors! I'll be glad to have substantial comments on
my code.


Greetings anyways,
Johannes
Greets.



--
"Viele der Theorien der Mathematiker sind falsch und klar
Gotteslästerlich. Ich vermute, dass diese falschen Theorien genau
deshalb so geliebt werden." -- Prophet und Visionär Hans Joss aka
HJP in de.sci.mathematik <[email protected]>


Your program won't even compile on my machine.

[[email protected] ~]$ more freq.c
int x[256]; // frequencies

void main()
{
char c;
int i, y=0, z;
while(! feof(stdin) )
if(++x[c=getchar()]>y)
y=x[z=c];
do {
for(i=0; i<256; i++)
if(x>0)
printf("%s", x>y ? " * " : " ");
printf("\n");
} while(y--);
for(i=0; i<256; i++)
if(x>0)
if(i>32)
printf(" %c ", i);
else
printf("%02x ", i);
printf("\n");

}
[[email protected] ~]$ gcc --version
gcc (GCC) 4.1.1 20061011 (Red Hat 4.1.1-30)
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There
is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.

[[email protected] ~]$ gcc -g freq.c -o freq
freq.c: In function 'main':
freq.c:7: error: 'stdin' undeclared (first use in this function)
freq.c:7: error: (Each undeclared identifier is reported only once
freq.c:7: error: for each function it appears in.)
freq.c:13: warning: incompatible implicit declaration of built-in
function 'printf'
freq.c:19: warning: incompatible implicit declaration of built-in
function 'printf'
freq.c:4: warning: return type of 'main' is not 'int'
[[email protected] ~]$
 
J

Johannes Bauer

int x[256]; // frequencies
Global.

It's completely acceptable to have variables defined at file scope in
C!

Believe me, I know. But it's very bad style to do so if not absolutely
necessary. Even more so, if you need to use global variables, you should
declare them "static" if they're module-private.

And the comment you used "//" is *not* valid C, it's C++. So this simple
line of code contains lots of mistakes, each and every one should be
avoided in order to create portable code.
Why does everyone have this hangup about this? I took a class in C a
while back and my teacher always used void main() { ... }. I can
confirm that it works fine with both MicroSoft compiler and BorLand.

So what? What does this tell us? Only that your teacher is an idiot. The
reference for C is not your teacher, whoever he or she may be, but the
*official* C standard. And the standard says: it's wrong, period.

Did your drivers ed teacher tell you "It's okay to run stop signs if
nobody's watching!" or "You only need to care about speed limits when
police is around!"? Did your math teacher tell you "Go ahead and divide
by zero, that's alright" or maybe your English teacher "Screw those
apostrophes, they're useless anyways"?

I sure hope that your stupid programming teacher is the only one who
spreads false "knowledge".
I read the answers but mostly people only comment on trivial things
that aren't even errors! I'll be glad to have substantial comments on
my code.

You code contains errors. Why do you post it here? To learn something?
Then accept the hints you're given. You'll be grateful at some point in
time, although you're currently obviously far too stubborn to realize
what you're doing.

If you need somebody to pet you and tells you your code is great, this
is probably the wrong place.

Greetings,
Johannes
 
C

CBFalconer

Why does everyone have this hangup about this? I took a class in C
a while back and my teacher always used void main() { ... }. I can
confirm that it works fine with both MicroSoft compiler and BorLand.

Because they are gross errors, and not allowed in portable code by
the ISO C standard. Which, in turn, is the basis for all code
discussed in this newsgroup. If you want to discuss Microsoft
software (junk), use a Microsoft newsgroup. If you want to discuss
Borland software, use a Borland newsgroup. However, if you want to
discuss C, come here.
 
J

James Kuyper

Johannes said:
int x[256]; // frequencies
Global.

It's completely acceptable to have variables defined at file scope in
C!

What's acceptable is not always a good idea. Global objects have many
disadvantages; they should be avoided except when necessary; they aren't
necessary in this case.
Why does everyone have this hangup about this? I took a class in C a
while back and my teacher always used void main() { ... }. I can
confirm that it works fine with both MicroSoft compiler and BorLand.

That doesn't make it legal. A conforming implementation of C is allowed
to reject a program which declares main() that way.

....
I read the answers but mostly people only comment on trivial things
that aren't even errors! I'll be glad to have substantial comments on
my code.

Several of the "trivial" things people have commented on ARE errors, and
serious ones - you don't seem to understand how serious. Most
importantly, #inclusion of the appropriate standard headers is
absolutely essential for your code to even compile, at least under most
implentations of C. If what you've given us is the complete text of your
program, and if you are using a compiler which accepts your code as
written, junk it - it's teaching you some very bad habits.

Also, you're using feof() incorrectly, and until you understand why the
way that you're using it is incorrect, I would not recommend relying
upon any of your programs to function properly.
 
J

James Kuyper

Johannes Bauer wrote:
....
And the comment you used "//" is *not* valid C, it's C++. So this simple
line of code contains lots of mistakes, each and every one should be
avoided in order to create portable code.

C standard, 6.4.9p2:

"Except within a character constant, a string literal, or a comment, the
characters // introduce a comment that includes all multibyte characters
up to, but not including, the next new-line character. The contents of
such a comment are examined only to identify multibyte characters and to
find the terminating new-line character."
 
C

CBFalconer

Johannes said:
.... snip ...

You code contains errors. Why do you post it here? To learn
something? Then accept the hints you're given. You'll be grateful
at some point in time, although you're currently obviously far
too stubborn to realize what you're doing.

If you need somebody to pet you and tells you your code is great,
this is probably the wrong place.

He could try alt.applause.crud.
 
C

CBFalconer

James said:
Johannes Bauer wrote:
...

C standard, 6.4.9p2:

"Except within a character constant, a string literal, or a comment,
the characters // introduce a comment that includes all multibyte
characters up to, but not including, the next new-line character.
The contents of such a comment are examined only to identify
multibyte characters and to find the terminating new-line character."

That is for C99. C90 doesn't accept it. They are also a grave
mistake on Usenet, because of line wrapping characteristics.
 
T

Tor Rustad

==============================================
----->>> ***READ THE C FAQ*** NOW!!! <<<<-----
......>>> ***READ THE C FAQ*** NOW!!! <<<<.....
......>>> ***READ THE C FAQ*** NOW!!! <<<<.....
----->>> ***READ THE C FAQ*** NOW!!! <<<<-----
==============================================
int x[256]; // frequencies
Global.

It's completely acceptable to have variables defined at file scope in
C!

I once asked a COBOL programmer how to create local variable in that
language, the answer I got was:

"What is a local variable?"

;-)
Why does everyone have this hangup about this? I took a class in C a
while back and my teacher always used void main() { ... }. I can
confirm that it works fine with both MicroSoft compiler and BorLand.

LOL, yet another "void main" fan boy to be eaten in c.l.c!

FYI, you haven't written a valid C program yet, and your teacher hasn't
told you about *Standard C*, which is the topic here.

==============================================
----->>> ***READ THE C FAQ*** NOW!!! <<<<-----
......>>> ***READ THE C FAQ*** NOW!!! <<<<.....
......>>> ***READ THE C FAQ*** NOW!!! <<<<.....
----->>> ***READ THE C FAQ*** NOW!!! <<<<-----
==============================================
 
S

santosh

Johannes said:
int x[256]; // frequencies

Global.

It's completely acceptable to have variables defined at file scope in
C!

Yes, but in most cases it is not good programming practise.
Indiscriminate use of file and program scope objects were among many of
the reasons a lot of programmers abandoned C in favour of "OO"
languages, which discourage such features even more.

You won't feel the need to encapsulate data for small or even midsize
programs, but believe me, if ever you do go on to work on large
systems, your cavalier programming methodology will be instantly
rejected.
Why does everyone have this hangup about this? I took a class in C a
while back and my teacher always used void main() { ... }. I can
confirm that it works fine with both MicroSoft compiler and BorLand.

Unfortunately most C programming classes in India are "tool centric",
i.e., they pick an implementation like Turbo C or MSVC and teach
a "dialect" of C that they (the instructors) figured out from their own
half-baked education and their perusal of the documentation for these
compilers. And the documentation usually encourages extensions and
usually fails to provide sufficient warnings about non-standard
constructs.

In the "Real World" C has an internationally accepted Standard, name
ISO/IEC 9899:1999, the latest working draft of which can be downloaded
here:

<http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf>

The actual Standard is available for a cost from ISO and other national
Standards bodies like BIS:

The Standard is the only contract you can trust between you the
programmer and _any_ implementation that claims conformance to it.
Extensions are almost always a much weaker contract between you and a
specific implementation. They need not be supported by any other
conforming implementation (thus linking your code to a particular
compiler) and even the the implementation that does support it today
could drop support tommorrow.

And void main() is not defined as portable by the Standard.
I read the answers but mostly people only comment on trivial things
that aren't even errors! I'll be glad to have substantial comments on
my code.

Your failure to include the relevent headers and your incorrect use of
the feof() functions _are_ real errors. They may happen to work in a
particular run, but nothing whatsoever can be guaranteed about such
broken code.

<snip>
 
J

James Kuyper

CBFalconer said:
That is for C99. C90 doesn't accept it. They are also a grave
mistake on Usenet, because of line wrapping characteristics.

Since it is supported by the current version of the standard, Johannes
was wrong to claim that it "is *not* valid C".

I'm don't care about the fact that C90 doesn't accept it. And I only
consider them "a grave mistake on usenet", if they occur on a line long
enough for line wrapping to be a problem. That wasn't true in this case.
It will have to indented many times before it wraps.
 
R

rajash

James said:
Johannes said:
(e-mail address removed) schrieb:

int x[256]; // frequencies
Global.

It's completely acceptable to have variables defined at file scope in
C!

What's acceptable is not always a good idea. Global objects have many
disadvantages; they should be avoided except when necessary; they aren't
necessary in this case.

In this case they help simplify the code - the array gets initialized
to 0 at compile-time, instead of needing extra code for an
initialization loop bad for efficiency!
That doesn't make it legal. A conforming implementation of C is allowed
to reject a program which declares main() that way.

But no "conforming implementation" on Windows rejects it! I don't
believe any C compiler anywhere would reject it.
...

Several of the "trivial" things people have commented on ARE errors, and
serious ones - you don't seem to understand how serious. Most
importantly, #inclusion of the appropriate standard headers is
absolutely essential for your code to even compile, at least under most
implentations of C. If what you've given us is the complete text of your
program, and if you are using a compiler which accepts your code as
written, junk it - it's teaching you some very bad habits.

OK you're right I should remember that. However I don't think it's the
end of the world - the standard library is always linked in so the
right functions will be found in the end by the linker.
Also, you're using feof() incorrectly, and until you understand why the
way that you're using it is incorrect, I would not recommend relying
upon any of your programs to function properly.

I don't really understand the problem with feof - it just checks if
the EOF indicator is set in a given FILE * struct. Anyway I'll read
about it.
 
S

santosh

James said:
Johannes Bauer wrote:
(e-mail address removed) schrieb:

int x[256]; // frequencies
Global.

It's completely acceptable to have variables defined at file scope
in C!

What's acceptable is not always a good idea. Global objects have many
disadvantages; they should be avoided except when necessary; they
aren't necessary in this case.

In this case they help simplify the code - the array gets initialized
to 0 at compile-time, instead of needing extra code for an
initialization loop bad for efficiency!

This is an especially poor argument for justifying file scope objects.
But no "conforming implementation" on Windows rejects it! I don't
believe any C compiler anywhere would reject it.

Did you see the post by "Chad" were his conforming compiler refused to
compile your code?
OK you're right I should remember that. However I don't think it's the
end of the world - the standard library is always linked in so the
right functions will be found in the end by the linker.

Please read the thread titled "Question regarding malloc casing" where
it is made clear that not including a prototype in scope for Standard
library functions is simply begging to invoke undefined behaviour.

In short the compiler generates correct function call and return code at
the machine level based on the function signature. Providing the wrong
signature (which is what happens when you fail to prototype the
function), leads the compiler to generate _wrong_ function call and
return code at the machine level, which will likely cause subtle errors
and data corruption.
I don't really understand the problem with feof - it just checks if
the EOF indicator is set in a given FILE * struct. Anyway I'll read
about it.

No. In C you must first try to read from a stream using an I/O function
like getc() etc. When the function returns an EOF or an error return,
only then is it meaningful to check whether the actual cause for the
failure is an end-of-file condition (feof(s) returns true), or some
other unspecified error (ferror(s) returns true).

Please read the FAQ. It will help you avoid making many silly mistakes
and assumptions.

<http://www.c-faq.com/>
 
J

James Kuyper

santosh said:
Did you see the post by "Chad" were his conforming compiler refused to
compile your code?

To be fair, the fact that main() was declared as void was not the reason
why Chad's compiler refused the code. Chad was using gcc, and my copy of
gcc accepts void main, unless I choose an option like -pedantic-errors.
 
J

James Kuyper

James said:
Johannes Bauer wrote:
(e-mail address removed) schrieb:

int x[256]; // frequencies
Global.
It's completely acceptable to have variables defined at file scope in
C!
What's acceptable is not always a good idea. Global objects have many
disadvantages; they should be avoided except when necessary; they aren't
necessary in this case.

In this case they help simplify the code - the array gets initialized
to 0 at compile-time, instead of needing extra code for an
initialization loop bad for efficiency!

You can zero initialize automatic variables, too:

int x[256] = {0};

The speed difference between initialization during program startup vs.
after program startup isn't normally large enough to justify worrying
about. The difference in the maintainability of a program that uses
global variables and one that keeps variable as local as possible is far
more important.
But no "conforming implementation" on Windows rejects it! I don't
believe any C compiler anywhere would reject it.

I believe that gcc is available for Windows, and is conforming to the
C90 standard with the right options turned on, and conforms fairly well
with C99 with different options turned on. If, in addition, you turn on
the -pedantic-errors option, it rejects "void main()".

....
OK you're right I should remember that. However I don't think it's the
end of the world - the standard library is always linked in so the
right functions will be found in the end by the linker.

That's not true, in general. On most systems I've used, the part of the
standard library which is described in math.h is NOT always linked in;
you have to explicitly add the linker option -lm to link in the math
library. More esoterically, if you want to link C modules to a main
program written in Fortran (something I haven't had to do, but people I
work with do this all the time), the compiler will not automatically
tell the linker where to find the C libraries; you have to do that
explicitly yourself.

However, I wasn't talking about linking. I was talking about
compilation. In general, your code won't compile correctly without the
declarations that come from the appropriate standard library headers.
Those declarations are needed for the compiler to generate the correct
code for linking to the corresponding standard library functions. You
might have some "lucky" accidents with a particular compiler where
defective code appears to behave as you intended it to, but that same
code will not compile correctly under other implementations of C.
I don't really understand the problem with feof - it just checks if
the EOF indicator is set in a given FILE * struct. Anyway I'll read
about it.

Yes, do. The key point is that the EOF indicator is cleared when you
open the file; it's pointless to check it until you've started reading
the file. You should always check the return values from the functions
which read a file; if they indicate a failure, the requested data was
not actually read, and you shouldn't attempt to process it. If you've
already checked for failure from the reading functions, the only time
you actually need to use either feof() or ferror() is after you've had a
failure indication.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top