Strlen gives an incorrect output after fgets - c

I read a string using fgets. It prints correctly but if i try to output the length using a strlen or a while until NULL it returns a bad value. Does fgets not end the string with NULL?
char word[256];
fgets(word, sizeof(word), stdin);
while(word[i])
i++;
printf("%d",i);
For the string aba it outputs 40.

Function fgets also includes the new line character in the string. So function strlen counts this symbol.
From the C Standard
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.

The below code outputs proper value:
int main()
{
char word[256];
int i =0;
fgets(word, sizeof(word), stdin);
while(word[i])
i++;
printf("%d\n",i);
}

Related

How to prevent my code to count `\0` as one character? [duplicate]

I read a string using fgets. It prints correctly but if i try to output the length using a strlen or a while until NULL it returns a bad value. Does fgets not end the string with NULL?
char word[256];
fgets(word, sizeof(word), stdin);
while(word[i])
i++;
printf("%d",i);
For the string aba it outputs 40.
Function fgets also includes the new line character in the string. So function strlen counts this symbol.
From the C Standard
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.
The below code outputs proper value:
int main()
{
char word[256];
int i =0;
fgets(word, sizeof(word), stdin);
while(word[i])
i++;
printf("%d\n",i);
}

string length with fgets function in C [duplicate]

This question already has answers here:
Removing trailing newline character from fgets() input
(14 answers)
Closed 6 years ago.
I have a problem. I've tried to see the length of some string after using fgets function. If I enter string under the number of letter which can be in the string (like: the maximum letters in string is 9 and I enter 4 letters), I get length of the string+1. why?
Here's my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char name[10]={0};
printf("enter your name\n");
fgets(name, 10, stdin);
printf("your name is %s and it is %d letters\n", name, strlen(name)); // length problem
return 0;
}
From fgets manual page (https://linux.die.net/man/3/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 terminating null byte (aq\0aq) is stored after the last character in
the buffer.
So it adds '\n' after your 4 letters, returning string_length+1.
From Removing trailing newline character from fgets() input you can add #Tim Čas solution to your code.
The line is still read with the fgets() function and after we remove the newline character.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char name[10] = { 0 };
printf("enter your name\n");
fgets(name, 10, stdin);
printf("your name is %s and it is %d letters\n", name, strlen(name)); // length problem
name[strcspn(name, "\n")] = 0;
printf("NEW - your name is %s and it is %d letters\n", name, strlen(name));
return 0;
}
That outputs:
enter your name
Andy
your name is Andy
and it is 5 letters
NEW - your name is Andy and it is 4 letters
Press any key to continue . . .
Because the end of line character '\n' is included in the string copied into name by fgets() .
If character array has enough space then the standard function fgets also includes the new line character in the array that usually corresponds to the entered key Enter.
You can remove this redundant new line character the following way
name[strcspn( name, "\n" )] = '\0';
after that you will get the expected result of applying function strlen.
As is written in man fgets,
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.
Since you are reading from stdin, fgets(name, 10, stdin) reads at most 9 characters from stdin buffer and appends \0 to the end. It just happens that the new line character \n produced when user hit enter is in the buffer too.
As a sidenote, it is customary (and a good practice) to use sizeof() when specifying size of the array passed to fgets.
fgets(name, (int) sizeof(name), stdin);

What is the difference between getchar/putchar, gets/puts and fgets/fputs (in C)?

I am currently studying input and output in C and I have found out that there are about a billion different ways to get input, such as, getch, getchar, gets and fgets, and the same with output (putchar, puts, fputs, etc.).
All these different methods of I/O are confusing me quite a bit, so I came on here to ask what the basic differences between the aforementioned functions are.
I also wrote a bit of code using these different functions and I commented in how I think they work, based on what I've learnt, but I'm not sure if my understanding is correct. I've read up on them in other places as well, but the explanations are very complicated and don't seem coherent.
So could anyone please tell me if I am using them correctly and if not, how I should use them and what are the main differences between them?
Here is my code:
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <ctype.h>
void individualCharacters()
{
char theChar;
while ((theChar = getchar()) != '~') { // getchar() stores all characters in a line buffer as it is entered until newline is entered
putchar(theChar); // putchar() prints the characters in the line buffer and does not print a newline, line buffering depends on compiler
}
}
void withoutF()
{
char name[50];
printf("What is your name? ");
gets(name); // receives a string until newline is entered, newline is then replaced with string terminator, array limit should not be passed
puts("Hi"); // only prints one string at a time and adds the newline because gets() previously replaces the newline
puts(name);
}
void withF()
{
char name[50];
printf("What is your name? ");
fgets(name, 50, stdin); // does add a newline so the newline takes up one space in the array, it stores input until either newline is entered or array limit is reached
fputs("Hi ", stdout); // does not print a newline but prints the string input up to the array limit
fputs(name, stdout);
}
void main()
{
//sum();
//individualCharacters();
//withoutF();
//withF();
//printRandomString();
}
These are just some functions I wrote that get input and display output in different ways, but I'm having trouble understanding why there are so many different ways of doing so.
If I have made any mistakes using the I/O functions, feel free to tell me so I can make amendments.
Thank you
fgets - reads up to SIZE-1 characters from a specified stream into a buffer, including the trailing newline if there's room. Adds a 0 terminator to the end of the buffer, making it a valid C string:
char buffer[SIZE];
if ( fgets( buffer, sizeof buffer, stdin ) ) // read from standard input
do_something_with( buffer );
else
error();
On success, fgets returns the address of the input buffer. On failure or end-of-file, it returns NULL.
fgetc - reads a single character from the specified input stream and returns it:
FILE *input_stream = fopen( "some_file", "r" );
int c;
while ( (c = fgetc( input_stream )) != EOF )
do_something_with( c );
gets - was deprecated after C99, removed completely from C2011. Like fgets, it would read a sequence of characters from standard input into a buffer and add a 0 terminator, but unlike fgets it did not provide a mechanism to limit input, making it a popular malware exploit. Also, it would not store a trailing newline to the buffer. Using it was guaranteed to introduce a point of failure in your code. Pretend you've never heard of it.
getc - identical to fgetc, except that it may be implemented as a macro.
getchar - reads a single character from standard input:
int c;
...
while( (c = getchar()) != EOF )
do_something_with( c );
fputs - writes a string to the specified output stream:
char str[SIZE];
...
fputs( str, output_stream );
fputc - writes a single character to the specified output stream:
while ( i < strsize )
fputc( str[i], output_stream );
putc - identical to fputc, except that it may be implemented as a macro
putchar - writes a single character to standard output.
getch() is a function that prompts to press a key,in which the character is not echoed back.
In contrast getche() will echo the character back.
gets() will read characters from stdin but is unsafe(use fgets() instead).
getchar() will return the next character it reads from stdin, it's same as calling getc() with stdin as an argument.
fgets() reads characters from a stream (like a file or stdin), and stores them as a C string into str until (num-1) characters have been read or newline or EOF is reached.
putch() writes a character to stdout. It's same as calling putc() with stdout as an argument.
puts() writes a C string pointed by str to stdout and appends a newline character. It starts copying till it reached the null-terminator(\0). Null-terminator is not printed.
fputs() writes a C string pointed by str to the stream, and is essentially like puts()
As for your code,try to avoid using gets(), as it is unsafe and use scanf(), same goes for puts(). Use printf() instead.
Here,give this a read: http://www.cplusplus.com/reference/cstdio/
I know it's C++ reference but the library functions are the same
fgets
char * fgets ( char * str, int num, FILE * stream );
Get string from stream
Reads characters from stream and stores them as a C string into str until (num-1) characters have been read or either a newline or a the End-of-File is reached, whichever comes first.
A newline character makes fgets stop reading, but it is considered a valid character and therefore it is included in the string copied to str.
A null character is automatically appended in str after the characters read to signal the end of the C string.
fputs
int fputs ( const char * str, FILE * stream );
Write string to stream
Writes the string pointed by str to the stream.
The function begins copying from the address specified (str) until it reaches the terminating null character ('\0'). This final null-character is not copied to the stream.
getchar
function
<cstdio>
int getchar ( void );
Get character from stdin.
Returns the next character from the standard input (stdin).
It is equivalent to getc with stdin as its argument.
putchar
function
<cstdio>
int putchar ( int character );
Write character to stdout
Writes character to the current position in the standard output (stdout) and advances the internal file position indicator to the next position.
It is equivalent to putc(character,stdout).
gets: from standard input to memory
puts: from memory to standard input
Example :
#include<stdio.h>
void main( )
{
char name[10];
printf("What is your first and last name?");
gets(name);
puts(name);
}

Using strstr to determine if a given string contains a string with spaces [C]

I'm working through an example of using the strstr() function.
If I input "Pamela Sue Smith", why does the program output ""Pamela" is a sub-string!" and not ""Pamela Sue Smith" is a sub-string!".
#include <stdio.h>
#include <string.h>
void main(void)
{
char str[72];
char target[] = "Pamela Sue Smith";
printf("Enter your string: ");
scanf("%s", str);
if (strstr( target, str) != NULL )
printf(" %s is a sub-string!\n", str);
}
main does not have return-type void but int.
scanf can fail. Check the return-value.
If successful, it returns the number of parameters assigned.
%s only reads non-whitespace, until the next whitespace (thus 1 word).
%s does not limit how many non-whitespace characters are read. A buffer-overflow can be deadly.
Use %71s (buffer-size: string-length + 1 for the terminator)
You swapped the arguments to strstr.
From the manual page for scanf:
“s” — Matches a sequence of non-white-space characters; the next
pointer must be a pointer to character array that is long enough
to hold the input sequence and the terminating null byte ('\0'),
which is added automatically. The input string stops at white
space or at the maximum field width, whichever occurs first.
So, the part “Sue Smith” never makes it to str. You could use fgets which allows you to read a whole line at a time:
if (fgets(str, sizeof str, stdin) == NULL) {
printf("End of file\n");
return;
}
Note that in this case, str contains the terminating end-of-line character. You could do
if (*str != '\0')
str[strlen(str) - 1] = '\0';
to remove it.
(Also, as some others already pointed out, the “haystack” argument to strstr goes first.)

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.

Resources