i have a piece of code in C .But i am not able to understand its output
#include<stdio.h>
main()
{
char a1[20];
char a2[30];
char a3[40];
scanf("%s",&a1);
gets(a2);
fgets(a3,sizeof(a3),stdin);
printf("%d,%d,%d\n",strlen(a1),strlen(a2),strlen(a3));
}
When i enter my input like
amit
singh
output comes out to be 4,0,6 and fgets doest not allow me to enter any string ,i am able to enter only 2 inputs?
input is "amit\nsingh\n"
the scanf consumes "amit" (and writes that into a1)
the gets consumes "\n" (and writes empty string to a2)
the fgets consumes "singh\n" (which it writes to a3)
The output is correct.
Do not EVER use gets!
http://pubs.opengroup.org/onlinepubs/9699919799/functions/fscanf.html
http://pubs.opengroup.org/onlinepubs/9699919799/functions/gets.html
http://pubs.opengroup.org/onlinepubs/9699919799/functions/fgets.html
scanf() takes amit and stores it in array a1.
Since functions of the scanf() family leave the newline character in the input buffer and gets() reads up to a newline character (which it finds immediately), it stores an empty string into a2.
So the call to fgets() reads singh into a3. fgets() puts also the newline character into the target variable - this is why you see 6 characters as string length for a3.
Since there are no more input commands, no 3rd line is read.
scanf leaves a '\n' in the stream which is read by gets.
gets doesn't count \n in the length. Hence you get a 0 there.
Then your fgets reads "singh" and as it does take into account the newline character, it outputs 6.
Have a look at the following references for better understanding:
http://www.cplusplus.com/reference/clibrary/cstdio/fgets/
http://www.cplusplus.com/reference/clibrary/cstdio/gets/
Related
I would like to have a better understanding of using fgets() and stdin.
The following is my code:
int main()
{
char inputBuff[6];
while(fgets(inputBuff, 6, stdin))
{
printf("%s", inputBuff);
}
return 0;
}
Let's say my input is aaaabbbb and I press Enter. By using a loopcount, I understand that actually the loop will run twice (including the one I input aaaabbbb) before my next input.
Loop 1: After I have typed in the characters, aaaabbbb\n will be stored in the buffer of stdin file stream. And fgets() is going to retrieve a specific number of data from the file stream and put them in inputBuff. In this case, it will retrieve 5 (6 - 1) characters at a time. So that when fgets() has already run once, inputBuff will store aaaab, and then be printed.
Loop 2: Then, since bbb\n are left in the file stream, fgets() will execute for the second time so that inputBuff contains bbb\n, and then be printed.
Loop 3: The program will ask for my input (the 2nd time) as the file stream has reached the end (EOF).
Question: It seems that fgets() will only ask for my keyboard input after stdin stream has no data left in buffer (EOF). I am just wondering why couldn't I use keyboard to input anything in loop 2, and fgets() just keep on retrieving 5 characters from stdin stream and left the excess data in the file stream for next time retrieval. Do I have any misunderstanding about stdin or fgets()? Thank you for your time!
The behavior of your program is somewhat more subtle than you expect:
fgets(inputBuff, 6, stdin) reads at most 5 bytes from stdin and stops reading when it gets a newline character, which is stored into the destination array.
Hence as you correctly diagnose, the first call reads the 5 bytes aaab and prints them and the second call reads 4 bytes bbb\n and prints them, then the third call gets an empty input stream and waits for user input.
The tricky part is how stdin gets input from the user, also known as console input.
Both console input and stdin are usually line buffered by default, so you can type a complete line of input regardless of the size of the buffer passed to fgets(). Yet if you can set stdin as unbuffered and console input as uncooked, the first fgets() would indeed read the first 5 bytes as soon as you type them.
Console input is an intricate subject. Here is an in depth article about its inner workings: https://www.linusakesson.net/programming/tty/
Everything is there in manual page of fgets() whatever you are asking. Just need to read it properly, It says
char *fgets(char *s, int size, FILE *stream);
fgets() reads in at most one less than sizecharacters
from stream and stores them into the buffer pointed to by s. Reading
stops after an EOF or a newline. If a newline is read, it is
stored into the buffer. A terminating null byte (aq\0aq) is stored
after the last character in the buffer.
If input is aaaabbbb and in fgets() second argument you specified size as 6 i.e it will read one less 5 character and terminating \0 will be added so first time inputBuff holds aaaab and since still EOF or \n didn't occur so next time inputBuff holds bbb\n as new line also get stored at last.
Also you should check the return type of fgets() and check if \n occurs then break the loop. For e.g
char *ptr = NULL;
while( (ptr = fgets(inputBuff, 6, stdin))!= NULL){
if(*ptr == '\n')
break;
printf("%s", inputBuff);
}
fgets() does only read until either '\n' or EOF. Everything after that will be left in stdin and therefore be read when you call fgets() again. You can however remove the excess chars from stdin by for example using getc() until you reach '\0'. You might want to look at the manpages for that.
I'm using strstr() function to search a string given by the user in some other string.
Problem is that when I use fgets() to take input, the strstr() function is giving zero(false) even if the string entered by user is there.
For Example:
char search[20]; //MAX size of search term is 20 bytes
puts("Enter search term: ");
fgets(search,20,stdin); //suppose user enters: photographer (12 characters long)
if(strstr("I'm no photographer but I can picture us together",search))
puts("Found!");
else
puts("No luck!");
Output: No luck!
Even tough "photographer" is there in the string
However, if I use scanf() to take search input.
scanf("%19s",search); //like this
Output: Found!
Why is this happening ?
This is happening because fgets() stores a trailin newline \n at the end of the string read. So the string you read in search is basically "photographer\n"
Either use scanf() or overwrite a null character \0 on the newline.
To overwrite on the newline, you can do something like this
l=strlen(search)-1;
if(search[l]=='\n')
search[l]='\0';
from the manual:
fgets() reads in at most one less than size characters from stream and stores them into the buffer pointed to by s. Reading stops after an EOF or a newline. If a newline is read, it is stored into the buffer. A terminating null byte ('\0') is stored after the last character in the buffer.
beware that none of those functions are safe to use because they don't check the size of the buffer.
I am using gcc (Ubuntu 4.8.2-19ubuntu1) 4.8.2
I am writing a very simple script to take string as input and print the same with the some custom message. First user enters the T(no. of times to take string) and then takes input by fgets.. I used this&this as reference. I am getting a very strange output ie fgets is adding some extra new lines and even loop is not working properly for T=2 it is asking input only once. Can anybody explain me what is wrong with snippet. Thanks in advance!
#include<stdio.h>
#include<string.h>
int main()
{
int T;
scanf("%d",&T);
while(T--){
char str[100]={""};
int i;
printf("Hello\n");
fgets(str,80,stdin);
i = strlen(str)-1;
if(str[i]=='\n')
str[i]='\0';
printf("World\n");
printf("%s\n",str);
}
return 0;
}
Please see the image reference for T=2, even T=2 it is taking string only once and order of printing statement is also not as expected.
This is because your scanf() call
scanf("%d",&T);
does not consume the new line character \n accompanied by your input.
When you input T, your input is 2Enter.
scanf() consumes the 2, sees \n and stops consuming, leaving \n in the input buffer.
When the fgets() gets called, it sees the \n in the buffer and treats this as the input.
To solve this, you have a few choices (in decreasing order of my subjective preference):
Use fgets() to get the first input, then parse it using strtol() to get T.
Add an extra fgets() after the scanf().
Add getchar() to consume one extra character. This works if you are certain that exactly one \n will be present after the input. So for example it won't work if you type 2SpaceEnter. Alternatively, you may use while(getchar() != '\n'); after the scanf() to consume everything up to a new line, but this may cause problems if an empty line is a valid input to your later fgets() calls.
If your implementation supports it, you may use fpurge(stdin) or __fpurge(stdin).
And, very importantly, do not use fflush(stdin) unless your implementation clearly defines its behavior. Otherwise it is undefined behavior. You may refer to this question for more details. Also, note that the fpurge() and fflush() methods may not work correctly if your input can be piped into the program.
This line
scanf("%d",&T);
reads the input until the first non-numeral is found, which is newline. Then fgets() reads that newline for its first input.
I suggest using fgets() to read the number too.
fgets(str,80,stdin);
sscanf(str, "%d", &T);
With your first call to scanf you allow the user to input an integer for the number of loops. They do so, and use a carriage return to signal the end of input. At this point scanf reads the integer, but leaves the end-of-line (\n) in the stream..
So when you call fgets, fgets gets from the stream until it reaches the first newline -- in you code, on the first loop, this is the very first character it encounters.
If you discard the newline before calling fgets, you should get your desired results. You can do this, for example by changing your first three lines to:
int T;
char newline;
scanf("%d%c",&T, &newline);
Although there are probably stylistically superior ways of doing this.
You have a newline character in the input stream when you press "enter" after typing 2 for the first scanf. This is consumed by fgets() initially, hence it prints nothing (You replace the newline by \0).
In the next line, your input is read and echoed after World because you are printing it after it.
I'm new to C, I have lines of code look like this:
char user[16];
fgets(user,16,stdin);
I typed "zeyang" on the keyboard, and I have another code:
char pwname[1000];
pwname="zeyang";
Then I use strcmp to compare user and pwname:
strcmp(user, pwname);
The return value is a negative number, I expect it to be 0, because they are all "zeyang". Why it isn't 0?
fgets includes the typed newline if there's room. You're comparing "zeyang\n" with "zeyang". From the fgets(3) man page:
The newline, if any, is retained.
The first string coming from stdin contains an additional newline character.
The problem is that the sentence you enter will be terminated by a new line character. (I guess you pressed ENTER when you have finished to insert characters. :D
In this case I would use strncmp :
strncmp(user,pwname,strlen(pwname));
This code won't compare the new line character.
When allocating Strings on the heap (with 'malloc'),
and initializing them with the standard input (using 'fgets),
an unnecessary newline appears between them when trying to print them (with 'printf' and %s formatting).
for example:
main()
{
char *heap1;
char *heap2;
heap1=malloc(10);
heap2=malloc(10);
fgets(heap1,10,stdin);
fgets(heap2,10,stdin);
printf("%s%s",heap1,heap2);
}
with input "hi1\nhi2" produces "hi1\nhi2".
compiled using gcc 4.3.4 for Debian.
fgets also reads the '\n' (newline) character. You should remove it if you don't want it to print like that.
heap1[strlen(heap1) - 1] = '\0';
after you read the contents of heap1.
fgets returns the newline as part of the string.
See man 3 fgets. Specifically:
fgets() reads in at most one less
than size characters from stream and
stores them into the buffer pointed
to by s. Reading stops after an
EOF or a newline. If a newline is
read, it is stored into the buffer.
A '\0' is stored after the last
character in the buffer.
fgets is probably appending the newline. Try trimming the string you get back from fgets.