I have written below program which tries to read and print the values of a structure.
I thought that scanf ignores the /n for all kinf of data except for char but when i run the below program and provide the first input as an integer. I dont get the o/p for name variable. Why??
#include <stdio.h>
#include <string.h>
struct employee
{
int empno;
char name[10];
float p_money;
};
int main()
{
struct employee e;
struct employee *ptr;
ptr = &e;
printf("please enter the empno \n");
scanf("%d", &(ptr->empno));
printf("please enter the name \n");
gets(ptr->name);
//scanf("%d", &(ptr->empno));
printf("please enter the money \n");
scanf("%f", &(ptr->p_money));
printf("Roll No: %d\n", ptr->empno);
printf("Name: %s\n", ptr->name);
printf("Money: %f\n", ptr->p_money);
getchar();
return 0;
}
Execution:
please enter the empno
10
please enter the name
please enter the money
100.99
Roll No: 10
Name:
Money: 100.989998
please enter the empno
10jackal
please enter the name
please enter the money
100.99
Roll No: 10
Name: jackal
Money: 100.989998
The problem is not with scanf but gets - use fgets instead.
char * gets ( char * str );
gets - Reads characters from the standard input (stdin) and stores them as a C string into str until a newline character or the end-of-file is reached.
1use fgets instead of gets... gets is bad.
The reason why gets is bad:
gets Reads characters from the standard input until enter (new line is encountered.) is pressed.
In your case, name[10], and you are doing gets(name). gets does not know how big the name is... If you enter 9 character, it is okay.
But what if you enter more than 9 char? gets() continues to write all the char past the memory which doesn't belong to you hence causing "Undefined Behavior"
Related
I am trying to create a program where the user enters their name and a float number, when the user enters their name it completely skips the part to enter a double I am not sure what is causing this problem the code bellow is what i have:
#include <stdio.h>
#include <stdint.h>
//extern double control(); //name in asm label (ex. global start)
int main()
{
char name[100];
double salary;
printf("Welcome to Software Analysis by Paramount Programmers, Inc.\n");
printf("Please enter your first and last name and press enter: ");
scanf("%s", name);
scanf("%lf", &salary);
printf("%lf", salary);
//printf("%f", var);
return 0;
result
Welcome to Software Analysis by Paramount Programmers, Inc.
Please enter your first and last name and press enter: david n
0.000000The bash script file will terminate
As the commentator wrote above, scanf ("%s", str) reads characters from the input stream until a space or '\n ' is encountered. Instead of the above function, use
fgets(name, sizeof(name), stdin)
Good luck :)
This question already has answers here:
scanf() leaves the newline character in the buffer
(7 answers)
Closed 1 year ago.
This C code is not waiting for student name. It directly prints total student number. But when I comment out the first printf-scanf statement(or enter number of students:), then code is waiting for the user to enter student name.
#include <stdio.h>
int main()
{
char name[10];
int count;
printf("ENTER NUMBER OF STUDENTS:\n");
scanf("%d", &count);
printf("ENTER STUDENT NAME:\n");
scanf("%[^\n]%*c", &name);
printf("Total_Students: %d\n", count);
printf("NAME: %s\n", name);
return (0);
}
The second scanf is skipped because the newline character is being interpreted from the first scanf.
For instance, if you entered 2 for number of student, what is being entered is 2\n. The first scanf reads the number 2 and leaves the \n in the buffer which is being interpreted by the 2nd scanf.
You can simply add a space in the second scanf to get past this issue
scanf(" %[^\n]%*c", &name);
change the second scanf() argument to %s and it directly makes the last entry as NULL
.
This question already has answers here:
scanf() leaves the newline character in the buffer
(7 answers)
fgets doesn't work after scanf [duplicate]
(7 answers)
Closed 1 year ago.
Here, if I don't use getchar() the output is misbehaving:
What exactly is the getchar() doing here ?
And what is it holding until another input gets invoked ?
And how will the next input be invoked here in this case ?
My code:
//To take 3 students data using stucture which is user defined.
#include<stdio.h>
#include<stdlib.h>
//#include<conio.h>
struct student
{
char reg_number[200];
char name[200];
int marks_obt;
};
int main()
{
struct student stud1,stud2,stud3;
printf("Enter registration number of student 1 : ");
gets(stud1.reg_number);
printf("Enter name of student 1 : ");
gets(stud1.name);
printf("Enter marks of student 1 : ");
scanf("%d",&stud1.marks_obt);
system("cls");
//getchar();
printf("Enter registration number of student 2 : ");
gets(stud2.reg_number);
printf("Enter name of student 2 : ");
gets(stud2.name);
printf("Enter marks of student 2 : ");
scanf("%d",&stud2.marks_obt);
system("cls");
//getchar();
printf("Enter registration number of student 3 : ");
gets(stud3.reg_number);
printf("Enter name of student 3 : ");
gets(stud3.name);
printf("Enter marks of student 3 : ");
scanf("%d",&stud3.marks_obt);
system("cls");
printf("ID of student 1 is %s \n Name of student 1 is %s \n Marks obtained by stdent 1 is %d",stud1.reg_number,stud1.name,stud1.marks_obt);
printf("\n\n");
printf("ID of student 2 is %s \n Name of student 2 is %s \n Marks obtained by stdent 2 is %d",stud2.reg_number,stud2.name,stud2.marks_obt);
printf("\n\n");
printf("ID of student 3 is %s \n Name of student 3 is %s \n Marks obtained by stdent 3 is %d",stud3.reg_number,stud3.name,stud3.marks_obt);
//getch();
}
First of all, never use the gets(). It is deprecated from the C and C++ standards. The safe way would be to apply fgets():
char input[128];
if (fgets(input, sizeof input, stdin) == NULL) {
// Oops... input was incorrectly given, handle the error
return EXIT_FAILURE; // To quit
}
// Removing the trailing newline character
input[strcspn(input, "\n")] = 0;
You're facing an overlap when asking for another input from the user in the next gets() call because you hit the Return key as well when you finish typing with scanf(). A newline key is added at the end.
The getchar() takes the newline, so it is discarded and does the job you expect.
There are already comments and a correct answer that should be enough, but judging by your last comment it seems that you didn't yet understand what's going on.
This line:
scanf("%d",&stud1.marks_obt);
Parses an integer, for that you press Enter, when you do that a \n is added to the stdin buffer, and remains there, it is not parsed by scanf.
After that:
gets(stud2.reg_number);
Will parse that \n character and store it in stud2.reg_number, and the program moves on.
When you use getchar(), it parses the \n and leaves the stdin buffer empty again so the gets has nothing to parse and waits for your input, correcting the problem, it's still a flimsy solution, but it works in this particular case.
Moral of the story, don't mix scanf with gets, fgets at least, since, as stated, gets was removed from the standard in C11. The reason why some compilers still support it is beyond me.
I made a program to take multiple inputs as string, store and print them.
Somehow the "Account Number" that's stored in a[i].acn is not printing. I've tried debugging and the problem seems to be in the loop that adds spaces to a[i].name .
#include <stdio.h>
#include <string.h>
struct Bank
{
char name[10],acn[8];
float bal;
}a[100];
int n,i,flag;
void add()
{
//function to add Rs. 100 to accounts that have balance over 1000
//and print the details.
for(i=0;i<n;i++)
if(a[i].bal>=1000)
a[i].bal+=100;
printf("\nS.No.\tName\t\tAcc. No.\tBalance(in Rs.)");
for(i=0;i<n;i++)
printf("\n[%d]\t%s\t%s\t%.2f",i+1,a[i].name,a[i].acn,a[i].bal);
}
void main()
{
printf("Enter the number of customers: ");
scanf("%d",&n);
printf("Enter the details of %d customers:\n",n);
for(i=0;i<n;i++)
{
printf("\nCustomer-%d",i+1);
printf("\nFirst Name: ");
fflush(stdin);
gets(a[i].name);
printf("Account Number: ");
fflush(stdin);
gets(a[i].acn);
printf("Account Balance: ");
scanf("%f",&a[i].bal);
}
for(i=0;i<n;i++)//The problem seems to be in this loop
while(strlen(a[i].name)<10)
strcat(a[i].name," ");
add();
}
Input:
Enter the number of customers: 2
Enter the details of 2 customers:
Customer-1
First Name: Aarav
Account Number: ASDF1234
Account Balance: 1200
Customer-2
First Name: Asd
Account Number: abcd1122
Account Balance: 999.9
Output:
S.No. Name Acc. No. Balance(in Rs.)
[1] Aarav 1300.00
[2] Asd 999.90
scanf() then gets() is bad
scanf("%d",&n); reads the integer, yet leaves the following '\n' in stdin that gets() reads as an empty string "".
I recommend to use fgets() to read all the line into a sizable buffer and then parse using sscanf(), strtol() etc.
Code overfills buffer
a[i].nam only has enough room for 9 characters and then the null character. Appending a space until it has a length more the 9 overfills .name[10].
struct Bank {
char name[10],acn[8];
float bal;
} a[100];
while(strlen(a[i].name)<10)
strcat(a[i].name," ");
Use while(strlen(a[i].name)<9) to pad with spaces, but not too many.
Money needs special considerations. For now, consider a long of lowest denominational (cents). Read in a double and then long balance = lround(input*100.0);
Other weaknesses exist.
There are few things to correct in your program.
Use fgets instead of gets because in gets there is no boundary check and there is a danger of reading beyond the allocated size.
When using fgets , scanf and even gets they all read the left over \n characters from the standard buffer , so using fgets we can avoid it if we properly use it.(scanf also avoids space characters but it cannot be used to read multiword strings)
remove fflush(stdin), its not required you can see reason here
And last, but certainly not least use int main() instead of void main()
You have this:
struct Bank
{
char name[10],acn[8];
float bal;
}a[100];
since C strings must end with a NUL character (aka '\0') the name can be at maximum 9 chars long.
But here
while(strlen(a[i].name)<10)
strcat(a[i].name," ");
you keep adding spaces until it's 10 characters long. In other word - you write outside the array.
Change name to be name[11]
Besides that gets and fflush(stdin) should be avoided.
This question already has answers here:
How to do scanf for single char in C [duplicate]
(11 answers)
The program doesn't stop on scanf("%c", &ch) line, why? [duplicate]
(2 answers)
Closed 2 years ago.
i am a beginner in C programming. I was learning about the user inputs. The following piece of code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char grade;
printf("Enter you grade: ");
scanf("%c", &grade);
printf("Your grade is %c.", grade);
return 0;
}
does what I intend it to do i.e.
ask for the grade
display the grade
But when I modify the code to the following :
#include <stdio.h>
#include <stdlib.h>
int main()
{
int age;
printf("Enter you age: ");
scanf("%d", &age);
printf("You are %d years old.\n", age);
printf("-----------------------------\n");
double gpa;
printf("Enter your GPA: ");
scanf("%lf", &gpa);
printf("Your GPA is %f. \n", gpa);
printf("-----------------------------\n");
char grade;
printf("Enter you grade: ");
scanf("%c", &grade);
printf("Your grade is %c.", grade);
return 0;
}
it does the following:
asks for the age
displays the age
asks for the gpa
displays gpa
asks for grade
it doesnt display grade.
The output looks like:
Enter you age: 45
You are 45 years old.
-----------------------------
Enter your GPA: 4
Your GPA is 4.000000.
-----------------------------
Enter you grade: Your grade is
.
please suggest me what I am doing wrong.
When you enter your age, this is what is in the input buffer just before the scanf(%d) starts retrieving characters:
45<newline>
The scan(%d) skips any white space in the buffer (there isn't any), reads the 45, but leaves the newline. Then when you enter your GPA, this is what is in the input buffer just before the scanf(%lf) starts retrieving characters:
<newline>4<newline>
The scan(%lf) skips any white space in the buffer (the newline), reads the 4, but again leaves the newline. In other words, the leading newline doesn't matter if your next next scanf also skips whitespace such as moving from the first entry to the second.
But scanf(%c) does not skip white space. It simply reads the next character, which is a newline:
<newline>A<newline>
That's why tour period appears on the following line, it has read a character, but that character was the newline rather than the grade.
Section 7.21.6.2 The fscanf function, in the ISO C11 standard, has this to say on the first step of processing a conversion specifier (my emphasis):
Input white-space characters (as specified by the isspace function) are skipped, unless the specification includes a [, c, or n specifier.
A quick fix would be to manually skip whitespace yourself, something like:
printf("Enter your grade: ");
scanf(" %c", &grade);
printf("Your grade is %c.", grade);
as per that same section of the standard:
A directive composed of white-space character(s) is executed by reading input up to the first non-white-space character (which remains unread), or until no more characters can be read.