fgets() Not Ignoring New Line - c

For my practice assignment I have to use either gets() or fgets().
I chose fgets() as its more secure.
The first input is meant to be able to hold a maximum of 5 characters.
So i gave the char array a size of 6 to accommodate the trailing '\0'.
I found the fgets() issue of it adding a trailing '\n' when you press Enter (using stdin with fgets())
I done a bit of research and found a for loop to try and get rid of it. However, it doesnt seem to be working and i cant for the life of me figure out why.
Its still skipping the next input when i type in 5 characters.
Here is the code:
#include <stdio.h>
#include <string.h>
int main(void)
{
//Declare char arrays
char arcInputString5[6];
char arcInputString10[11];
char arcInputString15[16];
char arcInputString20[21];
int clean1, clean2, clean3, clean4;
// int nStrLen1, nStrLen2, nStrLen3, nStrLen4;
// nStrLen1 = nStrLen2 = nStrLen3 = nStrLen4 = 0;
printf("\nPlease Input String 1 - Max Length 5: ");
//gets(arcInputString5);
fgets(arcInputString5, 6, stdin);
for(clean1 = 0; clean1 < strlen(arcInputString5); clean1++)
{
if(arcInputString5[clean1] == '\n' || arcInputString5[clean1] == '\r')
{
arcInputString5[clean1] = '\0';
break;
}
}
printf("\nPlease Input String 2 - Max Length 10: ");
//gets(arcInputString10);
fgets(arcInputString10, 10, stdin);
printf("\nPlease Input String 3 - Max Length 15: ");
//gets(arcInputString15);
fgets(arcInputString15, 15, stdin);
printf("\nPlease Input String 4 - Max Length 20: ");
//gets(arcInputString20);
fgets(arcInputString20, 20, stdin);
printf("\nThankyou For Your Inputs - They Are Shown Back To You Below\n");
puts(arcInputString5);
puts(arcInputString10);
puts(arcInputString15);
puts(arcInputString20);
printf("\nThe String Lengths For Each Input Are Listed Below");
printf("\n%d", strlen(arcInputString5));
printf("\n%d", strlen(arcInputString10));
printf("\n%d", strlen(arcInputString15));
printf("\n%d", strlen(arcInputString20));
}
Ive tried multiple ways of doing the for loop such as using the number 6 instead of "strlen(arcInputString5)"
Any help would be appreciated.
EDIT:
EXAMPLE INPUT:
asd d
EXAMPLE OUTPUT:
Please Input String 2 - Max Length 10: //skips this
Please Input String 3 - Max Length 15: //this is the next line for input

fgets() reads one character less than the given buffer size from stdin and then
appends a NUL-character. So in your case, with an input buffer of 6 characters,
it reads "asd d" into arcInputString5, and the newline character that terminates the line input is still unread.
The next fgets() then reads (only) this newline character into arcInputString10.
You need a buffer size of (at least) 7 to read the five characters "asd d" including the
newline character from stdin.
The same applies to your other buffers used for fgets().
Added: As Jonathan Leffler correctly commented, a better method is to supply
a "large" input buffer to fgets() and check the actual length of the user input after
reading one line.
You should also note that fgets() returns NULL if no character could be read at all
(end-of-file), so you should check the return value.

Change 6 to 7:
arcInputString5[7];
fgets(arcInputString5, 7, stdin);
You need to give space for the '\n' and '\0' characters.
valter

Call getchar() to retrieve the the newline character from the input stream before asking for the next user input.
I like to use the following simple function for clearing the input stream
void clear() {
while(getchar() != '\n');
}

Related

Output didn't include all of the characters

I was trying to input a string of characters and only output the last and the first character respectively. Below is the code I'm using.
#include<stdio.h>
int main(){
for(int i=0;i<3;i++){
int n; // length of the string
char string[101];
scanf("%d %s", &n, &string);
fflush(stdin); // sometimes I also use getchar();
printf("%c%c", string[n+1], string[0]);
}
printf("\n");
return 0;
}
I'm using for loop because i wanted to input the string 3 times, but when I ran the code the input isn't what I expected. If I input e.g.
5 abcde
output
a //there's space before the a
can you help me tell where I've gone wrong?
input:
5 abcde
6 qwerty
3 ijk
excpeted output:
ea
yq
ki
Few problems in your code:
In this statement
scanf("%d %s", &n, &string);
you don't need to give & operator with string. An array name, when used in an expression, converts to pointer to first element (there are few exceptions to this rule). Also, the size of string array is 101 characters but if you provide input more than 101 characters, the scanf() end up accessing string array beyond its size. You should restrict the scanf() to not to read more than 100 characters in string array when input size is more than that. (keep the remain one character space is for null terminating character that scanf() adds). For this, you can provide width modifier in the format specifier - %100s.
You are not validating the string length input against the input string from user. What happen, if the input string length is greater than or less than the actual length of input string!
fflush(stdin) is undefined behaviour because, as per standard, fflush can only be used with output streams.
I was trying to input a string of characters and only output the last and the first character respectively.
For this, you don't need to take the length of the string as input from user. Use standard library function - strlen(). This will also prevent your program from the problems that can occur due to erroneous length input from user, if that is not validated properly.
Putting these altogether, you can do:
#include <stdio.h>
#include <string.h>
int main (void) {
for (int i = 0; i < 3 ; i++) {
char string[101];
printf ("Enter string:\n");
scanf("%100s", string);
printf("Last character: %c, First character: %c\n", string[strlen(string) - 1], string[0]);
int c;
/*discard the extra characters, if any*/
/*For e.g. if user input is very long this will discard the input beyond 100 characters */
while((c = getchar()) != '\n' && c != EOF)
/* discard the character */;
}
return 0;
}
Note that, scanf(%<width>s, ......) reads up to width or until the first whitespace character, whichever appears first. If you want to include the spaces in input, you can use the appropriate conversion specifier in scanf() or a better alternative is to use fgets() for input from user.
Line 11: string[n+1] -> string[n-1]

Why does program terminate without taking input?

This is sample of my program:
#include <stdio.h>
void sum();
int main()
{
char choice[4];
do
{
sum();
printf("\nDo You want to restart the program: yes or no:\n");
fgets(choice, 4, stdin); //error point
} while (choice[0] == 'y' || choice[0] == 'Y');
printf("\nThanking You");
return 0;
}
void sum()
{
int a = 3, b = 4;
printf("sum of two number is %d", a + b);
}
In this program, only in the 1st iteration of while does it ask for input in choice and, on the next iteration the program auto terminates by taking any value in choice.
Following is the result after execution of code:
sum of two number is 7
Do You want to restart the program: yes or no:
yes
sum of two number is 7
Do You want to restart the program: yes or no:
Thanking You
[Program finished]
I am unable to understand that it takes input in choice while I haven't used scanf() (which leaves the new line character in the buffer). It may be it takes input from buffer that may be whitespace or other characters, but I don't know from where it came?
Your program is leaving a newline in the input buffer after the first prompt because there's not enough room for it in the buffer.
On the first call to fgets you give the string "yes" followed by a newline. The buffer has size 4 and you pass that size to fgets so it reads at most that many characters-1 to account for the terminating null byte. So there is still a newline left in the buffer.
That newline gets read immediately the next time fgets is called.
You should enlarge your buffer to handle more characters.
Your choice array is not large enough to hold all the input from the first loop. The second argument to the fgets function (4) tells it to read at most 3 characters (and it then appends a nul-terminator to the input). So, it leaves the newline character in the input stream, and that is read in the second loop (by itself).
Just increase your choice array size and the input limit to 5 (or more):
#include <stdio.h>
void sum();
int main()
{
char choice[5]; // Increase space for newline and nul
do {
sum();
printf("\nDo You want to restart the program: yes or no:\n");
fgets(choice, 5, stdin); // Inputs 'y', 'e', 's' and newline (4 chars) and appends a nul.
} while (choice[0] == 'y' || choice[0] == 'Y');
printf("\nThanking You");
return 0;
}
void sum()
{
int a = 3, b = 4;
printf("sum of two number is %d", a + b);
}
From fgets - cppreference (bolding mine):
Reads at most count - 1 characters from the given file stream and
stores them in the character array pointed to by str. Parsing stops if
a newline character is found, in which case str will contain that
newline character, or if end-of-file occurs. If bytes are read and no
errors occur, writes a null character at the position immediately
after the last character written to str.

C fgets and Arrays: Explanation

I have two questions regarding the following C code.
What is the purpose of clear() in the code? I thought
it was so I could press enter to "stop" entering the 11 characters
required for myarray, but it seems I could do that for the
suceeding scanf calls as well.
Does fgets always close the buffer with "\n"? What if I put 11
characters instead of ten? How would the function know to end the
character with "\n"?
#include <stdio.h>
void clear ()
{
while ( getchar() != '\n' );
}
int main() {
int value;
unsigned int second;
char myarray[11];
printf("Enter 10 characters:");
fgets(myarray, 11, stdin);
clear();
printf("Enter an integer between -50,000 and 50,000:");
scanf("%d",&value);
printf("Enter an unsigned integer between 0 and 100,000:");
scanf("%ud",&second);
...
What is the purpose of clear() in the code?
The purpose of clear() is to remove all the remaining charaters in the stdin buffer, in case the inputed string is bigger than 11 - 1.
Does fgets always close the buffer with "\n"? What if I put 11 characters instead of ten?
It does not, if the input stream has the size of 11 characters or bigger, only 11 - 1 will be read, the 11th character and those above are never read, leaving a space in myarray[] for the '\0' null terminator, they will remain in the buffer as will '\n', hence the need for clear().
Example:
If inputed string is "qwertyuiopa", q w e r t y u i o p \0 will be your char array, a \n will remain in the stdin buffer.
How would the function know to end the character with "\n"?
fgets stops reading as soon as the 11th - 1 character is read, as determined by its second parameter, regarldless of what character, or if '\n' is found, in witch case all the characters are read, including '\n', and will be stored in myarray[].
Example:
Inputed "qwerty", char array will be q w e r t y \n \0, stdin buffer will be empty.
One last note, for total correctness, the clear() function should account for EOF:
int c;
while((c = getchar()) != '\n' && c != EOF);

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);

Reading of standard input with fgets not waiting for input

Having this piece of code:
int main(void)
{
char str[4];
do
{
if (fgets(str,sizeof(str),stdin) == NULL)
break;
printf("\n %s \n", str);
}while (strncmp(str,"q\n",sizeof("q\n")));
return 0;
}
if i type more than 4 characters, then two lines are displayed. if i type 123456 and then press enter, does input store ['1','2','\n','\0'] or ['1','2','3','\0']? hen the second time printf is reached if i only press enter key one time?. How i can avoid this behaviour? I would like type 123456 and then get:
1234
The reason why fgets is only reading partial input is because the str array is too small. You need to increase the buffer size of str array.
Also remember that fgets will pick up \n ( enter / return ) that you press after giving your input.
To get rid of the \n do this:
fgets(str,sizeof(str),stdin);
str[strlen(str)-1] = '\0';
There is one MAJOR issue with your while condition ... I am not sure what your are trying to do there but strcmp is used to see if two strings are the same or not ... what you are doing is trying to compare a string to the size of something ...
There are multiple problems in your code:
you do not include <stdio.h>.
fgets() is given a very short buffer: 4 bytes, allowing for only 3 characters to be input at a time, including the '\n'. If you type more characters, they are buffered by the terminal and the standard stream library. It will take several calls to fgets() to read them all, 3 bytes at a time.
Your termination test is bogus: strncmp(str, "q\n", sizeof("q\n")) compares the string read by fgets() with "q\n" upto a maximum number of characters of 3 because sizeof("q\n") counts the q, the \n and the null terminator. You should just use strcmp() for this test.
You print the string with printf("\n %s \n", str);. Note however that a regular line read into str will contain the trailing newline so the printf call will actually output 2 lines.
Here is a modified version:
#include <stdio.h>
#include <string.h>
int main(void) {
char str[80];
while (fgets(str, sizeof(str), stdin) != NULL) {
str[strcspn(str, "\n")] = '\0'; // strip the newline if present
printf("\n %s \n", str);
if (!strcmp(str, "q"));
break;
}
return 0;
}
Try using getc() or fgetc() before using fgets()
When you use a scanf(), you press enter key (newline) which operates as accepting the input and transferring the input from stdin (standard input device) to your program.
scanf() itself does not consume the newline pressed. So, we need something down the code which will accept this newline and prevent this newline from acting as an input to the subsequent fgets(). This newline can be accepted using getc() or fgetc(), which should be written before fgets().
fgetc(stdin); OR getc(stdin);

Resources