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

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

Related

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().

strlen() returns the string count with the null terminator

normally, strlen() does not count the null terminator at the end of the string. But, below code prints the string count with the null terminator. Can anyone explain me why? Thanks
char str2[100];
printf("\nEnter a string: ");
fgets (str2, sizeof(str2), stdin);
printf("\n%d",strlen(str2));
I am assuming the preceding fgets prompt picked up the newline character.
For example:
You put in apple.
Internally your string was stored as apple\n\0.
strlen then returned 6 for apple + '\n'
The fgets() function accepts the input when a newline character(Enter key when using stdin) is encountered, and the newline character \n is considered a valid character by the function and included in the string copied to your str2.Hence when you pass it as a parameter to strlen() it gives one more than the original number of characters in your string to account for the additional \n character.
If you want the original number of characters or don't want a \n to be added, use the gets() function as it doesn't copy the newline character.And further, you only need to pass the string as argument,no need to pass the stream (stdin) as the default stream for gets() is stdin.
char str2[100];
printf("\nEnter a string: ");
gets(str2);
printf("\n%d",strlen(str2));
Here you have used fgets() function to take input. When you take input by fgets() function then an additional new line character('\n') will be added with your sting. suppose your input is : "hello" . after typing this sting you must press ENTER key for which new line character will be added with your string. Hence its seems to you that strlen() counts the null terminator. But if you take input using scanf() function it will not add additional new line character('\n') when ENTER is pressed. So you will see the exact number of character you string contains. Run the following code to see my explanation.
#include<stdio.h>
#include<string.h>
void main()
{
char str2[100];
printf("\nEnter a string: ");
scanf("%s",str2);
//fgets (str2, sizeof(str2), stdin);
printf("\n%d",strlen(str2));
}
as stated by others, the fgets() will read the newline(\n) character and store it in your array.
after every call to fgets() I always use strcspn() to search the array/pointer to find the newline character and replace it with the null character.
char str2[100];
printf("\nEnter a string: ");
fgets (str2, sizeof(str2), stdin);
//new line of code to replace '\n' with '\0'
str2[strcspn(str2, "\n")] = '\0';
printf("\n%d",strlen(str2));
fgets() reads until \n is encountered.
If the user enters anshul then str2 will contain anshul\n\0.
strlen() will return 7 because strlen() searches until it finds the NULL('\0') character.
gets(s) does not include the '\n' when you hit the enter key after being done entering the string.But, fgets() does include the '\n' while reading from a file.
As per the man page(use: man fgets) on linux terminal,
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.

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.

c, gets(),fgets()

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.

Resources