As I was following an example from a book,
#include <stdio.h>
main()
{
int c;
c = getchar();
while (c != EOF) {
putchar(c)
c = getchar();
}
}
I thought it would make more sense to read character first, then print it so switched putchar and getchar around
c = getchar();
putchar(c);
now when I run it, what happens is the first output of putchar is missing the first character of c? This is the output:
kingvon#KingVon:~/Desktop/C$ ./a.out
first letter is missing?
irst letter is missing?
but now it is not
but now it is not
This is interesting, why does this happen?
Because you're getting a character before the loop. That means c is equal to that first character, but in the loop it's getting every character after that. So,
Get: f
Start the loop
Get: i
Print: i
And so on
The problem is that now you're not printing the character that you read with getchar() before the loop, so you don't print the first character.
If you want to do the getchar() first, put it into the while() condition.
#include <stdio.h>
main()
{
int c;
while ((c = getchar()) != EOF) {
putchar(c)
}
}
Related
This question already has answers here:
How to enter the value of EOF in the terminal
(4 answers)
Closed 2 years ago.
I recently started learning C from The C Programming Language by Brian Kernighan and Dennis Ritchie. In that book, there's a whole subsection (1.5.1, 2nd Ed.) where the authors create a file copying program (but I am using this as a text (input by the user) copying program). Their code basically looks like this
#include <stdio.h>
int main()
{
int c;
c = getchar();
while (c != EOF) {
putchar(c);
c = getchar();
}
}
This code works fine when run, but the program never stops. The program keeps on waiting for inputs and goes on copying them, endlessly, never terminating. Now I wanted to create a program where this endless copying does terminate. To do so, I tweaked the code a little bit. Here's my code
#include <stdio.h>
int main()
{
int c;
c = getchar();
while (c != EOF) {
putchar(c);
c = getchar();
}
return 0;
}
I thought that explicitly writing return 0; at the end might do the job, but it seems that the output doesn't change at all. I also tried using if-else conditions and looping them as follows
#include <stdio.h>
int main()
{
int c;
c = getchar();
while (1) {
if (c != EOF){
putchar(c);
c = getchar();
}
else
return 0;
}
}
But the program didn't change at all in this case as well.
My question is that how do I change the code so that my program ends just after copying once (or, even better, generalising it to copying n times)?
Here, it is important for me to clarify what I mean by "once" (or "n times" for that matter). When I use the command prompt (I use Windows) to run the compiled file, the program expects an input. I enter the input through my keyboard, and then press Enter to see the reproduced input. After this, the program again expects me to enter some input. I don't want this to happen. I want the program to end by itself after it copies my input once. This is what I mean by "once" (and the above definition can easily be extended for "n times" as well).
#anatolyg and #Jabberwocky have suggested the use of \n (new line escape character) to make the program work. But this solution fails when the input contains linebreaks, for example
my code does
not work so
I am asking
for help here
Copying this into the command prompt as the input, and using the program suggested by the above two users yields only my code does as the output, which is not what I wanted as an output. Is there any way I can make this program work for text blocks with linebreaks and also make it stop after one input (in this case, the whole text block is just one input)?
After interacting with the other people here, I have come to realise that my definition of "one input" or "once" is quite vague, unclear and not at all concrete. Thus it is nothing but expected that C cannot do what I want it to do. I am accepting the answer which suggests to use the new-line escape character as a signal to terminate the program, because that is the closest to what I had in my mind. Thank you all.
Your return 0 won't make any difference as the execution will stay in the while until c becomes EOF. So you need to make c equal to EOF. Try ctrl-D or ctrl-Z depending on OS.
My question is that how do I change the code so that my program ends just after copying once (or, even better, generalising it to copying n times)?
Introduce a counter like:
#define MAX_INPUTS 10
...
int cnt = 1;
while (c != EOF && cnt < MAX_INPUTS) {
putchar(c);
c = getchar();
++cnt;
}
For starters this loop
while (c != EOF) {
putchar(c);
c = getchar();
}
is not endless. There is a condition in the while loop that if it is not satisfied the loop terminates.
To generate the output of the function getchar equal to EOF you should enter the key combination Ctrl + c in Windows or Ctrl + d in an Unix system.
Adding a return statement either in the body of the loop or after the loop does not principally influence on the program control flow.
Pay attention to that the return statement in main may be omitted. From the C Standard (5.1.2.2.3 Program termination)
1 If the return type of the main function is a type compatible with
int, a return from the initial call to the main function is equivalent
to calling the exit function with the value returned by the main
function as its argument;11) reaching the } that terminates the main
function returns a value of 0.
So for example these two programs
int main( void )
{
return 0;
}
and
int main( void )
{
}
are valid and equivalent.
Since you want to read only one line of input, you can terminate the loop on the end-of-line character '\n'.
c = getchar();
while (c != '\n') {
putchar(c);
c = getchar();
}
If you use a Windows terminal to enter data to your program, this will be enough. If you redirect the input to your program, so that it comes from a file, it will read the file up to the first newline character. However, if the file contains no newline character, your program will get EOF at end of file. So the terminating condition should also check for EOF.
c = getchar();
while (c != '\n' && c != EOF) {
putchar(c);
c = getchar();
}
If you want to read the first n lines from the file/terminal, you need a counter. Then your code will become a bit more complicated, and I think an endless loop with exits in the middle would be a better implementation.
int line_counter = 0;
int max_lines = 5;
while (1) {
int c = getchar();
if (c == EOF)
break;
putchar(c);
if (c == '\n')
{
++line_counter;
if (line_counter == max_lines)
break;
}
}
Another method for separating between inputs is with an empty line. This redefines input format to have "paragraphs" of text. This will complicate the code a little more - it should also hold the previous character it read. To detect an empty line, which marks the end of a paragraph: if both previous and current character are end-of-line characters, the paragraph of text has just ended.
int record_counter = 0;
int max_records = 5;
int prev_c = '\n';
while (1) {
int c = getchar();
if (c == EOF)
break;
putchar(c);
if (prev_c == '\n' && c == '\n')
{
++record_counter;
if (record_counter == max_records)
break;
}
prev_c = c;
}
Ypur latest edit suggests you might want something like this:
#include <stdio.h>
int main()
{
int c;
c = getchar();
while (1) {
if (c != EOF && c != '\n') { // '\n' is End of line (Enter)
putchar(c);
c = getchar();
}
else
return 0;
}
}
or simpler:
int main()
{
do
{
int c = getchar();
if (c != EOF && c != '\n') { // '\n' is End of line (Enter)
putchar(c);
}
else
{
return 0;
}
} while (1);
}
This code works fine when run, but the program never stops.
This is not true, if you don't satisfy the condition of the while statement:
while (c != EOF)
the program will terminate.
Now how you can send EOF to the input?
Depends. Which stdin operation are you trying to EOF? If stdin is terminalinput just press control-D. If the ONLY thing you want to send is EOF, use echo -n | (your program). If you are sending it FROM your C program, you are pretty much stuck with exiting from the program, at which point the state of its stdout will be EOF, which will in turn be reflected in whichever stdin it was redirected to. I'm pretty sure you can't just send EOF from within C without getting a hold of an underlying buffer, which aren't standardized, and therefore would leave you with some dirty programming to do.
Another solution is check in or some digitable character in the while condition for example:
#include <stdio.h>
int main()
{
int c;
c = getchar();
while (c != EOF && c!= 'A') {
putchar(c);
c = getchar();
}
}
in this case if you digit "A" the program will ends up.
The function getChar() in this case is always waiting for the new character, and in this case c is never to get the EOF value. You can set a character to finish (for example 'e' to exit) or you can count with a counter as you say to exit the loop. Do not use while(1) because is not a good practise.
I have been experimenting with getchar(), putchar() and have been trying to use EOF. Below is the snippet of code I have been experimenting with.
#include <stdio.h>
int main(void)
{
int c;
c = getchar();
while(c != EOF)
{
putchar(c);
printf("\n");
printf("%d\n", EOF);
c = getchar();
}
return 0;
}
Input: -
a
Expected output: -
a //Due to putchar()
-1 //Value of EOF
//Now the cursor should come in next line and wait for next character.
Output getting in real time: -
a
-1
-1
//Cursor waiting for next character.
I am not able to comprehend the reason why the output is showing -1 two times.
Your code comment says
//Now the cursor should come in next line and wait for next character.
But the second loop doesn't wait. It reads the newline that was already entered, and this is shown by the extra blank line in the output.
After the first input before the loop
c = getchar();
the input buffer contains the new line character '\n' that corresponds to the pressed key Enter.
So in the while loop there are outputted
a
and
-1
due to the statement
printf("%d\n", EOF);
After that this statement in the loop
c = getchar();
reads the new line character that is present in the input buffer. So again this statement
printf("%d\n", EOF);
outputs
-1
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...
I am reading a book called C Programming Language 2nd Edition. There it teaches a program called character counting. But according to the output it does not.It just takes the character and does nothing.
This is the first version:
#include <stdio.h>
#include <stdlib.h>
main() {
int c, nl;
nl = 0;
while ((c = getchar()) != EOF)
if (c == '/n')
++nl;
printf("%d\n", nl);
}
So when i type my sentence and press Ctrl+Z to satisfy EOF it gives me zero:
I am a good person
CTRL+Z
0
Press any key to return
It is supposed to count lines and being a beginner I could not understand.
Although the immediate problem is a simple case of replacing '/n' with '\n' (i.e. escaping n for the newline character which is what the backslash does), the fact that your code compiles and runs is due to the C99 standard:
6.4.4.4p10: "The value of an integer character constant containing more than one character (e.g., 'ab'), or containing a character or
escape sequence that does not map to a single-byte execution
character, is implementation-defined."
'/n' is a character array consisting of the forward slash and the letter n.
Once you've fixed that, you then will need to make changes to count characters as opposed to just newline characters.
Apparently the implementation is supposed to count only the number of newline characters, not the number of total characters, as implemented in the if(c=='\n') condition. The program returns 0 on your input as it does not contain a newline character.
It looks as if you're missing a set of {} brackets:
#include <stdio.h>
#include <stdlib.h>
main()
{
int c, nl;
nl = 0;
while((c = getchar()) != EOF)
{ // <- This starts the block to be repeated
if (c == '\n')
{ // <- This is just to keep the code 'safe' ...
++nl;
} // <- ... as is this
} // <- This ends the block to be repeated
printf("The number of New Line characters entered was %d\n", nl);
}
might be that the program want to know if the next char is not an end of a line ( '\n') so you'll need:
#include <stdio.h>
#include <stdlib.h>
main() {
int c, nl;
nl = 0;
while ((c = getchar()) != EOF)
if (c != '\n')
++nl;
printf("%d\n", nl);
}
this will count the number of characters, but there are others escape characters such as '\t' and so i'm not quite sure what the program is supposed to do, but i think that in your book you'll find some more description clarifying that part
for counting the number of lines simply change '/n' to '\n' as you probably know by now
CODE 1:
#include <stdio.h>
int main()
{
int c;
while ((c = getchar()) != EOF)
putchar(c);
return 0;
}
CODE 2:
#include<stdio.h>
main( )
{
int c,d;
c=getchar();
d=getchar();
putchar(c);
putchar(d);
}
1) If
Input : bo
Output : bo
I got to know this in 2nd program that it stores both in variables c and d but where does it stores them in 1st program.
2)Pl. explain the working of first program why it repeats any word despite of its length that is more than one character.
3) From book i got to know that EOF is encountered whenever I enter or there is some error but even if I press enter this program doesn't stops but it prints nextline character again.
For question one, it stores them in c (but only one at a time). The code, better indented, is:
while ((c = getchar()) != EOF)
putchar(c);
so you can see that, for each character input into c, it outputs it as well. Keep in mind that syntax is the short form for:
c = getchar();
while (c != EOF) {
putchar(c);
c = getchar();
}
so you can see each iteration of the loop gets the next character.
The second question, I assume you're asking why it works for any length input. That's because it doesn't care about the length. It's simply storing and echoing each individual character.
You could give it a billion characters if you like.
As to the third, you get back EOF for an error or end of file (CTRL-Z at the start of a line for Windows, usually CTRL-D under UNIX-like operating systems, unless you have some weird terminal characteristics set up).
If you were only interested in a line, you could use something like:
while ((c = getchar()) != '\n')
putchar(c);
putchar ('\n');
while ((c = getchar()) != EOF)
Reads the value from stdin until it encounters EOF(End Of File). So the same variable c stores different values read in different iterations.
In the second example only two variable ( of char type ) are there so it can read and store only two characters.