C program on Mac works unexpected - c

I have this little program:
#include <stdio.h>
int main(){
int c;
while(c != EOF){
printf("Enter character\n");
c = getchar();
printf("Character: %c\n", c);
}
printf("FIN\n");
return 0;
}
The output of the terminal seems odd, because the while loop gets executed twice after a character was entered:
Enter character
a
Character: a //This should be the last output after a char was entered, but the loop gets executed a second time without waiting for a keyboard-input:
Enter character
Character:
Enter character
In the terminal I'm compiling and running the code like this:
gcc main.c
./a.out
What am I doing wrong?
Thanks for the answers, It's the lf entered by enter .... It's so obvious :D

You are entering 2 characters, the 'a' and a LF.
The while test is not made until both have been processed.

As soon as you press enter, a newline character gets added to the input stream. So your program actually reads two characters: a and \n. This newline character is read by getchar() and assigned to c in the second iteration and you can actually see it being printed as an empty line. Before printing c, you could use a break statement to get out of the loop: if (c == '\n') break;
If you enter abc, you will see the empty line is printed after c.

For starters your program has undefined behavior because you are using uninitialized variable c in the condition of the while loop
int c;
while(c != EOF){
//...
The function getchar also reads white space characters as for example the new line character '\n' that is placed in the buffer after pressing the Enter key.
Another problem is that you are checking the variable c after reading and outputting it
while(c != EOF){
printf("Enter character\n");
c = getchar();
printf("Character: %c\n", c);
}
Instead of getchar you should use scanf as for example
char c;
while ( scanf( " %c", &c ) == 1 )
{
//...
}
Pay attention to the blank before the conversion specifier %c. This blank means that white space characters will be skipped.

Related

Undefined behaviour of scanf() in a do-while loop

I'm currently learning C by a book "C Programming a modern approach" and encountered this code. When I tried to run it, after typing consecutive characters like 'abc' and hitting Enter (new line), nothing was printed. Please explain what is going on here.
char ch;
do {
scanf("%c" , &ch);
} while (ch != '\n');
printf("%c", ch);
You're asking the user to input a character using scanf. This is happening in a loop until the user inputs a '\n' or newline character (the same as pressing the enter key), which is when the loop will break.
Your print statement will then print the character in the variable ch, which at that point will be '\n' (since this variable just stores one character, the last one you typed).
This newline character will probably be invisible when you run your program so you may not be seeing it. You can add another print statement after the loop and if that print statement starts at a newline, you know that the '\n' was printed on the previous line.
Something like:
#include <stdio.h>
int main()
{
char ch;
do
{
scanf("%c" , &ch);
} while (ch != '\n');
printf("%c", ch);
printf("I should show up on a newline");
return 0;
}
The code you provided reads characters from the input using the scanf() function and stores them in the variable ch until a newline character (\n) is encountered. After that, the program prints the last character that was read, which is the newline character.
The reason you are not seeing any output when you enter characters followed by a newline character is because the printf() statement is only executed after the loop has finished running. So, the program is waiting for you to enter a newline character to terminate the loop and print the last character that was read.
If you want to see the characters you enter, you can add a printf() statement inside the loop, like this:
char ch;
do {
scanf("%c" , &ch);
printf("%c", ch);
} while (ch != '\n');
This will print out each character as it is read from the input, so you can see what you're typing. Happy coding :)
When I tried to run it, after typing consecutive characters like abc and hitting Enter (new line), nothing was printed.
Well with the posted code, if the loop even finishes, the last byte read by scanf("%c", &ch) and stored into ch is the newline character. Hence printf("%c", ch) outputs this newline and it seems nothing is printed but something is, the newline which is invisible on the terminal but does move the cursor to the next line.
You can make this more explicit by changing the printf call to this:
printf("last value: '%c'\n", ch);
Note however that the posted code is not a recommended way to read the contents of the input stream:
scanf("%c", &ch) may fail to read a byte if the stream is at end of file. Failure to test this condition leads to undefined behavior (ch is unmodified, hence stays uninitialized if the input stream is an empty file) or to an infinite loop as ch may never receive a newline.
this code is a typical example of a do / while with a classic bug. It would be much better to write the code using getchar() and a while loop.
Here is a modified version:
#include <stdio.h>
int main(void) {
int c; // must use int to distinguish EOF from all valid byte values
int count = 0; // to tell whether a byte was read at all
char ch = 0; // the last byte read
// read all bytes from the input stream until end of file or a newline
while ((c = getchar()) != EOF && c != '\n') {
ch = (char)c;
count++;
}
if (count == 0) {
printf("no characters entered: ");
if (c == EOF) {
printf("end of file or read error\n");
} else {
printf("empty line\n");
}
} else {
printf("last character on line is '%c'\n", ch);
if (c == EOF) {
printf("end of file or input error encountered\n");
}
}
return 0;
}

Program to replace a letter with another in C

I wrote a program to replace a letter in a string. Although it has no error, the output is not as expected. Please help me with it.
#define _CRT_SECURE_NO_DEPRECATE
#include<stdio.h>
#include<string.h>
void replace(char s,char d);
char a[100];
int main()
{
char b,r;
printf("enter the string\n:");
gets(a);
printf("enter the the letter to be replaced\n:");
scanf("%c", &b);
printf("enter the letter to be replaced with\n:");
scanf("%c", &r);
replace(b,r);
}
void replace(char s, char d)
{
int i,f=0;
for (i = 0; a[i] != '\0'; i++)
{
if (a[i] == s)
{
a[i] = d;
f = 1;
}
}
if (f == 0)
{
printf("letter not found");
}
}
Output
enter the string
:hello every one
enter the the letter to be replaced
:e
enter the letter to be replaced with
:letter not found
I wanted to replace e with o but I am not able to give the input for word to be replaced
UPDATE
Use this loop to get rid of the input buffer problem when using scanf
but I am not sure how to implement it on my program need help
void
clear(void)
{
while ( getchar() != '\n' )
;
}
The scanf() function skips over initial whitespace characters when you read in strings using the %s specifier, but it does not do this when your read chars with the %c specifier. The gets() function that you use (which you should never ever ever use ever) reads through the newline, and discards it. So your first call to scanf() has a clean input stream. When you call scanf() the first time, a value is read into the variable b, but the trailing newline is left behind in the input stream. Then, when you try to read the next value, scanf() picks up this newline, instead of the value that you want to enter.
One fix for this is to discard any unwanted characters from the input stream like this:
while (getchar() != '\n')
continue; // discard unwanted characters
You can also test for the EOF character in the conditional expression if you really want to be careful. One virtue of this approach is that, no matter how many characters the user enters at your second prompt, only the first is taken, and the remaining characters through the newline are discarded. Since there is nothing left in the input stream, scanf() has to wait for the user to enter something at your third prompt. You should place this code after each call to scanf() to make sure that the input stream is clear.
Now, gets() is a terrible and unsafe function begging for buffer overflows, because it doesn't check to see if there is enough memory allocated for the string it is getting. Instead, use fgets(). This function takes an argument that specifies the maximum number of characters to read, including the null-terminator. fgets() also reads the newline character into the string, so you have to dispose of that yourself if you don't want it. Here are the modifications you need to make:
int i = 0;
...
char b,r;
printf("enter the string\n:");
fgets(a, 100, stdin);
while(a[i] != '\n' && a[i] != '\0') // remove newline
++i;
a[i] = '\0';
printf("enter the the letter to be replaced\n:");
scanf("%c", &b);
while (getchar() != '\n')
continue; // discard unwanted characters
printf("enter the letter to be replaced with\n:");
scanf("%c", &r);
while (getchar() != '\n')
continue; // discard unwanted characters
replace(b,r);
printf("%s\n", a);
...
I added a final printf() to display the changed string.

getchar() not working in c

getchar() is not working in the below program, can anyone help me to solve this out. I tried scanf() function in place of getchar() then also it is not working.
I am not able to figure out the root cause of the issue, can anyone please help me.
#include<stdio.h>
int main()
{
int x, n=0, p=0,z=0,i=0;
char ch;
do
{
printf("\nEnter a number : ");
scanf("%d",&x);
if (x<0)
n++;
else if (x>0)
p++;
else
z++;
printf("\nAny more number want to enter : Y , N ? ");
ch = getchar();
i++;
}while(ch=='y'||ch=='Y');
printf("\nTotal numbers entered : %d\n",i);
printf("Total Negative Number : %d\n",n);
printf("Total Positive number : %d\n",p);
printf("Total Zero : %d\n",z);
return 0 ;
}
The code has been copied from the book of "Yashvant Kanetkar"
I think, in your code, the problem is with the leftover \n from
scanf("%d",&x);
You can change that scanning statement to
scanf("%d%*c",&x);
to eat up the newline. Then the next getchar() will wait for the user input, as expected.
That said, the return type of getchar() is int. You can check the man page for details. So, the returned value may not fit into a char always. Suggest changing ch to int from char.
Finally, the recommended signature of main() is int main(void).
That's because scanf() left the trailing newline in input.
I suggest replacing this:
ch = getchar();
With:
scanf(" %c", &ch);
Note the leading space in the format string. It is needed to force scanf() to ignore every whitespace character until a non-whitespace is read. This is generally more robust than consuming a single char in the previous scanf() because it ignores any number of blanks.
When the user inputs x and presses enter,the new line character is left in the input stream after scanf() operation.Then when try you to read a char using getchar() it reads the same new line character.In short ch gets the value of newline character.You can use a loop to ignore newline character.
ch=getchar();
while(ch=='\n')
ch=getchar();
When you using scanf getchar etc. everything you entered stored as a string (char sequence) in stdin (standard input), then the program uses what is needed and leaves the remains in stdin.
For example: 456 is {'4','5','6','\0'}, 4tf is {'4','t','f','\0'} with scanf("%d",&x); you ask the program to read an integer in the first case will read 456 and leave {'\0'} in stdin and in the second will read 4 and leave {''t','f',\0'}.
After the scanf you should use the fflush(stdin) in order to clear the input stream.
Replacing ch = getchar(); with scanf(" %c", &ch); worked just fine for me!
But using fflush(stdin) after scanf didn't work.
My suggestion for you is to define a Macro like:
#define __GETCHAR__ if (getchar()=='\n') getchar();
Then you can use it like:
printf("\nAny more number want to enter : Y , N ? ");
__GETCHAR__;
I agree that it is not the best option, but it is a little bit more elegant.
Add one more line ch = getchar();
between scanf("%d",&x); and ch = getchar();
then your code work correctly.
Because when you take input from user, in this time you press a new line \n after the integer value then the variable ch store this new line by this line of code ch = getchar(); and that's why you program crash because condition can not work correctly.
Because we know that a new line \n is also a char that's why you code crash.
So, for skip this new line \n add one more time ch = getchar();
like,
ch = getchar(); // this line of code skip your new line when you press enter key after taking input.
ch = getchar(); // this line store your char input
or
scanf("%d",&x);
ch = getchar(); // this line of code skip your new line when you press enter key after taking input.
pieces of code work correctly.

Why getchar() behaves differently?

I found getchar() is behaving differently in some situations.
In the following code, it devours the newline character in the input.
#include <stdio.h>
// copy input to output; 1st version
int main()
{
int c;
while((c = getchar()) != EOF)
{
putchar(c);
}
}
The input and output in the terminal looks like this.
j
j
b
b
asdf
asdf
ashdfn
ashdfn
It exactly duplicates the input and ignores the newline character in the input due to return key I pressed after each input.
However, if there is a printf() statement inside the loop, it no longer ignores the newline character.
#include <stdio.h>
// copy input to output; 1st version
int main()
{
int c;
while((c = getchar()) != EOF)
{
putchar(c);
printf("\n");
}
}
The input and output in the terminal looks like this.
j
j
b
b
asdf
a
s
d
f
ashdfn
a
s
h
d
f
n
It echoes the newline character, which was used to be ignored in the previous situation.
Could you tell me why there is a difference and how does it behave exactly?
In first case, it reads one character - getchar() and prints it - putchar(), so there is not newline or '\n' after each character. The newline is the one you entered with enter key press.
While in 2nd case, you have printf("\n") which prints new line after every character is printed - through putchar().
getchar reads a character at a time. When you input 123 and press Enter key then this input goes to the C standard buffer with one more character \n (generated on pressing Enter key). Now from there getchar reads a character at a time and rest of the characters in input stream left behind for the next call of getchar.
Now, to answer your question I am going to explain it with a simple program;
#include <stdio.h>
int main(void)
{
int c, b;
c = getchar();
putchar(c);
b = getchar();
putchar(b);
b = getchar();
putchar(b);
}
Giving the input 123, the input stream of the buffer would be
123\n
Having four chars; '1', '2', '3' and '\n'.
First getchar reads 1 and then putchar output this character. Now the buffer have 23\n. Next call of getchar reads 2 and next to it will read 3. Finally \n is left behind for the next call of getchar. Hence the output will be
123
Now inputting the character one by one as in your first example. On passing j you are passing j\n to the buffer. First call of getchar will read j and is putchar output this on screen. Next call will read \n and putchar print this out on the screen but the effect is not seen to you until the read of next character. On third call of getchar, b is read but this time it goes to the next line on the output screen. This is because of the \n character read previously by getchar. Finally \n is left behind in the buffer for next call of getchar.
Now coming to your first example
#include <stdio.h>
// copy input to output; 1st version
int main()
{
int c;
while((c = getchar()) != EOF)
{
putchar(c);
}
}
This will work similarly as stated above.
Now coming to your second example
#include <stdio.h>
// copy input to output; 1st version
int main()
{
int c;
while((c = getchar()) != EOF)
{
putchar(c);
printf("\n");
}
}
This is printing two newlines after each of character but supposed to print a single character, right?
It is printing what it should! This is because it is printing a newline not only for characters j, b...etc but also for newline character \n. Take simple input j\n, b\n.
On first call of getchar, j is read and printed with a newline by printf then on next call \n is printed along with a newline and the output looks like
j
//The newline printed by printf along with j
//The newline printed by printf along with \n
b
It is not echoing the newline. getchar() is buffered input. Also, getchar() is of echoing type. The control will wait until you press Enter key from the keyboard.
If you do
abcdeEnter
since getchar() is of echoing type, it reads single char from the buffer until it encounters newline and the same char is echoed. The putchar() prints the received char on the terminal. The newline which is being output is entered by you when you press Enter.
The same thing happens in the second case, but one extra line is added because of printf.
Check http://ideone.com/H2kqBq
#include <stdio.h>
int main()
{
int c;
while((c = getchar()) != EOF)
{
putchar(c);
printf("\n");
}
}
The output is not as you have specified here.
The behaviour of getchar() and putchar() is consistent
in my opinion what is happening is, when you enter a character at the terminal, suppose 'a' and then press Enter, actually two characters are getting buffered in the input stream
'a' and '\n'
so the loop runs twice to putchar these two characters, that is why your next input starts at new line
(you may check that by using:
if(c!='\n') putchar(c);
this will cause the '\n' not to be printed and you would input on the same line)
when you add printf("\n"), it will also be printed twice because the loop will still run two times as there are two characters in the input stream.
so you will get
a
(newline from printf)
in the first iteration of the loop
(newline from input buffer)
(newline from printf)
in the second iteration

getchar does not stop when using scanf

I have a difficulty understanding getchar(). In the following program getchar works as expected:
#include <stdio.h>
int main()
{
printf("Type Enter to continue...");
getchar();
return 0;
}
However, in the following program, getchar does not create a delay and the program ends:
#include <stdio.h>
int main()
{
char command[100];
scanf("%s", command );
printf("Type Enter to continue...");
getchar();
return 0;
}
I have the following weired workaround, which works, but I don't understand why:
#include <stdio.h>
int main()
{
char command[100];
int i;
scanf("%s", command );
printf("Type Enter to continue...");
while ( getchar() != '\n') {
i=0;
}
getchar();
return 0;
}
So my questions are:
1. What is scanf doing? Why does scanf do this ?
2. Why is my work around working?
3. What is a good way to emulate the following Python code:
raw_input("Type Enter to continue")
The input is only sent to the program after you typed a newline, but
scanf("%s", command );
leaves the newline in the input buffer, since the %s(1) format stops when the first whitespace character is encountered after some non-whitespace, getchar() then returns that newline immediately and doesn't need to wait for further input.
Your workaround works because it clears the newline from the input buffer before calling getchar() once more.
To emulate the behaviour, clear the input buffer before printing the message,
scanf("%s", command);
int c;
do {
c = getchar();
}while(c != '\n' && c != EOF);
if (c == EOF) {
// input stream ended, do something about it, exit perhaps
} else {
printf("Type Enter to continue\n");
getchar();
}
(1) Note that using %s in scanf is very unsafe, you should restrict the input to what your buffer can hold with a field-width, scanf("%99s", command) will read at most 99 (sizeof(command) - 1)) characters into command, leaving space for the 0-terminator.
Whitespace is a delimiter for 5y3 %s format specifier, and newline is regarded as whitespace, so it remains buffered. Console input is normally line oriented, so a subsequent call to getchar() will return immediately because a 'line' remains buffered.
scanf("%s", command );
while( getchar() != '\n' ){ /* flush to end of input line */ }
Equally if you use getchar() or %c to get a single character you normally need to flush the line, but in this case the character entered may itself be a newline so you need a slightly different solution:
scanf("%c", ch );
while( ch != '\n' && getchar() != '\n' ){ /* flush to end of input line */ }
similarly for getchar():
ch = getchar();
while( ch != '\n' && getchar() != '\n' ){ /* flush to end of input line */ }
The sensible thing to do of course is to wrap these solutions into stand-alone specialised input functions that you can reuse and also use as a place to put common input validation and error checking code (as in Daniel Fischer's answer which sensibly checks for EOF - you would normally want to avoid having to duplicate those checks and error handling everywhere).
I'd rather first use fgets and then use sscanf to parse the input. I have been doing this stuff like this for a long time and the behaviour has been more predictable than using plain scanf.
Well, I have something easier: add another getchar() ... problem solved!!
after taking command input flush the stdin.
fflush(stdin);
but flushing a input stream results in undefined behavior (though Microsoft's C library defines the behaviour as an extension).

Resources