This was my own experiment to understand what goes under the hood, what does this program mean to the compiler?
main()
{
int c;
printf("%d\n",c);
printf("%d ", getchar());
while ((c == getchar()) != EOF){
putchar(c);
}
}
When I say c must equal getchar() (c == getchar()), does it not proceed through the while loop? Now I am really confused of my own code, of what c must mean!
Also, in this code:
main()
{
int c;
c = getchar()
while ((c = getchar()) != EOF)
putchar(c);
}
if we modify the int c to int c = getchar(), why cannot we somply write like this:
while (c != EOF)(
putchar(c);
c = getchar();
}
The compiler should know from the previous statement that c = getchar(), why have to write the statement again? Sorry, if I am confused.
while ((c==getchar()) != EOF) {
...
}
is a while loop. It evaluates the condition for each iteration of the loop and terminates only if the condition is false.
In your case, the condition is:
(c==getchar()) != EOF)
which is a nonsensical expression, but let's examine it anyway:
First, the program will evaluate:
getchar()
This grabs a keystroke from standard input. The value of the expression is the value of the key.
Then:
c==getchar()
This takes the result of getchar() and compares it to whatever is currently in c. In your first program, c is uninitialized, so its value is indeterminate. If c had a defined value, then c==getchar() would evaluate to either true or false. Since c had no defined value, c==getchar() also has no defined value.
Now the program evaluates:
(c==getchar())
Which would still be true or false, except that in your case it is undefined.
The program next considers:
(c==getchar()) != EOF
That is, it compares the true-false value to EOF; this makes no particular sense, and in your case we still have the undefined behavior of an uninitialized c.
In sum, if c were initialized, the expression would fetch a key from standard input and then compare either true or false to EOF. As I said, it is a nonsensical expression.
You're saying you want to look under the hood? Great! Let's dive in :)
while ((c == getchar()) != EOF)
As others have noted, this should be while ((c = getchar()) != EOF). The reason you do assignment (=) rather than equality testing (==) is because you're actually rolling two lines of code into one: c = getchar(); and while(c != EOF). So if the current character being read is k, the program evaluates it in a way kind of like this:
while ((c = getchar()) != EOF)
while ((c = 'k') != EOF)
while (('k') != EOF)
while ('k' != EOF)
while (1) // true
And it has the convenient side effect that c still has k inside for whatever you're planning on doing.
The other problem is here:
int c;
printf("%d\n",c);
printf will complain because you don't have anything assigned to c yet. It's been "declared", but not "initialized." It can't print something that's not there - and if it can, it would surely print something you don't want.
You have an extra equal sign that you need to remove:
while ((c == getchar()) != EOF){
should be
while ((c = getchar()) != EOF){
Here is what is happening. When (c == getchar()) is executed, to begin with c is uninitialized, so it has some garbage value. That garbage value is compared to the next character in the input stream, to see if they are the same. The result of the comparison is going to be 0 (if they are different) or 1 (if they are same). The latter is very unlikely, but it is theoretically possible that by some lucky (?) chance, the garbage value does happen to match the next character in the input stream.
That 0 or 1 is then compared to see whether it matches EOF. Well, EOF is going to be some negative value; that's what it is by definition. Obviously 0 or 1 will never match any negative value, so your loop will be infinite.
As for your second code fragment:
c = getchar();
while ((c = getchar()) != EOF) {
You're not checking whether the first character is EOF, as the value of c after the first getchar() will be immediately replaced by the assignment in the while condition. Assuming that there is a non-EOF first character, your code will work.
As for your third code fragment:
c = getchar();
while (c != EOF) { // corrected your typo of ( instead of {
putchar(c);
c = getchar();
}
The reason why you have to write c = getchar() again inside your while loop is to update the value of c with the second and subsequent characters in the input stream. Otherwise, it will always compare the current value of c, which is the first character in the input stream, to EOF, and this too will be an infinite loop unless the first character does happen to be EOF.
The most concise way of accomplishing what you want is:
int c;
while ((c = getchar()) != EOF)
putchar (c);
... just like your second code fragment, minus the extra line that does the first getchar() and assigns it to c.
c == getchar() != EOF means
c == getchar() is true if c and the result returned from getchar() are the same.
c == getchar() will always be not equal to EOF (since neither true not false equals EOF) so the program should infinite loop printing the character that randomly showed up here since you never initialized c int c;.
Related
I am learning C from the book "The C Programming Language";
my question is about something I observed while trying to reformulate with few lines of code regarding input and output:
why is it needed to give the getchar() function a value of a certain integer in order to have it store all the text in the input?
For example with this code putchar() is printing all that I type;
int c;
while ((c = getchar()) != EOF)
putchar(c)
But, why isn't it the same if I write:
while (getchar() != EOF)
putchar(getchar());
In the latter case, for example, if I write "okok", the program is then printing "kk".
I think the reason is within some property of getchar(), that I wasn't able to get;
for example, if I write a character counting program, and I want to exclude new lines, I also observed that it's working if I write it as:
int nc, c;
nc = 0;
while ((c = getchar()) != EOF)
if (c != '\n')
++nc;
printf("%d", nc);
But it's not able instead to distinguish correctly the '\n' when using getchar() directly instead of c integer:
while ((c = gethar()) != EOF)
if (getchar() != '\n')
++nc;
printf("%d", nc);
My purpose it is just to understand, as I wouldn't like to learn this just by memory, and in the book it is written that getchar() is working using int values, so I wonder if there is something that I missed about properties of getchar() despite reading several times, also searching in different questions in stack overflow regarding the getchar() topic.
When you write
while (getchar() != EOF)
putchar(getchar());
It always
reads one character and checks it for EOF,
reads one (another) character and prints it,
repeats.
Therefore, in your "okok" example, the odd 'o' characters are read, compared to EOF and discarded, and only the even 'k's make it through.
If you wanted to print all of the input characters, you would have to restructure your code. For example, to call getchar() once, save the return value to a variable, then use the already read value twice - check it for EOF and print it.
while (1) { /* loop forever (until break is called) */
int ch = getchar();
if (ch == EOF)
break;
putchar(ch);
}
getchar() function gets one char from the input and returns it.
while (getchar() != EOF)
putchar(getchar());
You have used the getchar() function two times.
For the input 'okok'
'o' will be returned in while (getchar() != EOF).
'k' will be returned in putchar(getchar());
Since you have written putchar() here it will get the char 'k' and prints it.
And again the process continues and prints only 'k'.
So the output will be 'kk'
To get the value 'okok' and print it try
do
{
char c=getchar();
if(c!=EOF)putchar(c);
}while(c!=EOF);
I'm new to C programming, I'm practicing while loop using getchar(). But I'm confusing about these two while loop code.
This is the first code:
char c;
c=getchar();
while(c != 'X')
c=getchar();
printf("Thanks for finally inputting an X.\n");
I undestand that this function will printf until the user enter X.
Here is the second code:
char c;
while((c=getchar()) != 'X');
printf("Thanks for finally inputting an X");
Which did the same thing as the last function, but I don't really understand while((c=getchar()) != 'X'); It means to me that when the user enters other characters than X, it will be true and print the sentence.
Look closely at the while in the second snippet:
char c;
// here ----------------v
while((c=getchar()) != 'X');
printf("Thanks for finally inputting an X");
There is a ; immediately after the while. This means that the body of the loop is empty. So the loop will continue to run just the condition until it is false, i.e. when c is equal to 'X'.
Both approaches are equivalent, but the second is more concise and uses less code:
Evaluating the condition (c = getchar()) != 'X') first calls getchar() to read a byte from the standard input, store in into c, which by the way should be defined as an int, and compares this byte with 'X', continuing the loop until the user finally types an X (followed by a return) because the body of the while loop is an empty statement.
The main problem with this approach is the program does not test for EOF, so it will perform a costly infinite loop if the standard intput reaches the end of file without ever reading an X.
Here is a better alternative:
int c;
while ((c = getchar()) != EOF) {
if (c == 'X') {
printf("Thanks for finally inputting an X\n");
break;
}
}
To avoid the confusing syntax while((c=getchar()) != 'X'); some programmers would use an empty block:
while ((c = getchar()) != 'X') {
}
Possiblity with an obnoxious comment:
while ((c = getchar()) != 'X') {
/* do nothing */
}
I personally prefer a redundant continue:
while ((c = getchar()) != 'X')
continue;
Note also that this syntactic issue is also present in other languages inspired by C: C++, java, javascript, C#, Objective C, etc.
These two code snippets are equivalent in behavior.
In order to understand the second snippet, you need to remember that what exists in the inner parentheses in this case, will be evaluated first.
So, this:
while((c=getchar()) != 'X');
will have the expression:
c = getchar()
evaluated first. Now, as you already know, the method getchar will be executed, receive the character the user input, and it will assign it to the variable c.
Now our expression looks like this:
while((c) != 'X');
but since c is just a character, it's surrounding parentheses do not have an effect anymore, and we have right now:
while(c != 'X')
which is the same as the the condition of the while loop in the first code snippet, that you already understand.
Tip: Read about operators precedence, which will help you understand why the parentheses are needed - otherwise you'd get a different, most probably unwanted, behavior.
The reason is that the != operator has higher precedence than the assignment operator. Using parentheses imposes the order of evaluation we desire.
Playing around with code examples from K&R in Codeblocks on Windows 10 (Danish language). The following example works as expected:
#include <stdio.h>
int main() {
char c = 'a';
putchar(c);
}
However, the following prints a series of boxes with question marks, the same number as the number of characters I type:
#include <stdio.h>
int main() {
char c;
while (c = getchar() != '\n') {
putchar(c);
}
}
So it looks like an encoding issue. When run, a command prompt opens with "C:\Users\username\Desktop\filename.exe" in the header, and my username contains the Danish character "å" which is replaced by a "Õ". The command prompt uses the CP 850 character set.
(By the way, I'm not checking if the character equals EOF, since that produces odd results. Pressing enter prints the expected number of boxes, plus one for \n, but it doesn't end the program.)
You are seeing a problem of operator precedence here. As you can see on this chart, = has a lower precedence than !=.
This means that getchar() != '\n' is evaluated first.
To the compiler your code looks like this:
#include <stdio.h>
int main() {
char c;
while (c = (getchar() != '\n')) {
putchar(c);
}
}
Since 'c' is getting an incorrect value (the true/false evaluation of the expression), the output is incorrect, and the program gives the behavior you are seeing, however
#include <stdio.h>
int main() {
char c;
while ((c = getchar()) != '\n') { //<----notice brackets around c=getchar
putchar(c);
}
}
gives the output you are expecting. This illustrates the fact that you should always put brackets around such expressions to be safe.
This line is bad.
while (c = getchar() != '\n')
It should be:
while ((c = getchar()) != '\n')
There are already some correct answers within the scope of the question but there are a couple of wider problems that you need to address.
Firstly getchar() returns an int and it is important that you define the variable that takes the return value as an int so you can differentiate errors and end of file from valid chars.
Secondly, if you receive end of file or there is an error on stdin before the program encounters a \n, your code will loop forever. This is what the man page on my laptop says about getchar()
If successful, these routines return the next requested object from the stream. Character values are returned as an unsigned char converted to an int. If the stream is at end-of-file or a read error occurs, the routines return EOF.
So once getchar() returns EOF it will return EOF all the time. You need to address this in your loop condition:
#include <stdio.h>
int main()
{
int c; // c declared as int
while ((c = getchar()) != EOF && c != '\n'))
{
putchar(c);
}
if (c == EOF)
{
// handle errors and end of file as you see fit
}
}
Edit: You get the boxes because of the lack of parenthesis around the assignment, look at this question for reference as to why you should have parenthesis around an assignment used as a truth value...
Also, there is something else that is also wrong with this program, consider this example:-
For example:
What you actually wanted:-
ABCD
< newline >
What you actually typed:-
ABCD
And since the program didn't find the '\n' anywhere in the code, it leads to undefined behavior since it goes out of bounds to find it...
There are two possible solutions when your input does not contain a '\n':-
Use EOF (Suggested by many since it the best possible solution for accepting every input...)
int main() {
char c;
while ((c = getchar()) != '\n') /* Always remember to put parenthesis around
an assignment in a condition... */
putchar(c);
}
Add a newline to your input:-
int main() {
char c;
// Use fputc to modify input...
fputc('\n', stdin);
while ((c = getchar()) != '\n') /* Always remember to put parenthesis around
an assignment in a condition... */
putchar(c);
}
But, beware! This method will stop at the first iteration of newline it gets, so if you have something outside of the '\n', well it won't be printed...
count = 0;
while ( (c = getchar()) != EOF)
{
if (c != '\t' && c != '\n') continue;
if (c == '\n') break;
if (c == '\t') count++;
}
what is the code mean and the getchar and EOF mean I did not understand
The getchar() standard function reads a character from the standard input stream.
The returned value is of type int (which is "wider" than char) since it can also return EOF for when input reading failed, generally because the stream was closed. The token EOF in the code is simply a constant from the header, it can be declared like this:
#ifndef EOF
# define EOF (-1)
#endif
So it's literally just an alias for the integer literal -1 (but I don't think you can rely on the numerical value, use the symbolic name!).
The code loops until EOF is detected, i.e. it loops over all characters readable on its standard input stream, and counts the number of times \t is found.
It can be simplified a lot, the first if is pointless (and the continueis of course mis-spelled).
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);
}