getchar() won't keep the console open - c

I'm writing this code to compare two strings. The code works, my only problem being keeping the console open after it finishes. Normally, getchar() works like a charm, but in this case it is simply ineffective. I think it's due to the if-else functions. How do I keep the console open?
#include <stdio.h>
#include <string.h>
#define SIZE 50
int main (int argc , char** argv) {
char isim[SIZE];
printf("Adinizi yazin:\n");
scanf("%s", isim);
if(strcmp(isim, "Cihan") == 0)
printf("Hosgeldiniz!\n");
else
printf("Cihan degilsiniz. Lutfen programi terk edin.\n");
getchar();
return 0;
}

Just use two getchar(), one after the other. scanf() doesn't remove the newline character from the input buffer, so first getchar() "eats" that newline. The second getchar() to wait for next input, which will keep the console open.
From scanf() page in cplusplus.com:
the function will read and ignore any whitespace characters encountered before the next non-whitespace character (whitespace characters include spaces, newline and tab characters -- see isspace).
Emphasis by me.

The input is sent to the program after a newline, but
scanf("%s", &isim );
leaves the newline in the input buffer, since the %s format stops when the first whitespace character is encountered after some non-whitespace. getchar() then returns that newline immediately and doesn't wait.
To make your code work, try something like this
scanf("%s", &isim );
while( getchar() != '\n' ){
/* flush to end of input line */
}

#include <stdio.h>
#include <string.h>
#include <conio.h>
#define SIZE 50
int main (int argc , char** argv) {
char isim[SIZE];
printf("Adinizi yazin:\n");
scanf("%s", &isim);
if(strcmp(isim, "Cihan") == 0)
printf("Hosgeldiniz!\n");
else
printf("Cihan degilsiniz. Lutfen programi terk edin.\n");
getch();
return 0;
}

You can use statement: getch(); in conio.h header. getch() not read character in buffer, it read character directly from keyboard. So console will open if you not yet input. getchar() read character from buffer,a newline in your input buffer after scanf() not be read and save in buffer. Then getchar() will read newline and statement stop, console will close.

Related

Why does scanf fail but fgets works?

I am asking the user for input on whether they would like to quit the program or not. There are two snippets. One reads input using the scanf() function, while the second reads input using the fgets() function. Using scanf(), the program goes in an infinite loop. Using fgets(), the program performs as intended. Why does scanf() fail, and fgets() work? How can i correct it so that scanf() will work? Here is the code:
First is with scanf()
#include <stdio.h>
#include <string.h>
int main(void)
{
char yesNo[6];
printf("Enter [quit] to exit the program, or any key to continue");
scanf("%s", &yesNo[6]);
while (strcmp(yesNo,"quit\n") != 0)
{
printf("Enter [quit] to exit the program, or any to continue");
scanf("%s", &yesNo[6]);
}
return 0;
}
Second is with fgets()
#include <stdio.h>
#include <string.h>
int main(void)
{
char yesNo[6];
printf("Enter[quit] to exit the program, or any key to continue: ");
fgets(yesNo, 6, stdin);
while (strcmp(yesNo,"quit\n") != 0)
{
printf("Enter [quit] to exit the program, or any key to continue:");
fgets(yesNo, 6, stdin);
}
return 0;
}
The difference between scanf("%s") and fgets you've to keep in mind is the way they take in input.
%s instructs scanf to discard all leading whitespace characters and read in all non-whitespace characters until a whitespace character (or EOF). It stores all the non-whitespace characters in its corresponding argument, in this case, yesNo, and then leaves back the last whitespace character back into the standard input stream (stdin). It also NUL-terminates its corresponding argument, in this case yesNo.
fgets reads in all input until a newline character ('\n') or until the maximum number of characters to read passed in as the second argument minus one (for the NUL-terminator '\0') has been read (or until EOF) and all this input, including the \n, is stored in its first argument, yesNo here, and it is NUL-terminated.
So, if you have scanf("%s", yesNo); with an input of quit\n, yesNo will contain just quit and the \n will be left in the stdin. Since the strings "quit" and "quit\n" aren't the same, strcmp will not return zero and the while loop will continue to loop.
For fgets(yesNo, 6, stdin); with the input quit\n, yesNo will hold quit\n and the stdin will be empty. strcmp returns zero as both the strings "quit\n" and "quit\n" are equal, and execution comes out of the loop.

Why is my program got into an infinite loop?

I want to scan a line until newline is pressed. I'm aware of gets() function, but I wanted to learn it with scanf(). The problem is, that my program falls into an infinite loop, where it scans the input from user and then infinitely prints it out, where it should print once after each scan. Can anybody explain why is it behaving like this?
#include<stdio.h>
int main()
{
char str[100];
while(str[0]!='\0')
{
scanf("%[^\n]",str);
printf("%s\n",str);
}
}
If you insist on using scanf, then change format specifier:
" %[^\n]"
The space in front will skip any previous "dangling" \n
Also you should initialize the str array before checking the contents of it, better yet use a do-while-loop instead .
Something like this should work
char str[100] = {0};
do
{
scanf(" %[^\n]",str);
printf("%s\n",str);
}
while(str[0]!='q');
Personally I prefer to use fgets(...) in combination with sscanf(...)
Also it is good practice to check the return value of scanf, there is a return value for a purpose.
added another while condition, loops until "q" or "quit"
Since %[^\n] does not accept newline, input is not accepted in the second loop.
Probably, this will do what you want.
#include<stdio.h>
int main(void){
char str[100];
while(1== scanf("%99[^\n]%*c",str)){//%*c consumes newline. Also In case of only newline terminates the loop
printf("%s\n",str);
}
}
BLUEPIXY is absolutely correct. The first return from scanf() is leaving the \n in the input buffer. Subsequent scanf() calls will return right away without reading any characters from stdin because scanf() stops reading on a \n. So a loop ensues. One way to avoid the loop is to read the \n from the input after the call to scanf() as shown below:
#include <stdio.h>
int main()
{
char str[100] = {0};
do
{
scanf("%[^\n]",str);
getchar();
printf("%s\n",str);
}while( str[0] != '\0' );
}
You seem to be under some false beliefs regarding how input works. So I'm going to explain below.
You don't need to do this in a loop because scanf() doesn't read and return one character at a time when you specify a string format. The input is buffered by the terminal. When you ask scanf() to return a string, the terminal will only send the input string to scanf() when it a newline is received. When that happens scanf() returns the string without the newline.
You'll need to do extra work to turn off terminal line buffering. The below example code shows how to turn off terminal I/O buffering.
#include <stdio.h>
#include <unistd.h>
#include <termios.h>
int main()
{
struct termios old_tio, new_tio;
unsigned char c;
/* get the terminal settings for stdin */
tcgetattr(STDIN_FILENO,&old_tio);
/* we want to keep the old setting to restore them a the end */
new_tio=old_tio;
/* disable canonical mode (buffered i/o) and local echo */
new_tio.c_lflag &=(~ICANON & ~ECHO);
/* set the new settings immediately */
tcsetattr(STDIN_FILENO,TCSANOW,&new_tio);
do {
c=getchar();
printf("%c ",(char)c);
} while(c!='q');
/* restore the former settings */
tcsetattr(STDIN_FILENO,TCSANOW,&old_tio);
return 0;
}

Reading of standard input with fgets not waiting for input

Having this piece of code:
int main(void)
{
char str[4];
do
{
if (fgets(str,sizeof(str),stdin) == NULL)
break;
printf("\n %s \n", str);
}while (strncmp(str,"q\n",sizeof("q\n")));
return 0;
}
if i type more than 4 characters, then two lines are displayed. if i type 123456 and then press enter, does input store ['1','2','\n','\0'] or ['1','2','3','\0']? hen the second time printf is reached if i only press enter key one time?. How i can avoid this behaviour? I would like type 123456 and then get:
1234
The reason why fgets is only reading partial input is because the str array is too small. You need to increase the buffer size of str array.
Also remember that fgets will pick up \n ( enter / return ) that you press after giving your input.
To get rid of the \n do this:
fgets(str,sizeof(str),stdin);
str[strlen(str)-1] = '\0';
There is one MAJOR issue with your while condition ... I am not sure what your are trying to do there but strcmp is used to see if two strings are the same or not ... what you are doing is trying to compare a string to the size of something ...
There are multiple problems in your code:
you do not include <stdio.h>.
fgets() is given a very short buffer: 4 bytes, allowing for only 3 characters to be input at a time, including the '\n'. If you type more characters, they are buffered by the terminal and the standard stream library. It will take several calls to fgets() to read them all, 3 bytes at a time.
Your termination test is bogus: strncmp(str, "q\n", sizeof("q\n")) compares the string read by fgets() with "q\n" upto a maximum number of characters of 3 because sizeof("q\n") counts the q, the \n and the null terminator. You should just use strcmp() for this test.
You print the string with printf("\n %s \n", str);. Note however that a regular line read into str will contain the trailing newline so the printf call will actually output 2 lines.
Here is a modified version:
#include <stdio.h>
#include <string.h>
int main(void) {
char str[80];
while (fgets(str, sizeof(str), stdin) != NULL) {
str[strcspn(str, "\n")] = '\0'; // strip the newline if present
printf("\n %s \n", str);
if (!strcmp(str, "q"));
break;
}
return 0;
}
Try using getc() or fgetc() before using fgets()
When you use a scanf(), you press enter key (newline) which operates as accepting the input and transferring the input from stdin (standard input device) to your program.
scanf() itself does not consume the newline pressed. So, we need something down the code which will accept this newline and prevent this newline from acting as an input to the subsequent fgets(). This newline can be accepted using getc() or fgetc(), which should be written before fgets().
fgetc(stdin); OR getc(stdin);

scanf reading "Enter" key

Why scanf doesn't work when I type "Enter" in the code below?
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char**argv)
{
char *msg = malloc(100*sizeof(char));
do{
scanf("%s",msg);
printf("%s\n",msg);
} while(strcmp(msg,"")!=0);
}
The "%s" in scanf("%s",... skips over leading whitespace (including "Enter" or \n) and so patiently waits for some non-whitespace text.
Best to take in a \n, use fgets().
char msg[100];
if (fgets(msg, sizeof msg, stdin)) {
// success
If you need to use scanf()
int result = scanf("%99[^\n]%*c", msg);
if (result != 1) handle_rump_line_or_end_of_file_or_IOError();
This will scan in 1 to 99 non-\n chars and then append a \0. It will then continue to scan 1 more char (presumably the \n) but not save it due to the *. If the first character is a '\n', msg is not changed and the '\n' remains in stdin.
Edit (2016): To cope with lines that begin with '\n', separate the scan that looks for the trailing '\n'.
msg[0] = '\0';
int result = scanf("%99[^\n]", msg);
scanf("%*1[\n]");
if (result == EOF) handle_end_of_file_or_IOError();
Because of scanf() wait char-string, separated by whitespaces, enters, etc. So, it just ignores ENTERs, and waiting for "real non-empty string". If you want to get empty string too,
you need to use
fgets(msg, 100, stdin);
Scanf looks through the input buffer for the specified format, which is string in this case. This has the effect of skipping your whitespaces. If you put a space between wording, it skips the space looking for the next string, similarly it will skip tabs, newlines etc. See what happens if you put a %c instead. It will pick up the newline because it is searching for a char now, and '\n' constitutes as a valid char.
If you want the same effect while getting whitespace, change it to a %c and remove the newline escape character at the print statement.

Changing the scanf() delimiter

My objective is to change the delimiter of scanf to "\n".
I tried using scanf("%[^\n]s",sen); and works fine for single inputs.
But when i put the same line inside a for loop for multiple sentences it gives me garbage values.
Does anyone know why?
Here's my code:
char sen[20];
for (i=0;i<2;i++)
{
scanf("%[^\n]s",sen);
printf("%s\n",sen);
}
Consider this (C99) code:
#include <stdio.h>
int main(void)
{
char buffer[256];
while (scanf("%255[^\n]", buffer) == 1)
printf("Found <<%s>>\n", buffer);
int c;
if ((c = getchar()) != EOF)
printf("Failed on character %d (%c)\n", c, c);
return(0);
}
When I run it and type in a string 'absolutely anything with spaces TABTABtabs galore!', it gives me:
Found <<absolutely anything with spaces tabs galore!>>
Failed on character 10 (
)
ASCII (UTF-8) 1010 is newline, of course.
Does this help you understand your problem?
It works in this case (for a single line) but if I want to take multiple lines of input into an array of arrays then it fails. And I don't get how scanf returns a value in your code?
There are reasons why many (most?) experienced C programmers avoid scanf() and fscanf() like the plague; they're too hard to get to work correctly. I'd recommend this alternative, using sscanf(), which does not get the same execration that scanf() and fscanf() do.
#include <stdio.h>
int main(void)
{
char line[256];
char sen[256];
while (fgets(line, sizeof(line), stdin) != 0)
{
if (sscanf(line, "%255[^\n]", sen) != 1)
break;
printf("Found <<%s>>\n", sen);
}
int c;
if ((c = getchar()) != EOF)
printf("Failed on character %d (%c)\n", c, c);
return(0);
}
This reads the line of input (using fgets() which ensures no buffer overflow (pretend that the gets() function, if you've heard of it, melts your computer to a pool of metal and silicon), then uses sscanf() to process that line. This deals with newlines, which are the downfall of the original code.
char sen[20];
for (i=0;i<2;i++)
{
scanf("%[^\n]s",sen);
printf("%s\n",sen);
}
Problems:
You do not check whether scanf() succeeded.
You leave the newline in the buffer on the first iteration; the second iteration generates a return value of 0 because the first character to read is newline, which is the character excluded by the scan set.
The gibberish you see is likely the first line of input, repeated. Indeed, if it were not for the bounded loop, it would not wait for you to type anything more; it would spit out the first line over and over again.
Return value from scanf()
The definition of scanf() (from ISO/IEC 9899:1999) is:
ยง7.19.6.4 The scanf function
Synopsis
#include <stdio.h>
int scanf(const char * restrict format, ...);
Description
2 The scanf function is equivalent to fscanf with the argument stdin interposed
before the arguments to scanf.
Returns
3 The scanf function returns the value of the macro EOF if an input failure occurs before
any conversion. Otherwise, the scanf function returns the number of input items
assigned, which can be fewer than provided for, or even zero, in the event of an early
matching failure.
Note that when the loop in my first program exits, it is because scanf() returned 0, not EOF.
%[^\n] leaves the newline in the buffer. %[^\n]%*c eats the newline character.
In any case, %[^\n] can read any number of characters and cause buffer overflow or worse.
I use the format string %*[^\n]%*c to gobble the remainder of a line of input from a file. For example, one can read a number and discard the remainder of the line by %d%*[^\n]%*c. This is useful if there is a comment or label following the number, or other data that is not needed.
char sen[20];
for (i=0;i<2;i++)
{
scanf("%[^\n]s",sen);
printf("%s\n",sen);
getchar();
}
Hope this helps ... actually "\n" remains in stream input buffer... Ee need to flush it out before scanf is invoked again
I know I am late, but I ran into same problem after testing C after a long time.
The problem here is the new line is considered as input for next iteration.
So, here is my solution, use getchar() to discard the newline the input stream:
char s[10][25];
int i;
for(i = 0; i < 10; i++){
printf("Enter string: ");
scanf("%s", s[i]);
getchar();
}
Hope it helps :)
While using scanf("%[^\n]", sen) in a loop, the problem that occurs is that the \n stays within the input buffer and is not flushed. As a result next time, when the same input syntax is used, it reads the \n and considers it as a null input. A simple but effective solution to address this problem is to use:
char sen[20];
for (i=0;i<2;i++)
{
scanf("%[^\n]%*c",sen);
printf("%s\n",sen);
}
%*c gets rid of the \n character in the input buffer.

Resources