c, gets(),fgets() - c

char s1[100];
char s2[100];
gets(s1);
fgets(s2,sizeof(s2),stdin);
printf("%d,%d\n",strlen(s1),strlen(s2));
after run, I input "abcd" two times,
and the result i got is : 4,5
why is that?

From the gets / fgets man page:
The fgets() function reads at most one less than the number of characters
specified by n from the given stream and stores them in the string s.
Reading stops when a newline character is found, at end-of-file or error.
The newline, if any, is retained. If any characters are read and there
is no error, a `\0' character is appended to end the string.
The gets() function is equivalent to fgets() with an infinite n and a
stream of stdin, except that the newline character (if any) is not stored
in the string. It is the caller's responsibility to ensure that the
input line, if any, is sufficiently short to fit in the string.
fgets keeps the newline, which is character number 5, but gets doesn't.
Also, get into a habit of using fgets always, as it is impossible to prevent buffer overflows when using gets.

Because fgets returns the string with '\n' at the end while gets not.

From the gets() man page:
The gets() function is equivalent to fgets() with an infinite n and a stream of stdin, except that the newline character (if any) is not stored in the string.

Related

Why this fgets() behaving in a weird way?

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.

How Can I Scan a File in a Way That Doesn't Discard Newlines

I am relatively new to C programming, but, from what I understand, fscanf skips any whitespace when scanning input for every type beside characters. What other means do I have to scan integers while keeping any newline character that may be attached to them within the file (as I actually want to do something with these newline characters)?
You can use fgets in the following format:
char *fgets(char *s, int size, FILE *stream);
and as it's man page says:
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.
It will read a newline character, however it will stop reading after that and terminate with the null character.
You could use fcanf(file,"%[^\n]") which takes everything up to user hit enter.

Why fgets takes cursor to next line?

I have taken a string from the keyboard using the fgets() function. However, when I print the string using printf(), the cursor goes to a new line.
Below is the code.
#include<stdio.h>
int main()
{
char name[25];
printf("Enter your name: ");
fgets(name, 24, stdin);
printf("%s",name);
return 0;
}
And below is the output.
-bash-4.1$ ./a.out
Enter your name: NJACK1 HERO
NJACK1 HERO
-bash-4.1$
Why is the cursor going to the next line even though I have not added a \n in the printf()?
However, I have noticed that if I read a string using scanf(), and then print it using printf() (without using \n), the cursor does not go to next line.
Does fgets() append a \n in the string ? If it does, will it append \0 first then \n, or \n first and then \0?
The reason printf is outputting a newline is that you have one in your string.
fgets is not "adding" a newline --- it is simply reading it from the input as well. Reading for fgets stops just after the newline (if any).
Excerpt from the manpage, emphasis mine:
The fgets() function reads at most one less than the number of characters specified by size from the given stream and stores them in the string str. Reading stops when a newline character is found, at end-of-file or error. The newline, if any, is retained. If any characters are read and there is no error, a `\0' character is appended to end the string.
An easy way to check if there's a newline is to use the help of one of my favorite little-known functions --- strcspn():
size_t newline_pos = strcspn(name, "\r\n");
if(name[newline_pos])
{
/* we had a newline, so name is complete; do whatever you want here */
//...
/* if this is the only thing you do
you do *not* need the `if` statement above (just this line) */
name[newline_pos] = 0;
}
else
{
/* `name` was truncated (the line was longer than 24 characters) */
}
Or, as an one-liner:
// WARNING: This means you have no way of knowing if the name was truncated!
name[strcspn(name, "\r\n")] = 0;
Because if there is a '\n' in the read text it will be taken by fgets(), the following was extracted from the 1570 draft §7.21.7.2 ¶ 2
The fgets function reads at most one less than the number of characters specified by n
from the stream pointed to by stream into the array pointed to by s. No additional
characters are read after a new-line character (which is retained) or after end-of-file. A
null character is written immediately after the last character read into the array.
I highlighted by making bold the part which says that the '\n' is kept by fgets().

fgets adds \0 or \n at the end of the input?

I've some doubts about fgets. From what I know, it adds "\n" at the end of the string, and not "\0". So if I write this code:
fgets(buff,2,stdin);
printf("%s",buff);
So fgets reads two characters, I give as input "y", so buff should be "y\n". I'd expect printf to print y and add a line, while it prints "y" without adding a line. Can you explain why?
char * fgets ( char * str, int num, FILE * stream );
Reads characters from input stream and stores them as a C string into str until (num-1) characters have been read or either a newline or the end-of-file is reached, whichever happens first.
A newline character makes fgets stop reading, but it is considered a valid character by the function and included in the string copied to str.
A terminating null character ('\0') is automatically appended after the characters copied to str.
It must terminate the string, so yes it will always add '\0' at the end. However, fgets might not always add the newline, if it doesn't fit. I recommend this reference page for fgets.
According to man page it clearly given :
char *fgets(char *s, int size, FILE *stream);
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() adds \0 at the end but it reads the string with \n if it exists in the file
i have such thing after reading string:
"guitar\n\0\U00000004\xd5..."
my file had string with word "guitar" and \n after it
so, as u see it read the word with "\n" and added "\0" to the string

Why is my output formatted, i.e. '\n' automatically in fgets?

Here is my code
#include<stdio.h>
int main()
{
FILE* fp;
int i;
fp=fopen("newfile","r");
if(fp==NULL)
{
printf("hhaha");
return 0;
}
char str[20];
for(i=0;i<2;i++)
{
fgets(str,20,fp);
printf("%s",str);
}
return 0;
}
Now if my newfile has text
my name
is xyz
then how come when i print the two lines are printed in two newlines?
where does the newline character come from?
fgets sets the pointer to a char * representing the line of the file including the \n at the end of the line. (As is the case with most strings, it will also be '\0' terminated)
A file with this:
Thisismyfile
Will have this from fgets:
This\n\0,is\n\0,my\n\0,file\n\01
1The final value may not be include \n. That will depend on whether it is a \n terminated file.
from man fgets
gets() reads a line from stdin into the buffer pointed to
by s until either a terminating newline or EOF, which it replaces with
'\0'. No check for buffer overrun is performed
(see BUGS below).
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.
and thus fgets behaviour is different from what you might expect
From the linux man page for fgets():
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 thebuffer.
fgets() includes the newline when reading into the string - that's how fgets() is defined to work. From the standard:
No additional characters are read after a new-line character (which is retained) or after end-of-file.

Resources