This question already has answers here:
Removing trailing newline character from fgets() input
(14 answers)
Closed 2 years ago.
The book_name is picking \n as input a printing the next variable in a new line. I inserted this code while ((getchar()) != '\n'); to prevent fgets() from taking \n as input after using scanf(). But i can't understand why fgets() is taking \n as input. Please explain.
CODE
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int id;
char *book_name;
char *author;
} book;
int main() {
int n;
printf("Enter number of books: \n");
scanf("%d", &n);
book *bk = calloc(n, sizeof(book));
for (int i = 0; i < n; i++)
{
printf("Enter the no of the book: \n");
scanf("%d", &((bk+i)->id));
while ((getchar()) != '\n');
(bk+i)->book_name = malloc(20);
printf("Enter the name of the book: \n");
fgets((bk+i)->book_name, 20, stdin);
(bk+i)->author = malloc(20);
printf("Enter the author of the book: \n");
fgets((bk+i)->author, 20, stdin);
}
for (int i = 0; i < n; i++)
{
printf("%d %s %s\n", (bk+i)->id, (bk+i)->book_name, (bk+i)->author);
}
return 0;
}
OUTPUT
Output of code
Check answered post here.
scanf() leaves '\n' in the buffer. So whenever any other function such as getchar() or fgets() tries to read from the stdin, leftover '\n' is read first.
If you are on file instead of stdin, better use below code for extra safety.
FILE *fp = fopen("my_file.txt", "r");
int c;
while ((c = fgetc(fp)) != EOF && c != '\n');
What you have done is the correct way to remove leftover \n, #sadbro probably misunderstood your code.
Related
I am unable to put the value in the first element of the array. It's always asking to put the value in array second element.
#include<stdio.h>
#include<string.h>
int main(void)
{
int a, i;
char names[50][50];
printf("\nEnter the number of names you want :");
scanf("%d", &a);
for(i = 0; i < a; i++)
{
printf("\n%d name :", i);
gets(names[i]);
}
printf("\nThe required name lists :");
for(int i = 0; i < a; i++)
{
printf("\n%d name :", i+1);
puts(names[i]);
}
return 0;
}
As scanf leaves behind a dangling newline character \n it causes the gets(Use fgets) to not wait for the input from the user. Try flushing the input buffer by using getchar.
Update: Added mechanism to remove the trailing \n registered by the fgets
#include<stdio.h>
#include<string.h>
int main()
{
int a,i;
printf("Enter the number of names you want: ");
scanf("%d",&a);
//Flush the input buffer
int ch;
while ((ch = getchar()) != '\n' && ch != EOF);
char names[50][50];
for(i=0;i<a;i++)
{
printf("%d name: ",i);
fgets(names[i],50,stdin); //Use fgets instead of gets
// To remove th \n registed by the fgets
char *p;
if ((p = strchr(names[i], '\n')) != NULL)
*p = '\0';
}
printf("The required name lists: \n");
for(int i=0;i<a;i++)
{
printf("%d name: ",i+1);
puts(names[i]);
}
return 0;
}
Reference:
Remove newline skipped by scanf
Remove newline registered by fgets
Put this after line scanf("%d",&a), as a workaround,
char c;
scanf("%c",&c);
Also use fgets(names[i],50,stdin) instead of gets(names[i])
Note: You get warning when you use gets in your code, as it is always assumes a consistent input from user. More explanation over here
Why is the gets function so dangerous that it should not be used?
So I need to write a function which counts the frequency of a character in a string in C. The function parameters must be just the character I want to count. So here's my code:
#include <stdio.h>
#include <string.h>
int charFrequency(char c) {
char str[500];
int i, nr = 0;
printf("Enter the string: ");
fgets(str, sizeof(str), stdin);
for(i=0; i < strlen(str); ++i) {
if (str[i] == c) {
nr++;
}
}
return nr;
}
int main(void) {
char c;
int nr;
printf("Enter the character you want to count: ");
c = getc(stdin);
getc(stdin); // what is the role of this code line? if I delete this line the programs does not work anymore.
nr = charFrequency(c);
printf("The frequency is %d", nr);
return 0;
}
I have a problem when I read the character I want to count. I use getc but the program doesn't work fine. But if I write again getc(stdin) the program works fine.
I also tried with scanf but I have the same issue. Can someone explain me how getc works?
I try to get strings as many as the input value in c.
But a leading white space located first line is removed.
I had already use the fgets and scanset. I want the input and output to be the same.
fgets(str[i], 100, stdin);
scanf("%[^\n]%*c]", str);
Code
int n = 0;
scanf("%d\n", &n);
char str[10][100] = {0};
for (int i = 0; i < n; i++) {
fgets(str[i], 100, stdin);
}
Input
3
**
*
**
Output
**
*
**
What should I do?
You have to use getchar() after reading n because the newline character '\n' will remain in the input buffer and your fgets in for loop will read that and also remove \n from scanf.
Use following line of code:
int n = 0;
scanf("%d\n", &n);
getchar();
char str[10][100] = {0};
for (int i = 0; i < n; i++) {
fgets(str[i], 100, stdin);
}
remove the "\n" from scanf and add a getchar() to capture the newline.
scanf("%d", &n);
getchar();
I have a problem with reading strings in c. When I add the gets() function in an if-instruction, the program stops.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int n,i = 0;
char sir[2000],ch;
printf("Press you option: "); scanf("%d",&n);
if(n == 1)
{
printf("text: "); gets(sir);
printf("\nINPUT: ");
for(i = 0;i < strlen(sir);i++)
printf("%c",sir[i]);
}
return 0;
}
Any solution?
When I add the gets() function in an if-instruction, the program stops.
Look at the preceding code. Maybe you entered 1 Enter
printf("Press you option: ");
scanf("%d",&n);
scanf("%d",&n); consume the '1', but not the '\n'.
Later code does
printf("text: ");
gets(sir);
And then gets() reads that '\n' and returns with sir[0] == '\0', an empty string. This causes for(i = 0;i < strlen(sir);i++) to not iterate the body of the for() loop.
What to do?
Read a line of user input fgets() and then process that string. Note that invalid input, EOF and buffer overflow handling not addressed in this simple code example. That would be step 2.
char buf[80];
printf("Press you option: ");
fgets(buf, sizeof buf, stdin);
sscanf(buf, "%d",&n);
printf("text: ");
fgets(buf, sizeof buf, stdin);
buf[strcspn(buf, "\n")] = '\0'; // lop off potential \n
strcpy(sir, buf);
This is due to the C input buffer problem, just add one getchar() as shown, it will work, let me know for any other help.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int n,i = 0;
char sir[2000],ch;
printf("Press you option: "); scanf("%d",&n);
if(n == 1)
{
printf("text: ");
getchar();
gets(sir);
printf("\nINPUT: ");
for(i = 0;i < strlen(sir);i++)
printf("%c",sir[i]);
}
return 0;
}
gets() is not preferred way to get the input from the user these days. As mentioned above please use fgets to read the input.
Coming back to your problem. Please fflush(stdin) in order to resolve your issue. Trying running the below code. i have just added fflush(stdin) and now the user input is taken by fgets() and no program stopping happens.
Code :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int n, i = 0;
char sir[2000], ch;
printf("Press you option: "); scanf("%d", &n);
if (n == 1)
{
printf("text: ");
fflush(stdin);
gets(sir);
printf("\nINPUT: ");
for (i = 0; i < strlen(sir); i++)
printf("%c", sir[i]);
}
return 0;
}
Also please read and understand why we are using fflush and why we need to avoid gets() function going forward. Hope i have helped you. Thank you :)
This is my code. I didnt want to use scanf() to read the name and I tried using fgets() but after I put the first name and age, the second and third time my program runs the for loop it doesnt take age .
#include <stdio.h>
#include <string.h>
struct student
{
char name[15];
int age;
};
int main()
{
int i;
struct student s[A];
for (i = 0 ; i < A ; i++)
{
printf("enter the names and age\n");
fgets(s[i].name, 10, stdin);
scanf("%d", &s[i].age);
}
printf("\n\n");
for (i = 0 ; i < A ; i++)
{
printf("%s\t%d\n", s[i].name, s[i].age);
}
return 0;
}
It doesnt work, why?
But when I replace fgets with
scanf("%s%d",s[i].name,&s[i].age);
It works fine
The difference between fgets() and scanf()
fgets(...) typically reads until receiving a '\n'
scanf("%d", ...) typically:
1. Reads and discards leading white-space.
2. Reads numeric input (sign,digits) until scanning a non-digit.
3. Non-digit is put back into stdin for the next input function.
Example:
JohnEnter
"John\n" is read by fgets() into s[0].name.
21Enter
21 is read by scanf("%d",...) into s[0].age. '\n' put back into stdin
"\n" is read by fgets() into s[1].name.
M
"M" is read by scanf("%d",...), nothing is put in s[1].age. 'M' put back into stdin.
aryEnter
"Mary\n" is read by fgets() into s[2].name.
19Enter
19 is read by scanf("%d",...) into s[2].age. '\n' put back into stdin
"\n" is read by fgets() into s[3].name.
Alternative: To read 2 lines, call fgets() twice, then parse:
int Scan_student(struct student *dest) {
char buffer[2][80];
dest->name[0] = '\0';
dest->age[0] = -1;
printf("enter the names and age\n");
for (int i=0; i<2; i++) {
if (fgets(buffer[i], sizeof buffer[i], stdin) == NULL) {
return EOF; // stdin was closed, no more input (or input error)
}
buffer[i][strcspn(buffer[i], "\r\n")] = '\0'; // lop off potential trailing \n
}
// parse the 2 buffers: MANY options here - something simple for now.
if (sscanf(buffer[0], " %14[-'A-Za-z ]", dest->name) != 1) {
return 0;
}
if (sscanf(buffer[1], "%d", &dest->age) != 1) {
return 0;
}
return 1;
}
int i;
struct student st[3];
for (i = 0 ; i < sizeof(st) / sizeof(st[0]) ; i++) {
if (Scan_student(&st[i]) != 1) break;
}
If you input both the name and the age in a single line, then that's the normal behavior because fgets() will read the whole line until 9 bytes (in your case) are read or a '\n' is found.
You need one of the two, for instance you could only use fgets() like this
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct student
{
char name[100];
int age;
};
int main()
{
int i;
struct student s[1];
for (i = 0 ; i < sizeof(s) / sizeof(*s) ; i++)
{
char number[100];
char *unconverted;
printf("Name > ");
fgets(s[i].name, sizeof(s[i].name), stdin);
if ((unconverted = strchr(s[i].name, '\n')) != NULL)
*unconverted = '\0'; // Remove the trailing '\n'
printf("Age > ");
fgets(number, sizeof(number), stdin);
s[i].age = strtol(number, &unconverted, 10);
if ((*unconverted != '\0') && (*unconverted != '\n'))
s[i].age = -1; // Invalid value indicating input error
}
for (i = 0 ; i < sizeof(s) / sizeof(*s) ; i++)
printf("Name: %s\nAge : %d\n", s[i].name, s[i].age);
return 0;
}
Or scanf() only
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct student
{
char name[100];
int age;
};
int main()
{
int i;
struct student s[1];
for (i = 0 ; i < sizeof(s) / sizeof(*s) ; i++)
{
printf("Name Age > ");
if (scanf("%99s%d", s[i].name, &s[i].age) != 2)
{
fprintf(stderr, "input error\n");
s[i].name[0] = '\0';
s[i].age = -1;
}
}
for (i = 0 ; i < sizeof(s) / sizeof(*s) ; i++)
printf("Name: %s\nAge : %d\n", s[i].name, s[i].age);
return 0;
}
and you can then input both name and age in a single line.
The fgets() method is better because you don't need to deal with the '\n' that scanf() doesn't pick up from stdin. A combination would work if you are careful to force the user to input the values in separate lines.
To be honest fgets() isn't required here as you've specified to read from stdin you should simply use gets() this reads from stdin by default. If your moving between a scanf() statement and a gets() statement you should use fflush(stdin) to clear out the input stream, example below:
scanf("%99s", s[i].name);
fflush(stdin);
gets(s[i].age);
In general your better sticking with either scanf() or gets() and not combining them.