Why when we are declaring the function fgets() we need to put -1 string from the original char? like this:
#include <stdlib.h>
#include <stdio.h>
int main ()
{
char string[15];
fgets(string,14,stdin); // < the original variable has 15 strings, but in fgets() we need to set 14, why?
printf("%s\n", string);
return 0;
getchar();
}
I'm a beginner in C, so i'm having this doubt in my mind
CodePudding user response:
You don't need to. fgets
takes three arguments.
- A C string buffer to read into.
- A count of characters.
- A file stream to read from.
It reads at most count - 1
characters into the buffer, thus leaving room for the null terminator every C string needs.
As a side note: your call to getchar
falls after the return
and is thus completely pointless as control flow will never reach it.
CodePudding user response:
There is no need to subtract 1 from the array length for the size argument to fgets()
.
The second argument tells fgets
the length of the array pointed to by the first argument so fgets()
only writes inside the buffer boundaries. fgets()
will read at most one less byte from the stream than the length of the destination array and write a null terminator so make the array a C string.
Since sizeof(char)
is 1
by definition, it is idiomatic in C to pass the size of the array as sizeof(string)
, but only do this if string
is an actual array, not a pointer.
Unless the stream pointer it in error or at end of file, the string read by fgets()
will be null terminated. You should test the return value of fgets()
to avoid reading the array in case of failure to read a string from the stream.
Here is a modified version:
#include <stdio.h>
int main() {
char string[15];
while (fgets(string, sizeof string, stdin)) {
printf(">>%s<<\n", string);
}
printf("Bye\n");
return 0;
}
Now let's run the program and do some testing:
If you type a short string
Hello!
followed by the Enter key, you will see 2 lines of output:>>Hello! <<
fgets()
read the string, including the trailing newline into thestring
array andprintf
outputs it, preceded by>>
and followed by<<
and a newline, producing 2 lines in one call.If you type a longer string
I am testing this function relentlessly
followed by the Enter key,fgets()
will read at most 14 bytes at a time and only the last chunk will have the trailing newline:>>I am testing t<< >>his function r<< >>elentlessly <<
Finally, if the input does not have a trailing newline, eg:
Yes!
followed by Ctrl-DCtrl-D, the arraystring
will not have a newline at the end either and the next call tofgets()
will returnNULL
:>>Yes!<< Bye!
CodePudding user response:
Why when we are declaring the function fgets() we need to put -1 string from the original char?
I believe you are talking about the use of
buffer[strlen(buffer) - 1] = 0;
after using fgets()
to fill in buffer
, with the purpose of removing* the expected \n
from the string. Not when "declaring the function" but after the call.
Well, this is wrong.
Example
#include <ctype.h>
#include <stdio.h>
int main(void)
{
char buf[5] = {0};
const int n = sizeof(buf);
printf("Enter up to %d bytes: ", n);
char* p = fgets(buf, n, stdin);
while ((p != NULL) && (*p != '\n'))
{
printf("Buffer: ");
for (int i = 0; i < n; i = 1)
if (isprint((int)*(buf i)))
printf("%c ", *(buf i));
else
printf("0x%0X ", *(buf i));
printf("\n\nEnter up to %d bytes: ", n);
p = fgets(buf, n, stdin);
}; // while()
return 0;
}
This program reads a string from stdin
using fgets
, buffer size is set to 5. After the read the 5 bytes are shown. When not printable they are displayed in HEX. 0x0A is the code for \n
Running
Enter up to 5 bytes: 12
Buffer: 1 2 0xA 0x0 0x0
Enter up to 5 bytes:
SO>
And there is a newline after the 12, at buf[2]
but
Enter up to 5 bytes: 1234
Buffer: 1 2 3 4 0x0
Enter up to 5 bytes:
SO>
Here we have no \n
since all 4 bytes were used and the last holds the mandatory 0
, the terminating NULL
for the string.
And the '\n'
are left for the next read. The program finishes since an ENTER
at the beginning of the string ends the loop.
Same if the user enters all 5 proposed bytes, as in
Enter up to 5 bytes: abcde
Buffer: a b c d 0x0
Enter up to 5 bytes: Buffer: e 0xA 0x0 d 0x0
Enter up to 5 bytes:
And the second call reads "5\n"
. This time the program does not end, since the '\n'
is on the second byte.
So...
fgets()
will keep the '\n'
at the end of the string as long as there is space for it. If all bytes are taken the remaining data is left on the input buffer.
fgets
returns a pointer
As you see in the manual, fgets()
returns a pointer to the buffer or NULL
in case of error or end of file. In case of error errno
is set.
If fgets
reads nothing the buffer is not touched at all, so every day many many sudent's programs hangs because the program does not check the returned pointer and keeps using the same data over and over, after error or EOF
.