how many students : 2 (it works fine)
how many students : 4 (it gives error "An access violation (segmentation fault) was raised in your program."
why it is happening with me, i have spent 4 hours but could not figure it out.
#include <stdio.h>
struct student
{
int rollno;
char name[20];
};
int main()
{
int n,i,j;
struct student detail[n];
printf("how many students: ");
scanf("%d",&n);
fflush(stdin);
for(i=0; i<n; i++)
{
printf("enter student no.%d\n",(i));
printf("Name: ");
gets(detail[i].name);
printf("Roll No: ");
scanf("%d",&detail[i].rollno);
fflush(stdin);
}
for(i=0; i<n; i++)
{
printf("Student no. %d Detail\n",(i+1));
printf("Name:\t\t%s \nRoll No: \t%d\n",detail[i].name,detail[i].rollno);
}
getch();
}
In your code, the primary issue is
int n,i,j;
struct student detail[n];
you're using n uninitialized. It invokes undefined behavior. You need to move the definition of detail[n]; after you have scanned the value from the user.
That said,
Check for the return value of scanf() to ensure success.
gets() is dangerous because it can cause buffer overflow. Use fgets() instead.
As per the standard, fflush(stdin) is UB, remove that.
getch() should be getchar(), if only stdio.h is included.
Related
After I execute the exe I get this error :
undefined reference to `StudentScan'
error: ld returned 1 exit status|
Note: I'm bad and new to coding so don't mind my bad coding please^^
Note2: I'm just messing with random functions.
#include <stdio.h>
#include <stdlib.h>
struct student {
char firstName[20];
char AverageNum[2];
};
void StudentScan(int, struct student[]);
void StudentPrint(int, struct student[]);
int main() {
int i;
int length;
struct student *studentp;
printf ("\nEnter the host of students: ");
scanf ("%d ", &length);
struct student list[length];
studentp=malloc(length*sizeof(struct student));
if (studentp==NULL)
{
printf("Out of memory!");
return 0;
}
for(i = 0; i < length; i++) {
StudentScan(i,studentp);
printf("\nEnter average number: ");
scanf("%s", list[i].AverageNum);
}
free (studentp);
void StudentScan(int i, struct student list[])
{ printf("\nEnter first name : ");
scanf("%s", list[i].firstName);
printf("\nEnter average number: ");
scanf("%s", list[i].AverageNum);
}
return 0;
}
The posted code has defined StudentScan() within main(). But nested function definitions are not allowed in C. This should generate a compiler warning, such as:
warning: ISO C forbids nested functions [-Wpedantic]
void StudentScan(int i, struct student list[])
Pay attention to all compiler warnings and fix them. If no warning is seen when compiling this code, turn up the level of compiler warnings. On gcc, I suggest to always use at least gcc -Wall -Wextra, and I always add -Wpedantic. The -Wpedantic is needed with gcc to see a warning for this. Some compilers, and gcc is one of these, do support nested function definitions as a compiler extension. Still, this feature is nonstandard, and it is best to not rely on it.
The fix is simple: move the definition of StudentScan() out of main():
#include <stdio.h>
#include <stdlib.h>
struct student {
char firstName[20];
char AverageNum[2];
};
void StudentScan(int, struct student[]);
void StudentPrint(int, struct student[]);
int main(void) {
int i;
int length;
struct student *studentp;
printf ("\nEnter the host of students: ");
scanf ("%d ", &length);
struct student list[length];
studentp=malloc(length*sizeof(struct student));
if (studentp==NULL)
{
printf("Out of memory!");
return 0;
}
for(i = 0; i < length; i++) {
StudentScan(i,studentp);
printf("\nEnter average number: ");
scanf("%s", list[i].AverageNum);
}
free (studentp);
return 0;
}
void StudentScan(int i, struct student list[])
{ printf("\nEnter first name : ");
scanf("%s", list[i].firstName);
printf("\nEnter average number: ");
scanf("%s", list[i].AverageNum);
}
Also note that you should always specify maximum widths when reading strings using scanf() family functions with %s or %[] to avoid buffer overflow. For example:
scanf("%19s", list[i].firstName);
Note that 19 is used, even though the firstName field is an array of 20 char values. Remember that one space must be reserved for the \0 terminator. And since you are using %s to read a string into the AverageNum field, you should also have:
scanf("%1s", list[i].AverageNum);
That is, this field can only hold one digit. If the intention is to hold two digits, this field must be changed within the struct to: char AverageNum[3].
And while we are discussing scanf(), note that this function returns the number of successful assignments made during the function call. If no assignments are made, 0 is returned. This return value should always be checked. Consider: if the user mistakenly enters a letter when a digit is expected, nothing is stored in the intended variable. This may lead to undefined behavior. You may try something like this to validate numeric input:
printf ("\nEnter the host of students: ");
while (scanf ("%d ", &length) < 1) {
puts("Please enter a number");
int c;
while ((c = getchar()) != '\n' && c != EOF) {
continue;
}
}
This code asks the user to enter input again if a number is not entered when expected. Note that if the user does enter a non-digit, this character remains in the input stream and must be cleared before attempting to process more user input. The while loop is a typical construction which accomplishes this task.
Edit
Based on comments made by the OP, here is a modified version of the posted code. This version uses a float value instead of a character array for the AverageNum field of the struct. A floating-point type may be more useful than an integer type for storing averages. It is usually best to use double for floating-point values, but in this case it looks like AverageNum has little need for precision (the char array was intended to hold only two digits); float is probably sufficient for this use. If a different type is desired, it is simple enough to modify the code below.
Some input validation is implemented, but note that more could be done. The user is prompted to enter a number when non-numeric input is found where numeric input is expected. The input stream is cleaned with the while loop construction after such an input mistake; it would be good to remove this code to a separate function called clear_input(), for example.
If the user signals end-of-file from the keyboard, scanf() will return EOF; the code below chooses to exit with an error message rather than continue with malformed input in this case. This could also occur with input redirected from a file, and this condition may need to be handled differently if such input is expected.
The loop that populated the list[] array seemed to be operating inefficiently, asking for AverageNum twice in each pass. This has been streamlined.
Note that the call to malloc() can be rewritten as:
studentp = malloc(length * sizeof *studentp);
This is a very idiomatic way of writing such an allocation. Here, instead of using an explicit type as the operand of sizeof, that is, instead of sizeof (struct student), the variable which holds the address of the allocation is used. sizeof only uses the type of the expression *studentp, so this variable is not dereferenced here. Coding this way is less error-prone and easier to maintain when types change during the maintenance life of the code.
Yet, it is unclear why memory is allocated for studentp in the first place. In the posted code, both the firstName and AverageNum fields are filled for members of the dynamically allocated studentp in calls to StudentScan() in a loop; the same loop fills the AverageNum field of the members of list[] (a different array of structs) with different input. There seems to be no need for one of these arrays of student structs; I have commented-out the dynamically allocated array in favor of the statically allocated version.
Here is the modified code:
#include <stdio.h>
#include <stdlib.h>
struct student {
char firstName[20];
float AverageNum;
};
void StudentScan(int, struct student[]);
void StudentPrint(int, struct student[]);
int main(void) {
int i;
int length;
// struct student *studentp;
printf ("\nEnter the host of students: ");
while (scanf ("%d", &length) < 1) {
puts("Please enter a number");
int c;
while ((c = getchar()) != '\n' && c != EOF) {
continue;
}
}
struct student list[length];
/* This is fine */
// studentp = malloc(length * sizeof (struct student));
/* But this is better */
// studentp = malloc(length * sizeof *studentp);
// if (studentp == NULL)
// {
/* Not wrong, but... */
// printf("Out of memory!");
// return 0;
// fprintf(stderr, "Allocation failure\n");
// exit(EXIT_FAILURE);
// }
for(i = 0; i < length; i++) {
StudentScan(i, list);
}
/* Code to display results here */
// free (studentp);
return 0;
}
void StudentScan(int i, struct student list[])
{
putchar('\n');
printf("Enter first name: ");
if (scanf("%19s", list[i].firstName) != 1) {
puts("Input error");
exit(EXIT_FAILURE);
}
printf("Enter average number: ");
while (scanf("%f", &list[i].AverageNum) < 1) {
puts("Please enter a number");
int c;
while ((c = getchar()) != '\n' && c != EOF) {
continue;
}
}
}
You have to remove the scan function from the main. Also there is not a printstudent function you are declaring. You must remove /n from the printf and the scanf functions and place them accordingly. You can then test if your data are being added correctly in your struct with a simple loop.
#include <stdio.h>
#include <stdlib.h>
struct student {
char firstName[20];
char AverageNum[2];
};
int main() {
int i=0;
int length;
struct student *studentp;
printf ("Enter the host of students:");
scanf ("%d", &length);
struct student list[length];
studentp=malloc(length*sizeof(struct student));
if (studentp==NULL)
{
printf("Out of memory!");
return 0;
}
for(i = 0; i < length; i++) {
printf("Enter first name :");
scanf("%s", list[i].firstName);
printf("Enter average number: ");
scanf("%1s", list[i].AverageNum);
}
for(i = 0; i< length; i++){
printf("number of host is: %d , his/her first name: %s , his/her avg number: %s \n", i, list[i].firstName, list[i].AverageNum);
}
free (studentp);
return 0;
}
I keep getting this error when I try to run a piece of code say that the variable is being used which isn't initialized, despite I've declared it.
{
FILE *fptr;
int length;
int number_search;
struct student
{
char surname[15];
char initials[6];
char title[4];
int student_number;
char module_name[25];
char module_code[7];
int assesment_mark;
int exam_mark;
int tuition_fee;
};
struct student record_student;
struct student *student_ptr;
student_ptr=&record_student;
length=sizeof(struct student);
printf("2 has been called\n");
printf("Enter module code: \n");
scanf("%s", module_code);
clear_buffer(module_code);
printf("%s\n",module_code); /*Test the string entered is 6 charaters, AB1234 format*/
if (! modcheck(module_code)) /*Change this fucntion to a differnt one to check correct format*/
{
printf("Invalid input\n");
}
else
{
printf("input ok\n");
printf("Enter Student Number: \n");
scanf("%d",number_search);
}
it's saying that the int number_search isn't being initialized despite it being in the code above.
Change:
scanf("%d",number_search);
to
scanf("%d", &number_search);
//^See here the address operator
Indeed, number_search is not initialized.
And your call to scanf(3) is wrong. It should be
scanf("%d", &number_search);
and even with that correction, number_search is still uninitialized: scanf can fail (e.g. if your user types hello or Ctrl D on Linux) and you should test the result of scanf (number of successfully read items), at least:
if (scanf("%d", &number_search) != 1) {
perror("number_search input failure"); exit(EXIT_FAILURE);
}
I believe that you should always explicitly initialize local variables (if that initialization happens to become useless, the compiler would optimize it out), like
int number_search = 0;
PS. You should compile with all warnings and debug info, e.g. gcc -Wall -Wextra -g; once you are sure of not having bugs, add -O2 to get optimizations.
printf("Enter module code: \n");
scanf("%s", module_code);
This should be
printf("Enter module code: \n");
scanf("%s", student_ptr->module_code);
and
scanf("%d", &number_search);
Scan to the address of the variable which is given by &number_search
I'm trying to save a student's name in a char array and print the first student's name, but my code doesn't work. I'm practicing C, so I'm coding random programs by myself and need help with this one. My code generates the following error:
format '%s' expects argument of type 'char *', but argument 2 has type 'int'
I'm quite new to C. Can anyone help?
Code:
#include <stdio.h>
#include <string.h>
main(){
char StudentsName[100];
float StudentsGrades[100];
int NumStudents, i, j;
printf("How many students you want to process? ");
scanf("%d", &NumStudents);
if(NumStudents > 15){goto skip_lines_grades;}
for(i=0; i<NumStudents; i++){
printf("\n Write the name of the student: ");
scanf("%s", &StudentsName[i]);
}
//Prints First Student, I'M GETTING THE ERROR HERE, WHY?
printf("%s", StudentsName[0]);
goto skip_last_msg;
skip_lines_grades:;
printf("We can process 15 students for now, try again.");
skip_last_msg:;
}
I hope you got the basic idea from the discussion above. To summarize, you need to define an array of 100 character variables.
Also, regarding your error, for char StudentsName[100];, StudentsName[0] represents the first char variable value, not an address, as expected by %s. So, your compiler is right. If you need to print a char, you need to use %c specifier. However, that also is wrong, considering your program logic.
To correct, you can
allocate an array of char [100] type, to hold more than one student's data.
allocate memory dynamically.
loop over to take the input for each student.
print the output.
free the allocated memory.
check the modified code, its self-explanatory.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NAMESIZ 128
int main(){
char *StudentsName[100]; //notice here
float StudentsGrades[100];
int NumStudents, i, j;
printf("How many students you want to process? ");
scanf("%d", &NumStudents);
if(NumStudents > 15){goto skip_lines_grades;}
for(i=0; i<NumStudents; i++){
StudentsName[i] = malloc(NAMESIZ); //notice here
printf("\n Write the name of the student: ");
scanf("%s", StudentsName[i]); //notice here
}
//for(i=0; i<NumStudents; i++) //uncomment to print all student data
i = 0; //comment out to print all student data
printf("Student [%d] is %s\n", (i+1), StudentsName[i]);
for(i=0; i<NumStudents; i++)
free (StudentsName[i]); //notice here
goto skip_last_msg;
skip_lines_grades:;
printf("We can process 15 students for now, try again.");
skip_last_msg:;
}
I am new to C and have been trying to get this simple code run which makes use of pointers to struct for calculating the average of grades entered. After entering the maths grade, the program throws an error and stops. What am I doing wrong.
Its also my first post in here, so please bear with me for any inconsistencies. Thanks!
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
char *name;
int mathGrade,scienceGrade,historyGrade,englishGrade;
}reportCard;
void average(reportCard *rc)
{
int avg = (rc->mathGrade +rc->scienceGrade+rc->historyGrade+rc->englishGrade)/4;
printf("The overall grade of %s is: %i ",rc->name, avg);
}
int main()
{
reportCard rc;
printf("Enter the Students Last name: ");
char studentName[20];
scanf("%s", studentName);
rc.name=studentName;
printf("Math Grade: \n");
scanf("%i", rc.mathGrade);
printf("Science Grade: \n");
scanf("%i", rc.scienceGrade);
printf("History Grade: \n");
scanf("%i", rc.historyGrade);
printf("English Grade: \n");
scanf("%i", rc.englishGrade);
average(&rc);
return 0;
}
You get an error because reading primitives with scanf requires pointers:
scanf("%i", &rc.mathGrade);
scanf("%i", &rc.scienceGrade);
// ^
// |
// Here
// ...and so on
scanf thinks that an uninitialized int that you pass is a pointer, and tries to write it, which results in an error.
In addition, you need to protect against buffer overruns on reading strings, like this:
scanf("%19s", studentName); // you allocated 20 chars; you need one for null terminator
This is a homework question. My compiler is CodeBlocks.
Here is my code :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Address{
char number[5];
char street[30];
char city[30];
};
struct Employee{
char ID[7];
char name[31];
struct Address *addr;
};
int main(){
int n,i;
char temp[7];
printf("Enter number of Employee : ");
scanf("%d",&n);
struct Employee **p=(struct Employee **)malloc(n*sizeof(struct Employee *));
for (i=0; i<n; i++)
{
p[i]=(struct Employee *)malloc(sizeof(struct Employee));
p[i]->addr=(struct Address *)malloc(sizeof(struct Address));
}
for(i=0; i<n; i++)
{
printf("Employee #%d\n",i+1);
printf("Enter ID : ");
gets(p[i]->ID);
printf("Enter Name : ");
gets(p[i]->name);
printf("Enter Home number : ");
gets(p[i]->addr->number);
printf("Enter Street : ");
gets(p[i]->addr->street);
printf("Enter City : ");
gets(p[i]->addr->city);
}
}
My problem is that when I run this code, I cannot enter the ID for the #1 employee; however, I can enter in the ID for employee #2 and #3.
Where is my problem?
There seems to be some issue with gets() reading something from the console before the first pass of the loop.
Adding gets(temp); right before the loop seems to fix it. A better solution would be to use something other than gets().
The initial scanf("%d", &n); doesn't consume the trailing newline, so it's left available for the gets() call.
Incidentally, never use gets(). It cannot be used safely. For example, if you're reading into a 6-byte array, and the user enters 10 characters, you have a buffer overflow. Consider using fgets() instead (but note that, unlike gets(), it leaves the '\n' character in the buffer).
You should ever explicit clear the input buffer after any user-input. And you should make your inputs safe with size limiter. And you should use the return value from scanf.
scanf("%d",&n);while(getchar()!='\n');
...
scanf("%6[^\n]",p[i]->ID);while(getchar()!='\n');
...
scanf("%30[^\n]",p[i]->name);while(getchar()!='\n');
...
scanf("%4[^\n]",p[i]->addr->number);while(getchar()!='\n');
...
scanf("%29[^\n]",p[i]->addr->street);while(getchar()!='\n');
...
scanf("%29[^\n]",p[i]->addr->city);while(getchar()!='\n');