What's wrong ?

D

Daniel.C

Hello.
I just copied this code from my book with no modification :

#include <stdio.h>
/* count characters in input; 1st version */
main()
{
long nc;

nc = 0;
while (getchar() != EOF)
++nc;
printf("%ld\n", nc);
}

There is no output, and no completion either. I tried adding a "printf" at
the end of the code, but it doesn't display.

i'm using MinGW developer studio with windows XP home.

Thanks in advance.
Daniel
 
J

jacob navia

Daniel.C said:
Hello.
I just copied this code from my book with no modification :

#include <stdio.h>
/* count characters in input; 1st version */
main()
{
long nc;

nc = 0;
while (getchar() != EOF)
++nc;
printf("%ld\n", nc);
}

There is no output, and no completion either. I tried adding a "printf" at
the end of the code, but it doesn't display.

i'm using MinGW developer studio with windows XP home.

Thanks in advance.
Daniel
You have to input an end of file character
since that is the condition you specified.

Under windows you would type ctrl+Z under linux
you would type ctrl+d
 
E

Eric Sosman

Daniel.C said:
Hello.
I just copied this code from my book with no modification :

#include <stdio.h>
/* count characters in input; 1st version */
main()
{
long nc;

nc = 0;
while (getchar() != EOF)
++nc;
printf("%ld\n", nc);
}

There is no output, and no completion either. I tried adding a "printf" at
the end of the code, but it doesn't display.

Until getchar() returns EOF, this program just counts
silently and produces no output. The output appears after
end-of-input is detected.
i'm using MinGW developer studio with windows XP home.

If the input is coming from your keyboard, simply taking
your hands away and deciding not to press any more keys won't
tell the program that you're finished typing. For all it
knows, you're thinking Very Hard or temporarily away on a
bathroom break or something, and it will keep waiting for
that next key. On Windows, the convention is to press ctrl-Z
to indicate "Th-th-that's all, folks!" Other systems have
other conventions.

If the input is coming from somewhere else, there will
be other, source-specific ways to indicate that it's all
finished. Disk-resident files typically need no help, but
things like sockets might.
 
R

Richard Tobin

Daniel.C said:
I just copied this code from my book with no modification :

#include <stdio.h>
/* count characters in input; 1st version */
main()
{
long nc;

nc = 0;
while (getchar() != EOF)
++nc;
printf("%ld\n", nc);
}
There is no output, and no completion either.

Are you giving it some input on standard input? Either by typing some
characters followed by an end-of-file indication (probably control-Z
or control-D), or redirecting from a file?

-- Richard
 
D

Daniel.C

Richard Tobin said:
Are you giving it some input on standard input? Either by typing some
characters followed by an end-of-file indication (probably control-Z
or control-D), or redirecting from a file?

-- Richard

Many thanks to all contributors.
Daniel
 
C

CBFalconer

Daniel.C said:
I just copied this code from my book with no modification :

#include <stdio.h>
/* count characters in input; 1st version */
main()

int main(void)
{
long nc;

nc = 0;
while (getchar() != EOF)
++nc;
printf("%ld\n", nc);

return 0;
}

There is no output, and no completion either. I tried adding a
"printf" at the end of the code, but it doesn't display.

Your book is obsolete and wrong. C99 requires the int in the
declaration of main, and the void for parameters is just good
practice. C99 will supply a default return value, but earlier
standards don't. Thus your code is wrong for any version.

If it doesn't work with the above simple changes, your compiler
system is fouled.
 
S

santosh

CBFalconer said:
int main(void)


return 0;


Your book is obsolete and wrong.

The example probably came from K&R2. So you are saying it's obsolete and
wrong. On what basis?
C99 requires the int in the
declaration of main, and the void for parameters is just good
practice. C99 will supply a default return value, but earlier
standards don't. Thus your code is wrong for any version.

They were omitted for brevity, as you well know.
If it doesn't work with the above simple changes, your compiler
system is fouled.

No, his problem is already solved, and it was not a compiletime one.
 
D

Daniel.C

jacob navia said:
You have to input an end of file character
since that is the condition you specified.

Under windows you would type ctrl+Z under linux
you would type ctrl+d
Just a precision. In the following code :

#include <stdio.h>

main()
{
int c;
while ((c = getchar()) != EOF)
putchar(c);
}
the enter key triggers the execution of the code. I certainly misunderstand
something. What is the difference between the two ?
Sorry, it's a painful beginning...
Daniel
 
S

santosh

Daniel.C said:
Just a precision. In the following code :

#include <stdio.h>

main()
{
int c;
while ((c = getchar()) != EOF)
putchar(c);
}
the enter key triggers the execution of the code. I certainly
misunderstand something. What is the difference between the two ?

In the loop above getchar() continues getting characters until it
detects end-of-file. This can happen either due to normal termination
of input or due to an error. You need to call other functions to
disambiguate between the two, which you do not need to worry about just
yet.

Normally to signal end-of-file from the keyboard you need to type a
system specific key sequence. For Windows it is CTRL-Z (Press the 'z'
key with the CONTROL key depressed) and it is CTRL-D for UNIX. Under
these systems simply hitting ENTER should not terminate the above loop.
Other systems may have other key sequences and semantics about input.
Generally I/O has been a very system specific and messy area of
programming.

Coming to the difference. ENTER is significant when the program
recieving your input is set to the so called "line input" mode. Most
interactive programs are set in this mode. In this mode the program
will continue getting input until a end-of-line sequence is detected.
This is commonly generated by pressing ENTER from keyboards.

Your program above is not an interactive program in the sense that it
can be used as a "filter" and as an element in a sequence of connected
commands. Usually in non-interactive input, end-of-file rather than
end-of-line signals end of input. This is because of various historical
reasons having to do with the idiosyncrasies of systems originating in
the fifties and sixties. They became very idiomatic and got stuck as a
practise.

In C, at this stage, all you need to remember is that for
non-interactive input, collect input until an end-of-file or error
occurs (which most C functions indicate by returning the value EOF
instead of a normal value). For interactive input (where you expect a
user to enter the input) you should usually collect input until you
receive a '\n' character (which is what the C library uses to represent
the system specific end-of-line sequence).
Sorry, it's a painful beginning...

Yes. I/O is generally confusing for newbies, particularly in languages
like C which expose a lot of low-level characteristics.
 
D

Daniel.C

santosh said:
In the loop above getchar() continues getting characters until it
detects end-of-file. This can happen either due to normal termination
of input or due to an error. You need to call other functions to
disambiguate between the two, which you do not need to worry about just
yet.

Normally to signal end-of-file from the keyboard you need to type a
system specific key sequence. For Windows it is CTRL-Z (Press the 'z'
key with the CONTROL key depressed) and it is CTRL-D for UNIX. Under
these systems simply hitting ENTER should not terminate the above loop.
Other systems may have other key sequences and semantics about input.
Generally I/O has been a very system specific and messy area of
programming.

Coming to the difference. ENTER is significant when the program
recieving your input is set to the so called "line input" mode. Most
interactive programs are set in this mode. In this mode the program
will continue getting input until a end-of-line sequence is detected.
This is commonly generated by pressing ENTER from keyboards.

Your program above is not an interactive program in the sense that it
can be used as a "filter" and as an element in a sequence of connected
commands. Usually in non-interactive input, end-of-file rather than
end-of-line signals end of input. This is because of various historical
reasons having to do with the idiosyncrasies of systems originating in
the fifties and sixties. They became very idiomatic and got stuck as a
practise.

In C, at this stage, all you need to remember is that for
non-interactive input, collect input until an end-of-file or error
occurs (which most C functions indicate by returning the value EOF
instead of a normal value). For interactive input (where you expect a
user to enter the input) you should usually collect input until you
receive a '\n' character (which is what the C library uses to represent
the system specific end-of-line sequence).


Yes. I/O is generally confusing for newbies, particularly in languages
like C which expose a lot of low-level characteristics.

Thank you very much for your detailed explanations.
Daniel
 
K

Keith Thompson

CBFalconer said:
int main(void)

Yes, that's an improvement.
return 0;

Yes, that's also an improvement.
Your book is obsolete and wrong. C99 requires the int in the
declaration of main, and the void for parameters is just good
practice. C99 will supply a default return value, but earlier
standards don't. Thus your code is wrong for any version.

Neither version of the standard defines the term "wrong", so it's not
clear what you're talking about.

The declaration "main()" is legal for C90. (There's a subtle argument
that the void keyword might be necessary, but since ANSI was careful
not to break existing code, it was clearly the intent that
"main() { ... }" should be acceptable.)

Support for C90 is much more widespread than support for C99, and even
compilers that do support C99 will almost certainly do no more than
issue a warning for the implicit int return type. (Which is not to
say that such a warning should be ignored, of course.)

As for the missing return statement, in C90 that merely causes an
undefined status to be returned to the calling environment. If the
environment doesn't use the status (say, if you type "./prog" to a
Unix shell), then this likely won't make any difference; at worst, it
might result in some harmless message after the program terminates.

Having said that, yes, both changes you suggest are certainly
improvements, but they don't necessarily tranform the program from
being "wrong" to being "right".
If it doesn't work with the above simple changes, your compiler
system is fouled.

If the above simple changes make any relevant difference to the
behavior of the program, I'll be astonished. We now know what the
problem was, and it would have shown up in exactly the same way with
your suggested changes in place.

I probably would have mentioned these things myself if they hadn't
already been covered by others. Actually, though, what bothered me
more was the way the source code was formatted. Here's a modified
version of the program with your changes and better layout (I also
added a pair of braces):

#include <stdio.h>
/* count characters in input; 1st version */
int main(void)
{
long nc;

nc = 0;
while (getchar() != EOF) {
++nc;
}
printf("%ld\n", nc);
return 0;
}

The point here (I'm addressing the OP now) is that consistent
indentation makes the structure of the program much easier to see. It
doesn't matter much for something this small, but it's vital for
larger and more complex programs, and it's a good idea to get into the
habit as early as possible.
 
C

CBFalconer

santosh said:
The example probably came from K&R2. So you are saying it's obsolete and
wrong. On what basis?


They were omitted for brevity, as you well know.

As I explained above, one of the error fouls C89 thru C95, the
other fouls on C99. So his compiler is accepting erroneous code -
no need to encourage it. Of course I didn't think of the simple
solution of the OP not knowing how to signal EOF. But that is
another subject. The code is still WRONG.
 
C

CBFalconer

Keith said:
.... snip ...

Support for C90 is much more widespread than support for C99, and even
compilers that do support C99 will almost certainly do no more than
issue a warning for the implicit int return type. (Which is not to
say that such a warning should be ignored, of course.)

I wonder. Since int is no longer a default type, the untyped
procedure definition is, I think, a syntax error, and requires a
complaint. The standard doesn't differentiate between errors and
warnings or anything else.
 
F

Falcon Kirtaran

Daniel.C said:
Hello.
I just copied this code from my book with no modification :

#include <stdio.h>
/* count characters in input; 1st version */
main()
{
long nc;

nc = 0;
while (getchar() != EOF)
++nc;
printf("%ld\n", nc);
}

There is no output, and no completion either. I tried adding a "printf" at
the end of the code, but it doesn't display.

i'm using MinGW developer studio with windows XP home.

Thanks in advance.
Daniel

Firstly, you ought to use Linux instead, but that is moot :p

To answer your question, what is the command line you use to run your
program?

If it is something like "a.out < file" EOF will actually be sent to
stdin (where your program is reading data from) when the file "file"
ends. However, if you ran it like "a.out", stdin is connected to your
tty (console) and the program is waiting for EOF (and looking like it
hung). Most standard UNIX consoles will allow you to type control-d for
EOF; try typing your input and then this. Enter simply inputs the
newline sequence, which is not EOF.
 
K

Keith Thompson

CBFalconer said:
Keith Thompson wrote:
... snip ...

I wonder. Since int is no longer a default type, the untyped
procedure definition is, I think, a syntax error, and requires a
complaint. The standard doesn't differentiate between errors and
warnings or anything else.

Right, and a pure C99 implementation certainly *could* treat "main()"
as a syntax error. But I doubt that any of them do so. I suspect
that most or all of them use a grammar that recognizes implicit int so
they can print a meaningful error message (or allow it either as an
extension or in a C90-conforming mode).
 
D

Daniel.C

Many thanks.
Daniel
Falcon Kirtaran said:
Firstly, you ought to use Linux instead, but that is moot :p

To answer your question, what is the command line you use to run your
program?

If it is something like "a.out < file" EOF will actually be sent to stdin
(where your program is reading data from) when the file "file" ends.
However, if you ran it like "a.out", stdin is connected to your tty
(console) and the program is waiting for EOF (and looking like it hung).
Most standard UNIX consoles will allow you to type control-d for EOF; try
typing your input and then this. Enter simply inputs the newline
sequence, which is not EOF.
 
S

santosh

CBFalconer said:
As I explained above, one of the error fouls C89 thru C95, the
other fouls on C99. So his compiler is accepting erroneous code -
no need to encourage it. Of course I didn't think of the simple
solution of the OP not knowing how to signal EOF. But that is
another subject. The code is still WRONG.

The program isn't in error for C90. It merely returns an unspecified
status value. I don't think that invokes undefined behaviour.
 
C

CBFalconer

santosh said:
CBFalconer wrote:
.... snip ...


The program isn't in error for C90. It merely returns an unspecified
status value. I don't think that invokes undefined behaviour.

Why shouldn't the OS have a provision: I won't display the output
unless the program completes successfully?
 
R

Richard Heathfield

santosh said:
CBFalconer wrote:

The example is indeed from K&R2 (top of page 18, in fact). K&R2 is neither
obsolete nor wrong.


No, it doesn't. The behaviour of the program under C89 through C95 is
well-defined. The *termination status* is undefined, but that isn't an
error.

....for which everyone and his cat has a conforming compiler, of course. I
Don't Think So.

No, his compiler is accepting correct code. I consider Chuck's amendments
to improve the style of the code, but the code as written works just fine.
The program isn't in error for C90. It merely returns an unspecified
status value. I don't think that invokes undefined behaviour.

Well, it's an undefined termination status, but that's all. The program
does not rely on any unspecified, undefined, or implementation-defined
behaviour (unless you count the possibility of overflowing a long int,
which would take quite a while to achieve), so it can be argued that it is
strictly conforming.
 

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

Similar Threads


Members online

Forum statistics

Threads
473,994
Messages
2,570,223
Members
46,812
Latest member
GracielaWa

Latest Threads

Top