Elementary questions from a beginner

S

Sathyaish

Please forgive my nescience. I have worked extensively on Win32 but I
am only familiar with C and C++. Lately, I have been practicing C from
K&R. Here 're a few doubts I have written in the comments. I'd be
grateful if someone could answer them.

#include <stdio.h>

void main()
{

/*This program reproduces on the screen whatever you write on your
keyboard. TWICE.
One time it writes the output by default (out of the program) and the
other time it writes
because the program is at work.

So if yo write to the screen the following it appears as:

Hello, this is a test program
Hello, this is a test program

The repitition occurs at the press of the Enter key.

This is one thing I don't understand. Why is the output repeated at
the press of the enter key? Does getchar terminate
reading at a newline? It doesn't seem so because after the newline it
is still reading inside the while loop. It does
not terminate the loop. It only puts char on the output device after
every newline. Something I should expect from
getline(). This is my doubt.

Another doubt I have resolved by heuristic endeavour is the EOF
character representation on the keyboard is Ctrl+Z.
Why?

Another doubt has just creeped up. When I press Ctrl+C, it just
terminates without warning. When I press Ctrl+Z, it
asks, "Press any key to continue". Pressing any key thereafter
terminates the program. Why is that so?

I've also tried to print EOF. The value, it seems to me from the
output is -1. K&R says EOF value is big enough to
distinguish from char type range. As I see, -1 is not really *BIG
ENOUGH* but an illegal value for a char type because
normally char type is unsigned. But then I am reminded of the two's
complement representation of numbers. Does the K&R
book say it's *BIG ENOUGH* because of the binary representation of -1
being all 1s, and therefore the largest possible
value in the range?

*/

int c;

while ((c=getchar()) != EOF) putchar(c);
printf("%d", EOF);


//To emulate EOF, press Ctrl+Z


}
 
J

Joona I Palaste

Sathyaish said:
Please forgive my nescience. I have worked extensively on Win32 but I
am only familiar with C and C++. Lately, I have been practicing C from
K&R. Here 're a few doubts I have written in the comments. I'd be
grateful if someone could answer them.
#include <stdio.h>
void main()

Non-standard form of main(). Better would be int main(void).
/*This program reproduces on the screen whatever you write on your
keyboard. TWICE.
One time it writes the output by default (out of the program) and the
other time it writes
because the program is at work.
So if yo write to the screen the following it appears as:
Hello, this is a test program
Hello, this is a test program
The repitition occurs at the press of the Enter key.
This is one thing I don't understand. Why is the output repeated at
the press of the enter key?

It isn't. The first line isn't output, it's echo from your system
console, which C doesn't even know, or care about. The second line is
output from your program.
Does getchar terminate
reading at a newline? It doesn't seem so because after the newline it
is still reading inside the while loop. It does
not terminate the loop. It only puts char on the output device after
every newline. Something I should expect from
getline(). This is my doubt.

Your console (which is an OS concept and not a C one) buffers characters
until you press Enter. It then sends all of them to your C program,
which obediently displays them back to stdout, causing the second line
of text.
Another doubt I have resolved by heuristic endeavour is the EOF
character representation on the keyboard is Ctrl+Z.
Why?

Because the makers of your OS thought it would be nice. It could be
any key combination they want.
Another doubt has just creeped up. When I press Ctrl+C, it just
terminates without warning. When I press Ctrl+Z, it
asks, "Press any key to continue". Pressing any key thereafter
terminates the program. Why is that so?

Your program is not causing this. Your compiler environment is. There is
no code in your program to display "Press any key to continue", so it
isn't doing it. Your compiler environment is noticing the program's end
and printing this "Press any key to continue" all on its own. Try
exiting your compiler and running your program straight from the command
line.
I've also tried to print EOF. The value, it seems to me from the
output is -1. K&R says EOF value is big enough to
distinguish from char type range. As I see, -1 is not really *BIG
ENOUGH* but an illegal value for a char type because
normally char type is unsigned. But then I am reminded of the two's
complement representation of numbers. Does the K&R
book say it's *BIG ENOUGH* because of the binary representation of -1
being all 1s, and therefore the largest possible
value in the range?

EOF should be a value normally outside the range of (signed) char.
The C standard specifies EOF has to be a negative value. Because of
this, the return value of getchar() is int, not char, and you should
make note of this in your program.
The binary representation of -1 is not standardised. It could be all 1s,
but then it could be something different. So therefore the comment in
K&R is wrong, or at least confusing. The point is that EOF's value
must be outside the range of signed char.
while ((c=getchar()) != EOF) putchar(c);
printf("%d", EOF);
//To emulate EOF, press Ctrl+Z

}

--
/-- Joona Palaste ([email protected]) ------------- Finland --------\
\-- http://www.helsinki.fi/~palaste --------------------- rules! --------/
"'It can be easily shown that' means 'I saw a proof of this once (which I didn't
understand) which I can no longer remember'."
- A maths teacher
 
P

Peter Pichler

Joona I Palaste said:
EOF should be a value normally outside the range of (signed) char.
The C standard specifies EOF has to be a negative value.

That would make it "at least" (read: farther from zero than) -127.
More if CHAR_BIT > 8.

As far as I understand the document, all that is required is that
EOF has the type int and is negative. ITYM unsigned char.
 
J

Joona I Palaste

That would make it "at least" (read: farther from zero than) -127.
More if CHAR_BIT > 8.
As far as I understand the document, all that is required is that
EOF has the type int and is negative. ITYM unsigned char.

You think right. I was thinking "unsigned char" and writing "signed
char". Call it a brain-to-fingertips communication failure.
 
J

John Cochran

EOF should be a value normally outside the range of (signed) char.
The C standard specifies EOF has to be a negative value. Because of
this, the return value of getchar() is int, not char, and you should
make note of this in your program.
The binary representation of -1 is not standardised. It could be all 1s,
but then it could be something different. So therefore the comment in
K&R is wrong, or at least confusing. The point is that EOF's value
must be outside the range of signed char.

Wrong.
EOF simply needs to be a negative number. The functions fgetc(), getc(), etc.
return an unsigned char cast to an integer. Therefore they return only
positive numbers even if the type of char is signed. The most common value
for EOF is -1 and there is no requirement for EOF to not match a legal value
for a signed character.
 
J

Jeremy Yallop

John said:
Wrong.
EOF simply needs to be a negative number. The functions fgetc(), getc(), etc.
return an unsigned char cast to an integer. Therefore they return only
positive numbers even if the type of char is signed.

The fgetc() function returns an unsigned char converted to an int (not
"integer"). If sizeof(int) is 1 then some characters will result in
negative return values from fgetc(). In such cases fgetc() may return
a value that compares equal to EOF even though end-of-file has not
been reached and no read error has occurred:

In other words, the following code will not behave correctly on
implementations where sizeof(int) is 1:

int c;
while ((c = fgetc(fp)) != EOF) {
/* process c */
}

The robust way is to use the feof() and ferror() functions:

int c;
while (c = fgetc(fp), !feof(fp) && !ferror(fp)) {
/* process c */
}

Jeremy.
 
S

Sathyaish

Thank you so much, friends. You have spent your precious time
understanding my problem and helping me out with answers.

Since there are so many questions in this post, I would request some
more of your time, in which I shall be reading each of the answers in
the light of my questions to better understand the concepts. I still
feel there's something missing that I could not communciate well
enough. So it would take me a few days' time to come back with more
questions on this thread.

Thank you so much for your time, friends.

Warm Regards,
Sathyaish Chakravarthy
 
D

Dan Pop

In said:
In other words, the following code will not behave correctly on
implementations where sizeof(int) is 1:

int c;
while ((c = fgetc(fp)) != EOF) {
/* process c */
}

The robust way is to use the feof() and ferror() functions:

int c;
while (c = fgetc(fp), !feof(fp) && !ferror(fp)) {
/* process c */
}

OTOH, sizeof(int) == 1 would render <ctype.h> unimplementable:

1 The header <ctype.h> declares several functions useful for
classifying and mapping characters. In all cases the argument
is an int, the value of which shall be representable as an
unsigned char or shall equal the value of the macro EOF. If the
argument has any other value, the behavior is undefined.

On such an implementation, there are unsigned char values that cannot
be represented by an int. Passing such a value to a <ctype.h> function
would either generate the wrong answer (if the result of converting the
unsigned char value to int was non-negative) or invoke undefined
behaviour (if the result of the conversion was negative).

So, unless you're coding for freestanding implementations (which need
not provide <ctype.h> at all or as specified by the C standard), you can
safely assume that sizeof(int) > 1 and use the first loop above, as
taught by virtually any C book.

Dan
 
P

pete

Dan said:
OTOH, sizeof(int) == 1 would render <ctype.h> unimplementable:

1 The header <ctype.h> declares several functions useful for
classifying and mapping characters. In all cases the argument
is an int, the value of which shall be representable as an
unsigned char or shall equal the value of the macro EOF. If the
argument has any other value, the behavior is undefined.

On such an implementation, there are unsigned char values that cannot
be represented by an int.
Passing such a value to a <ctype.h> function
would either generate the wrong answer
(if the result of converting the
unsigned char value to int was non-negative) or invoke undefined
behaviour (if the result of the conversion was negative).

I don't see why that is a problem.
The description of the ctype functions,
implies that there may any number of int values for arguments,
which cause undefined behavior in a ctype function.

isdigit(EOF == -1 ? -2 : -1)

The description of the ctype functions does not say that
they should be able to take any unsigned char value as an argument,
only that the int argument value should also be representable as
an unsigned char.
 
D

Dan Pop

In said:
I don't see why that is a problem.
The description of the ctype functions,
implies that there may any number of int values for arguments,
which cause undefined behavior in a ctype function.

OTOH, the underlined text above suggests that, if I have a valid character
value, I can use these functions. If 'a' > INT_MAX, isalpha('a')
invokes undefined behaviour.

Dan
 
P

pete

Dan said:
OTOH, the underlined text above suggests that,
if I have a valid character
value, I can use these functions. If 'a' > INT_MAX, isalpha('a')
invokes undefined behaviour.

'a' is a constant of type int.
'a' can't excede INT_MAX.

I think that the implication of
"... if I have a valid character value, I can use these functions."
is that 'a' is also less than UCHAR_MAX.
 
R

Ravi Uday

[snip]
In other words, the following code will not behave correctly on
implementations where sizeof(int) is 1:

int c;
while ((c = fgetc(fp)) != EOF) {
/* process c */
}

The robust way is to use the feof() and ferror() functions:

int c;
while (c = fgetc(fp), !feof(fp) && !ferror(fp)) {
/* process c */
}

I just interchanged the order to know the evaluation. Results are not same ??
Can someone explain to me.

while ( c1 = (!feof(fp) && !ferror(fp)), fgetc(fp) ){ /* Infinite loop !! */
/* process c */
}

- Ravi
 
R

Richard Bos

I just interchanged the order to know the evaluation. Results are not same ??
Can someone explain to me.

while ( c1 = (!feof(fp) && !ferror(fp)), fgetc(fp) ){ /* Infinite loop !! */
/* process c */
}

No wonder. This loop is equivalent to

c1 = !feof(fp) && !ferror(fp);
while (fgetc(fp) ){
/* process c */
c1 = !feof(fp) && !ferror(fp);
}

and since fgetc() rarely if ever returns a zero value for text files,
this is a semi-infinite loop unless you feed it some binary data.

Richard
 

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,733
Messages
2,569,440
Members
44,831
Latest member
HealthSmartketoReviews

Latest Threads

Top