I have this simple code (trying to do an exercise in KandR):-
#include <stdio.h>
int main(){
int c = EOF;
while(c=(getchar() != EOF)){
printf("%d",c);
}
return 0;
}
When i run this and enter any character (a single character), i get the output as 11. If i enter multiple characters for example 'bbb' i get the output as 1111. I understand that i have explicitly added brackets to give precendence to the condition check of getchar() != EOF which should either result in 1 or 0. But i don't understand why am i getting multiple 1's.
Another case is:
#include <stdio.h>
int main(){
int c = EOF;
while(c=(getchar() != EOF)){
putchar(c);
}
return 0;
}
No matter which character i enter, i always get the output as a square box with 1's and 0's in it (shown at the bottom of the screenshot below)
1) In the first case, why is the output printing more than 1 1's?
2) Why isn't the output of case 2 same as case 1?
Until unless you press EOF, (getchar() != EOF) will return true which assigns 1 to c. That's why you are getting output always as 11, first 1 for the character you entered and second 1 is for \n passed to the input buffer on pressing Enter key.
Similarly in case of putchar it prints the character corresponding to the returned value 1 which is non-printable (printable characters start from 32) and you will get some weird output, one for input character and another for \n.
Now change the parentheses in conditional expression to
while( (c=getchar()) != EOF ){...}
Now it will work as it should but will give you two ASCII code in first case (one for \n).
1) In the first case, why is the output printing more than 1 1's?
Because you are looking for an EOF. In order to send your program EOF from the keyboard, press Ctrl+Z
2) Why isn't the output of case 2 same as case 1?
Because %d produces a decimal representation of the character code, while putchar produces the character itself. For example, if you print 'A' using printf's %d format, you would see 65 - ASCII code of the uppercase character A. On the other hand, if you print it using putchar, you would see character A itself.
Demo on ideone.
Related
I have two pieces of codes to test how the two console I/O functions, getchar() & scanf(), handle the EOF. But I still do not have a clear comprehension about the actual operations behind the outputs and their behaviors. Can someone explains that for me? Thanks a lot! (I am using Windows OS)
// 1st piece of Code
#include <stdio.h>
#include <ctype.h>
int main(void)
{
char ch;
while ((ch=getchar()) != EOF)
{
putchar(toupper(ch));
}
return 0;
}
If I type
abc
or
abc(ctrl+z)
The program will have the same outputs:
ABC
// 2nd piece of Code
#include<stdio.h>
int main(void)
{
int x;
while(scanf("%d",&x) != EOF)
{
/*Ctrl + z + Enter*/
printf("x=%d\n",x);
}
return 0;
}
If I type
123
The program will output:
x=123
Otherwise, if I type
123(ctrl+z)
The program will have an infinite output:
x=123
x=123
x=123
x=123
...
getchar() returns the value of the character converted to unsigned char or EOF in case of error.
The error can be "end of file" or something else; usually (for getchar()) the programmer does not care about the error, just that an error happened.
scanf() returns the number of values matched and assigned (basically the number of % in the format string) or EOF in case of error. Note that the number can be less than the number of % in case, for example, of badly formatted input
Just like for getchar() the error can be "end of file" or something else. Particularly, reading less than the number of % is not an error.
So you may prefer to test for the correct number of assignments rather than testing for error in scanf()
#include <stdio.h>
int main(void) {
int x;
while (scanf("%d", &x) != 1) {
/*Ctrl + z + Enter*/
printf("x=%d\n", x);
}
return 0;
}
The problem is that on Windows the EOF is put into the input buffer like a normal character (with the encoded value 26).
When reading character by character (with e.g. getchar) this is handled by the Windows run-time library. But it doesn't work like that with scanf because when scanf parses the input it's like another character. And as a non-digit it's an invalid character for te "%d" format, leading to your scanf Call to return 0 instead of EOF (since it's not parsed by the format).
One way to solve it is to press the Ctrl-Z sequence on its own new line.
Another (and more reliable) way to solve it is to check that scanf returns the number of formats you have in the string. In your case you should compare against 1 (as you have one format specifier).
I'm working through some of the exercises in K&R. Exercise 1-6 asks for verification that the expression getchar() != EOF is either 0 or 1. I understand why it is, but the code I wrote to prove it didn't work as expected. I wrote the following two snippets:
Version 1:
int main(void)
{
int c;
while (c = getchar() != EOF)
{
putchar(c);
}
printf("%d at EOF\n", c);
return 0;
}
Version 2:
int main(void)
{
int c;
while (c = getchar() != EOF)
{
printf("%d\n", c);
}
printf("%d at EOF\n", c);
return 0;
}
My questions:
When I type in a character and hit enter with version one, why do I not see either a 0 or 1 on the screen? Instead, my cursor moves to the first position on next line, which is otherwise empty. I though putchar would send c to stdout.
While the use of printf in the second version does produce a 0 or 1 appropriately, it duplicates the 1 for each non-EOF character (I see the number 1 on two consecutive lines for each character I input). Why?
Many thanks in advance for your thoughts. If there is a reference that you think would help, please send a link.
CLARIFICATION:
I know I'm assigning c a value of either 0 or 1. That's what I want to do, and it's what the exercise wants. That's also why I don't have parentheses around c = getchar(). My question deals more with understanding why the output isn't what I had expected. Sorry for any confusion.
The assignment operator = has lower precedence than the inequality operator !=.
So this:
while (c = getchar() != EOF)
Is parsed as:
while (c = (getchar() != EOF))
So then c is assigned the boolean value 1 if getchar is not EOF and 0 if it does return EOF.
As a result, the first program print the character for the ASCII code 1, which is a non-printable character. That's why you don't see anything. The second program, using the %d format specifier to printf, converts the number 1 to its string representation.
You need parenthesis to have the result of getchar assigned to c:
while ((c = getchar()) != EOF)
EDIT:
To further clarify the output you're getting, in both programs the variable c has the value 1 inside of each while loop. The difference here is that putchar is printing the character with the ASCII value of 1 (an unprintable character), while printf with %d print the textual representation of the value 1, i.e. 1.
If you changed the printf call to this:
printf("%c", c);
You would get the same output as using putchar.
As for the printing of 1 twice for each character, that is because you're actually entering two characters: the key you press, plus the enter key. When reading from the console, the getchar function doesn't return until the enter key is pressed.
I have been going through The C Programming Language by Brian W. Kernighan and Dennis M. Ritchie and am at Character Input and Output, specifically on File Copying. The example in the book
#include <stdio.h>
int main(void)
{
int c;
c = getchar();
while (c != EOF)
{
putchar(c);
c = getchar();
}
return 0;
}
works perfectly.
But I decided to put my own spin on things and rewrite it a bit:
#define <stdio.h>
int main(void)
{
int c;
printf("Please enter a digit: ");
c = getchar();
while (c != EOF)
{
printf("The digit entered was: ");
putchar(c);
printf("Please enter a digit: ");
c = getchar();
}
return 0;
}
After compiling and executing, the result of my code is:
Please enter a digit: 9
The digit entered was: 9Please enter a digit: The digit entered was:
Please enter a digit: *cursor is here*
The input should be:
Please enter a digit: 9
The digit entered was: 9
Please enter a digit: *the cursor should be here*
Also, I have a little problem understanding EOF. It would be great if someone could help me with these issues.
Thank you!
Most 'terminals' do not send keyboard input to the program 'one key at at time'. Rather, the terminal will wait for the enter key, and then send all keys pressed (up to that point) to the target program. Hence, the question code suffers from getting newlines \n as input, as well as digits.
The code below throws away all non-digit values (but also allows for the EOF value):
#include <stdio.h>
#include <ctype.h>
int main(void)
{
int c;
do {
c=0;
/* Get user input */
printf("Please enter a digit: ");
while(!isdigit(c) && EOF != c)
c = getchar();
/* Produce output. */
if(c == EOF)
printf("\n");
else
printf("The digit entered was: %c\n", c);
} while (c != EOF);
return 0;
}
Compile the above (Linux GCC example: gcc -Wall -o test *.c)
Then execute: (Linux example: ./test)
Please enter a digit: 5
The digit entered was: 5
Please enter a digit: 6
The digit entered was: 6
Please enter a digit: <CTRL-D>
<CTRL-D> usually generates an EOF condition.
Because the ENTER value "\n" (ASCII value 10) will be get by
getchar(c);
so it will do second time of
printf("The digit entered was: ");
printf("Please enter a digit: ");
Well, it's the trouble about the new-line character that you feed the standard input with while handing your piece into the console screen.
Let me ask you this:
With the code that you have said to work perfectly, you probably have tried some input like "Hello!" let's say, or maybe just a single character like "9" as in your example. You have typed down 'H' then 'e' then 'l' ... then '!' and then hit the enter-key, or just '9' and then hit the enter-key.
After that, you had the following on your screen:
Hello!
Hello!
_
The last underscore there is for indicating the flashing cursor. My question is: Why is it there? Why is it not right next to the last '!'?
Same story with the 9, this would be the things on your screen:
9
9
_
Well, here's why: It is because your programme has printed one more character that you cannot see directly, a new-line character '\n'. Proof: If it hadn't printed that, the underscore would flash next to the '!' or '9'.
When you hit your enter-key, you feed the standard input with a new-line character '\n' in addition to whatever you had typed down so far in that session. Standard input gets fed with all that and getchar(); consumes them one by one.
In your code which doesn't work as you had expected, you feed the standard input with '9' '\n', getchar(); first gets the '9' and then '\n', and then it looks for more, but there isn't any more. Only then (when there isn't more) it asks from you for more.
And that's the story...
To get what you were expecting, you should do something else, I won't tell you that directly, it's a good exercise. I can hint you that you should be using another while loop within the one you already have with a condition checking for a '\n' encounter.
EOF is just a special character, or rather a value indicating a special case of being at the End Of File. For standard input, I guess it can be issued with the CTRL + D key combination on Linux, it is CTRL + Z on Windows. Using that combination and then hitting enter should get you out of that outer loop.
You're being tripped up by a trailing newline in your input; when you type 9 and hit Enter, the input stream that your code reads from will contain the encodings for two characters, the 9 and a newline (in ASCII, it would be the sequence of values [57,10]) . Here's how it breaks down:
Code prompts you to enter a digit
You type 9 and hit Enter
Input stream now contains the characters {'9', '\n'};
getchar returns the next available character from the input stream, which is '9'
'9' is not equal to EOF, so you print the digit and prompt for the next character
getchar returns the next available character from the input stream, which is '\n'
'\n' is not equal to EOF, so you print the character and prompt for the next character
The input stream is now empty, so getchar blocks until you type something else.
You can fix this relatively easily:
#include <ctype.h>
...
while (c != EOF)
{
printf("The digit entered was: ");
putchar(c);
printf("Please enter a digit: ");
do
{
c = getchar();
} while ( isspace( c ));
}
That last little do loop will read characters from the input stream until it sees something that isn't a newline or other whitespace character. You can add an additional check to make sure the character entered really was a digit [0-9]:
while (c != EOF)
{
printf("The digit entered was: ");
putchar(c);
do
{
printf("Please enter a digit: ");
do
{
c = getchar();
} while ( isspace( c ));
if ( !isdigit( c ))
printf( "%c is not a digit!\n" );
} while ( !isdigit( c ));
}
Now, something to be aware of; what you're storing in c is not the value 9, but the encoding for the character '9', which in ASCII is the integer value 57. If you want to store the value 9 in c, you'll have to do something different.
When I want to figure out what does getchar() actually do, this little piece of loop did confuse me.
int i;
int c;
for (i = 0; i < 100; i++) {
c = getchar();
printf("%d\n", c);
printf("i is %d\n", i);
}
The input and output is:
input: 1
output:
49
i is 0
10
i is 1
input: 12
output:
49
i is 2
50
i is 3
10
i is 4
As I previously supposed, if I enter 1 character, the getchar() should extract it out and putchar() would print it, then the program move to the next loop and wait for my next input. But the results seem to show that the code do not work as I supposed:
What do the output numbers mean?
There is always an extra loop printing 10, what does this 10 mean? If it means EOF, why after replacing c = getchar(); with c = (getchar() != EOF); within the loop, the code always print 1 which, as I supposed, should print a 0 in the last loop?
Thx very much!
Question
What do the output numbers mean?
The output numbers refer to the value of your characters according to your character set, usually based on ASCII (some mainframes use also EDCDIC).
C11 (n1570), § 5.2.1 Character sets
Two sets of characters and their associated collating sequences shall be defined: the set in
which source files are written (the source character set), and the set interpreted in the
execution environment (the execution character set). Each set is further divided into a
basic character set, whose contents are given by this subclause, and a set of zero or more
locale-specific members (which are not members of the basic character set) called
extended characters. The combined set is also called the extended character set. The
values of the members of the execution character set are implementation-defined.
Therefore, through this character encoding, 49 is the character'1' and 50 is the character '2'.
Question
There is always an extra loop printing 10, what does this 10 mean?
With ASCII charset, 10 is the linefeed character '\n'.
When you are typing the character '1' on your keyboard, the standard input stream stdin will receive in fact two characters : '1' and '\n', since you are pressing <Enter> to valide your input.
Therefore, you should clean the standard input stream once you have done your getchar call. One possible way to achieve it is to consume every characters until you reach a newline character or EOF:
#include <stdio.h>
int c;
while ((c = getchar()) != '\n' && c != EOF)
;
On BSD, there is also the function fpurge and, on Solaris and GNU/Linux, __fpurge is available.
Question
If it means EOF, why after replacing c = getchar(); with c = (getchar() != EOF); within the loop, the code always print 1 which, as I supposed, should print a 0 in the last loop?
The value of EOF can't be 10, since EOF must have a negative value.
C11 (n1570), § 7.21.1 Introduction
EOF, which expands to an integer constant expression, with type int and a negative value [...].
What do the output numbers mean?
Character codes of the character getchar() returns, since you get a one and you're printing it using the %d specifier. In this case, it seems your character encoding is ASCII or maybe UTF-8, so 1 stands for 49, 2 for 50, etc.
2: [... too long to quote...]
10 is the ASCII and Unicode char code for newline ('\n'). Since you press Enter (getchar() waits for it!), you will get the character that Enter sent to the terminal.
I'm completely new to C and have this example from The C Programming Language book:
#include <stdio.h>
#define IN 1 /* inside a word */
#define OUT 0 /* outside a word */
/* count line and words and characters in input */
main()
{
int c, nl, nw, nc, state;
state = OUT;
nl = nw = nc = 0;
while ((c = getchar()) != EOF) {
++nc;
if (c == '\n')
++nl;
if ( c == ' ' || c == '\n' || c == '\t')
state = OUT;
else if ( state == OUT) {
state = IN;
++nw;
}
}
printf("%d %d %d\n", nl, nw, nc);
}
The code compiles fine in the terminal with: gcc -o count count.c
When I run it with: ./count it let's me test it, gives me a new line to type in the input. I type in, hit the Return and it gives me another blank line for my text input, not outputting anything.
What is it that I do wrong? I was doing some other examples with input and I was receiving an output, but none of the code that I use from this book works for me now.
Many thanks.
The value "EOF" is not equal to a newline aka '\n'. "EOF" is the value sent when you hit ctrl+d, when standard input (aka getchar()) is coming from the keyboard, or when you reach a file, if you're redirecting standard input from a file (which you would do with ./count < file).
Hit Ctrl-D, which is the EOF character for Linux, assuming that is what you are using.
The loop in the code says to iterate till EOF (End-of-File) character is read. If you are using Linux, this would be Ctrl+D. For Windows, you have to press Ctrl+Z and enter key.
If the intended outcome of the program is to count the number of lines, words and characters in the input, then it is important that there should be a clear demarcation of where the given input starts and where it ends.
In this particular program, The input starts when the while loop starts (and the input character is not EOF) and the input stops when the EOF character is entered.
The meaning and usage of EOF has to be clear.
EOF is a macro that is returned by stream functions to indicate an end-of-file condition. This symbol is declared in stdio.h.
When a comparison of the form:
((c = getchar()) != EOF)
is made, what happens internally is that the ASCII value of the character input in 'c' is compared to the ASCII value of EOF.
After you enter the input you hit 'Return'. 'Return' corresponds to New Line of Line feed and the ASCII value for this is 10 (Decimal).
EOF in ASCII corresponds to End of Transmission and has the ASCII value 4 (Decimal).
So if you keep hitting 'Return' after the inputs, the program will expect inputs infinitley. To indicate the end of input, EOF has to be input. EOF corresponds to Ctrl-D (ASCII value 4).
So to sum up, there is nothing wrong with your program. All you have to do is at the end of the input, instead of hitting 'Return' , Do a control-D.
Hm,I love K&R .
Got this question before, needs a ending.
As Ctrl+d, you can try:
ls | ./count