putchar and printf not behaving as expected - c

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.

Related

How to get get last character on getchar()!=EOF

Is there any way to get the last element before EOF while using getchar()?
E.g I have a text saying
"Hey there
people"
What would be the condition to check the last char in that text (in our example e). My thoughts are the following but i am not sure what the if condition should be.
//pseydocode
int c;
while(c=getchar() != EOF)
if(c==EOF-1) //assuming EOF is the end EOF -1 would be the last character.
if(c==O) print O;
else if(c==P) print P;
else if (c==e) print e;
I want to check the very last character and if it's a specific letter to print it.
Thank you.
There is no indication that the character just returned from getchar is the last available character. To print the last character before EOF, you must remember the return from getchar. When EOF is returned, then print the previously remembered character.
For example, this code prints the last character of a stream:
#include <stdio.h>
int main(void)
{
int c, previous = EOF;
while (1)
{
c = getchar();
if (c == EOF)
break;
previous = c;
}
if (previous == EOF)
printf("There were no characters in the stream.\n");
else
printf("The last character was %c.\n", previous);
}
When you try the above, you are likely to find the last character is a new-line character, '\n'.
In general, it would be impossible for a C implementation to know the character just returned is the last character. Input might be coming from a terminal, for example, and the user has just typed a character, which getchar() returns. At this point, we do not know what the user will do next—they might type another character, or they might type and end-of-file indication (as by pressing control-D twice, in a Unix system). So, having just gotten a character, we do not know whether what is coming next is another character or is EOF.
char c;
int tmp = 0;
while(tmp != EOF)
{
c = (char)tmp;
tmp=getchar();
}
c becomes 0 (null terminator) in case of an empty input, otherwise it is the last character before EOF.
You have to write the code to remember the last character(if any at all) before EOF.
int c;
int lc = EOF;
while((c=getchar()) != EOF) {
lc = c;
}
//here lc will hold the last character read before EOF,
//or it will also be EOF if no characters got read at all.
Note that your original condition was while(c=getchar() != EOF), which is incorrect - it is evaluated as while(c=(getchar() != EOF)), you have to write while((c=getchar()) != EOF

Usage of EOF in C

Output
Code:
#include<stdio.h>
main()
{
int c;
printf("Enter any charachter!: ");
while((c = getchar()) != EOF) {
putchar(c);
printf("%d\n", (c = getchar()) != EOF);
}
}
I've tried to test out EOF in C and I'm having a difficult time with it. I've wanted to get the value of EOF and found out that it is -1.
I wrote a simple program using getchar() and putchar().
I have added the screenshot of the program and output. Output doesn't make any sense to me.
As you can see I'm trying to get a character and display it using getchar() and putchar(). And I'm trying to print out the value of the condition used in the while loop. To check the EOF I'm deliberately entering -1 as input. putchar() prints out -1 and then the final printf statement confuses me. I enter -1 for getchar() but 1 displayed meaning c is not equal to EOF. But I thought -1 is EOF.
And I don't understand why 11 is also displayed. I'm using codeblocks IDE.
Please help me. Thanks in advance.
EOF isn’t a character, and it isn’t read from the stream. It’s just the return value indicating that there is no more input on that stream. You can signal an EOF by typing CtrlD on *nix or CtrlZ on Windows.
getchar takes input one character(byte) at a time. so when you input '-1' it is treated as a character array input and first getchar takes input only '-' and second one takes input '1'. Thus you are not getting your desired output. Also putchar is designed to print one character at a time. So it might not work properly too. You can change your code following way to make it work.
int c;
while(scanf("%d", &c)!=EOF) { //to ensure there is some input value as scanf will return EOF when input stream finishes.
printf("%d\n", c);
if(c == EOF) {
printf("c is equal to EOF\n");
break;
}
}

Converting char to Int with getchar() extra numbers

I want to convert a char to an int. However when I use the usual way of
convertedInt = c - '0';
I get an extra negative number when printing the results. For instance this code with the input 654 produces the output:
while (c != '\n'){
c = getchar();
convertedInt = c - '0';
printf("%d\n", convertedInt);
}
//Output
4
5
6
-38
I don't think it has anything to do with the getchar because if I just print the char without converting it I get the expected output.
You are testing before reading the character. Try this:
int c;
while ((c = getchar()) != '\n' && c != EOF) {
convertedInt = c - '0';
printf("%d\n", convertedInt);
}
Note that getchar() can return EOF in the event of an error, or if the user signals EOF from the keyboard, and so c should be tested for this value to avoid a possible infinite loop.
In the code from the question, it appears that the controlling expression of the while statement tests the value of c uninitialized the first time. This leads to undefined behavior. Later, when the last digit is read and printed, c is tested again and found not to be \n. Then getchar() is called and c has a value of 10, the decimal value of the newline character in ASCII. So, convertedInt gets the value 10 - 48, or -38. Then c is tested a final time; now it is equal to \n, and the loop is terminated.
First of all, getchar returns an int that normally contains a character code in the lowest byte. The reason that it returns an int is that it has to be able to return a value for EOF that is distinct from any possible unsigned char value. EOF is used to indicate the end of the input and is not meant to be treated like a character input. On many systems, EOF has the value -1.
The value you are seeing is '\n' - '0' == 10 - 48 in ASCII.
Here is a common idiom for handling the undesirable inputs from getchar():
while((c = getchar()) != EOF && c != '\n') {
if(c >= '0' && c <= '9') {
convertedInt = c - '0';
printf("%d\n", convertedInt);
}
}
A similar check can be acheived by including #include <ctype.h> and changing the condition of the if statement to if(isdigit(c)).
When you do getChar(), you are checking it for \n later, but you are subtracting '0' first. Replace with this
while(1){
c = getchar();
if(c == '\n')
break;
convertedInt = c - '0';
printf("%d\n", convertedInt);
}

Why it ignores the second character

I have this code:
#include <stdio.h>
#include <ctype.h>
int main()
{
char x;
printf("Program shows your name and check if the first letter is capital");
while (scanf_s("%c", &x) !=1 || getchar() !='\n')
{
if (islower(x))
{
printf("Name begins with a capital letter\n");
while (getchar() != '\n')
;
}
else
{
printf("%c", x);
}
break;
}
while ((x = getchar()) != EOF)
{
printf("%c", x);
}
return 0;
}
For example:
When I type "Matthew" the result is "Mtthew". Whats wrong? I have no clue.
I tried to change almost everything in first "while" but i think the problem is not there. Any ideas?
The function getChar() removes a character from the input stream, so that it is no longer upon it. By using it within your conditional statement, it is:
Getting the character from the stream (a.k.a: removing it)
Comparing it, and finally
Discarding it (without having saved it somewhere)
If you refactor your code to consider this, then I believe your mystery character will return :-)
Change the first while to
while ((x = getchar()) != EOF && x != '\n')
EDIT: And change char x to int x because EOF isn't guaranteed to be representable by a char.
Your program worked without skipping a character when the following changes were made: (refer to comments in-line)
int x; //change to int for use with getchar()
printf("Program shows your name and check if the first letter is capital");
while (scanf("%d", &x) !=1 || getchar() !='\n')
^ //changed to d for int
But the comment made in #J.Murray's answer about getchar() eating a character is valid. So although your program worked for me, there are some input sequences for which it will not.
Note: The reason for using int as opposed to char is that getchar() can return EOF, which == -1. A char cannot contain a -1.
Certainly incorrect use of scanf_s("%c", &x)
The fscanf_s function is equivalent to fscanf except that the c, s, and [ conversion specifiers apply to a pair of arguments (unless assignment suppression is indicated by a *). The first of these arguments is the same as for fscanf. That argument is immediately followed in the argument list by the second argument, which has type rsize_t and gives the number of elements in the array pointed to by the first argument of the pair. (C111dr §K.3.5.3.2 6)
scanf_s("%c", &x, (rsize_t)1)
Other issues may exist.

printf vs putchar - different output

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.

Resources