fgets() is coming earlier than it should - c

int main (void){
Article article;
char title[100], author[100], journal[100], newtitle[100];
int year;
fgets(title, 80, stdin);
fgets(author, 80, stdin);
fgets(journal, 80, stdin);
scanf("%d\n", &year);
article = create_article(title, author, journal, year);
print_format_full(article);
fgets(newtitle, 80, stdin);
article = update_title(article, newtitle);
print_format_simplified(article);
// insert your code here
return 0;
}
I wanted to use fgets() for the last string(new title) after performing the first print function (print_format_full(article);) , but if I run the program, the program is asking for 5 inputs right at the beginning of the program. Can anybody help me find where I got it wrong?

scanf() reads exactly what you ask it to, it leaves a newline in the input buffer, which is automatically read by fgets.
To consume the newline, either change the sequence, use fgets before scanf, or use fgets to read the number and then Parse it with sscanf, strtol etc.
A while loop and getchar works too.

Related

Using getchar() after scanf()? [duplicate]

This question already has answers here:
scanf() leaves the newline character in the buffer
(7 answers)
Closed 5 years ago.
I have two questions:
why only when i do space in "%d " --> scanf("%d ", &num); it works?
I tried fflush(stdin) \ _flushall() between the scnaf and the gets and it doesn't works, it skips the gets.
When I do the space, it first does scanf then the gets and after that it print the number and print the string.
void main()
{
char ch, str[10];
int num;
printf("Enter your number : ");
scanf("%d ", &num);
printf("%d\n",num);
gets(str);
puts(str);
system("pause");
}
why only when i do space in "%d " --> scanf("%d ", &num); it works?
scanf("%d", &num); without a space after the "%d", stops scanning after reading a number. So with input 123Enter, the '\n' remains in stdin for the next input function like the now non-standard gets(). gets() reads that single '\n' and returns. By adding a space, scanf("%d ", &num); consumes the white-space after the number and does not return until non-white-scape is entered after the number.
When I do the space, it first does scanf then the gets and after that it print the number and print the string.
By adding a space, scanf("%d ", &num); does not return until non-white-space is entered after the number (as in 'a' in the following). Since stdin is usually line buffered, this means input of 2 lines needs to first occur. 123Enter abcEnter.
Recommend to instead use fgets() to read a line of user input.
char str[10*2]; // no need for such a small buffer
int num;
printf("Enter your number : ");
fflush(stdout);
fgets(str, sizeof str, stdin);
sscanf(str, "%d", &num);
printf("%d\n",num);
printf("Enter data : ");
fflush(stdout);
fgets(str, sizeof str, stdin);
fputs(str, stdout);
More robust code would check the results of fgets(), sscanf() and use strtol() rather than sscanf().
The C FAQ covers all these problems with scanf. See Why does everyone say not to use scanf? What should I use instead? and associated entries. Generally you'll use fgets followed by processing the resulting line such as with sscanf and checking that sscanf succeeded. This avoids leaving unparsed input and risking an infinite loop.
int number;
char line[255];
fgets( line, sizeof(line), stdin );
if( sscanf( line, "%d", &number ) != 1 ) {
fputs("That doesn't look like a number.\n", stdin);
}
Note that fgets will read to a newline or as much as your buffer can hold. If the line is larger than your buffer, it might only read part of the line. Next read from input will get the rest of the line. There's ways to avoid this, such as the POSIX getline function, but at least you don't wind up in an infinite loop.
Let's decipher some comments.
Do not ever use gets. Use fgets.
The reason you don't use gets is because there's no way to limit how much is read from stdin. This means the user can overflow the buffer causing havoc.
char buffer[32];
// What the line is more than 31 characters?
gets(buffer);
fgets() takes the size of the buffer and will read that many characters at most. This prevents a buffer overflow.
char buffer[32];
// If there's more than 31 characters it will stop reading.
// The next read of stdin will get the rest of the line.
fgets( buffer, sizeof(buffer), stdin );
"There's no gets() function in C."
Yes, there is a gets() function in C.
Yes, there isn't a gets() function in C.
It depends on which C you're talking about.
Some people when they say "C" mean C11, the current standard. Others when they say "C" mean C99 the previous standard. Some still adhere to C90, the original standard. There is a gets() function in C90. It was deprecated in C99. It was removed from the language in C11.
C compilers and documentation lag very, very, very far behind the standard. Many are still working on full support of C99. If you work to C11 you're going to be very surprised by the lack of support. If you want your code to work on most any compiler, write to C99.
Anyway, don't use gets.

C: error replacing gets() with fgets()

I am currently having an issue replacing gets() with fgets(). I have looked at multiple examples of doing this and it seems very straight forward however I am getting unexpected output in doing so. Using the gets() method in comments below, I get good behavior from my shell program I am writing, however when I change to the fgets() call, I get output ": no such file or directory" when giving input "ls". Like I said, with the gets() call it is working fine. code below:
int main(void) {
while(1) {
int i = 0;
printf("$shell: ");
scanf("%s", first);
/* gets(input);*/
fgets(input, sizeof(input), stdin);
//...parse input into tokens for exec system call...
execvp(first, args);
}
return 0;
}
Unlike gets, fgets will read the newline and store it in the string.
From the man page:
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.
You can remove the newline (if it is present) by replacing it will a null byte:
fgets(input, sizeof(input), stdin);
if (input[strlen(input)-1] == '\n') input[strlen(input)-1] = '\0';

Line not prompting for input

I'm new to programming and have been working on an assignment in class. For some strange reason the program keeps printing 2 different printf's on the same line and not giving me a chance to input information
Here is the code:
#include <stdio.h>
#include <stdlib.h>
int main (void)
{ char Name[20];
char cid1[6]="", cid2[6]="", cid3[6]="", cid4[6]="", cid5[6]="", cid6[6]="";
char Description1[21]="", Description2[21]="", Description3[21]="", Description4[21]="", Description5[21]="", Description6[21]="";
int hrs1 = 0, hrs2=0, hrs3=0, hrs4=0, hrs5=0, hrs6=0;
char grade1[2]="",grade2[2]="",grade3[2]="",grade4[2]="",grade5[2]="",grade6[2]="";
printf("Enter Students Name ");
fgets(Name, 20, stdin);
printf("Enter Class ID ");
scanf("%5s", cid1);
printf("Enter Class Description "); // Problem
fgets(Description1, 20, stdin); // here
printf("Enter Class Hours ");
scanf("%d", &hrs1);
printf("Enter Class Grade ");
fgets(grade1, 1, stdin);
printf("%s\n", Name);
printf("%s\n", cid1);
printf("%s\n", Description1);
printf("%d\n", hrs1);
printf("%s\n", grade1);
system("pause");
return 0;
The area marked “Problem here” is where the problem is currently occurring. In stead of prompting for the class description it will skip straight to entering class hours and completely ignore the enter class grade at the bottom.
It prints it as: Enter Class DescriptionEnter Class Hours.
They are trying to teach you the difference between scanf and fgets. And they are probably tricking you by telling you that the Class ID has to be 4 characters.
So if your Class ID is "1234" and you hit Enter after, what ends up in stdin is:
1234\r\n
The %5s format in scanf says to read 5 characters and then move on. So, you read in 1234\r and leave \n in the stdin stream. Then when fgets executes, it reads in the \n and moves on.
From the above on fgets:
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 the
end-of-file is reached, whichever happens first.
There is a newline left in the input buffer, from the previous input operation. One way to get rid of it is to read character by character until you've read a '\n'.
You did not consume the newline characters by your scanf calls. As fgets returns when it reads a newline character, it returns immediatelly.
You could change the scanf format string to consume newline characters as follow
scanf("%5s\r\n", cid1);
It seems like you are running this on windows. Windows has issues with flushing its stdin properly. Try using an
fflush(stdin);
after any reads from the console.

Why is the first string ignored when reading with fgets from stdin? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Dev-C++ Input skipped
I am trying to read an array of character strings from stdin using fgets, but the first string I want to read is always ignored. What is causing this issue?
#include <stdio.h>
int main()
{
int i;
struct material
{
char name[30];
float price, kg;
};
unsigned m,nr;
printf("Lorry capacity=");
scanf("%u", &m);
printf("Number of materials=");
putchar('\n');
scanf("%u", &nr);
struct material list[nr];
for (i=0; i<nr; i++)
{
printf("Name=");
fgets(list[i].name, 30, stdin);
}
putchar('\n');
for (i=0; i<nr; i++)
{
printf("%s ", list[i].name);
}
return 0;
}
scanf("%u", &nr);
struct material list[nr];
for (i=0; i<nr; i++)
{
printf("Name=");
fgets(list[i].name, 30, stdin);
The scanf("%u", &nr); leaves the newline in the input buffer, so fgets finds an empty line without requiring further input to be entered.
It is generally a bad idea to mix (f)scanf and fgets, for that reason (among others).
As a quick fix, empty the input buffer before the first fgets,
int ch;
while((ch = getchar()) != EOF && ch != '\n');
if (ch == EOF) {
// oops
}
A more principled fix would be to read in the values before using fgets to get an entire line including the newline, and decode the numbers with strtoul or maybe sscanf.
This is a very common error. After reading a number with scanf, the newline you typed by pressing ENTER is left in the input buffer, so the first call to fgets reads the (very short) line that consists of only that newline.
I noticed that I can get rid of the newline left in the input buffer, by reading it with getchar().
Also, I had to use the following code to remove the trailing newline character from fgets() input:
char *pos;
if ((pos=strchr(Name, '\n')) != NULL)
*pos = '\0';
One of the things that's generally misunderstood is that when you ask for input from the user, you get freebies.
When the computer ask for the amount of materials:
Number of materials=
51
And you enter "51" you're really getting three characters: '5', '1', and '\n'. Everything comes with a newline character when you hit the enter key.
Different utilities that get input from the user handle this different. fgets() will read the newline and then it stores the input as "51\n". If you read it as a string using scanf()'s string format specificer "%s" you'll get only the digits "51" and the newline character is left on the stdin buffer.
So in your case you read a number via scanf:
scanf("%u", &nr);
Which leaves the newline, then when you try to do the next read:
fgets(list[i].name, 30, stdin);
fgets picks up that newline and stores it.
So there's a bunch of fixes possible here, one is to just use fgets() only, another is to consume the newlines with getchar() after each scanf, choice is up to you.
BTW: You can insert a newline in your printfs: printf("Number of materials=\n");
You can just do a fgets after each scanf, which will then eat the pending newline:
char dummy[10];
...
scanf (...);
fgets (dummy, 1, stdin);

how does fgets internally works?

Well it is a basic question but I seem confused enough.
#include<stdio.h>
int main()
{
char a[100];
printf("Enter a string\n");
scanf("%s",a);
}
Basically the above is what I want to achieve.
If I enter a string
James Bond
then I want that to be stored in array a.
But the problem is because of presence of a blank space in between only James word is stored.
So how can I solve this one.
UPDATE
After the replies given below I understand fgets() would be a better choice. I want to know internal working of fgets as why is it able to store the string with space where as scanf is not able to do the same.
Is this what you need?
freeBSD: http://www.freebsd.org/cgi/cvsweb.cgi/src/lib/libc/stdio/fgets.c?rev=1.14.14.1;content-type=text%2Fplain
open implementation: https://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=7425&lngWId=3
OWP(dead) http://www.koders.com/c/fid042417FA231704B84308A66E1B82EADEDAB22051.aspx
ReactOS http://www.koders.com/c/fidEB3507945463053CEFCD518EA0CDFF9EB78E24C9.aspx?s=fgets.c#L1
All implementations scans the input file(or stream) until it reaches \n or EOF, or the maxSize param is hit...
scanf reads up until the first whitespace character. The solution is to use fgets, if memory serves me correctly, in your instance it'd be:
fgets(a, 100, STDIN);
It will read up to 100 characters (or the first \n) from standard input and store it in a.
Do not use the gets function ever, even if it looks easier.
Usually scanf breaks the input at whitespace (space, tab, newline, ...).
For example, the input " 5 42 -100" is accepted with scanf("%d%d%d") because each %d strips the leading whitespace. The same behaviour happens with %s.
The only conversion specifiers where the ignoring of leading whitespace doesn't happen are %%, %[ and %c (and, for different reasons, %n)
char input[] = " hello world";
char buf[100];
sscanf(input, "%8c", buf); /* buf contains " hello w" */
sscanf(input, "%8[^o]", buf); /* buf contains " hell" */
The fgets function reads as many characters as there are, up to the nest line break.
I use The Open Group Base Specifications Issue 7 for online documentation
You should use gets(a)/fgets(a, sizeof(a), stdin) instead of sscanf().
Try fgets():
char a[100];
printf("Enter a string\n");
fgets(a, sizeof(a), STDIN);
To learn more about STDIN, check this.

Resources