How to fill the array in the main function? - c

I found online the following program using struct and functions.
We call a function that fills the array. Inside the function there is the for-loop that inserts the elements that the user gives.
#include <stdio.h>
// student structure
struct student {
char id[15];
char firstname[64];
char lastname[64];
float points;
};
// function declaration
void getDetail(struct student *);
int main(void) {
// student structure variable
struct student std[3];
// get student detail
getDetail(std);
return 0;
}
// function definition
void getDetail(struct student *ptr) {
int i;
for (i = 0; i < 3; i++) {
printf("Enter detail of student #%d\n", (i + 1));
printf("Enter ID: ");
scanf("%s", ptr->id);
printf("Enter first name: ");
scanf("%s", ptr->firstname);
printf("Enter last name: ");
scanf("%s", ptr->lastname);
printf("Enter Points: ");
scanf("%f", &ptr->points);
// update pointer to point at next element
// of the array std
ptr++;
}
}
}
Is it possible to call the function "getDetail" repetitively in the main to fill the array instead of having the loop inside the function? I mean to have the for-loop in the main instead of inside the function?
I tried the following:
#include <stdio.h>
// student structure
struct student {
char id[15];
char firstname[64];
char lastname[64];
float points;
};
// function declaration
void getDetail(struct student *);
int main(void) {
// student structure variable
struct student std[3];
// get student detail
for (i = 0; i < 3; i++) {
printf("Enter detail of student #%d\n", (i + 1));
getDetail(std);
}
return 0;
}
// function definition
void getDetail(struct student *ptr) {
printf("Enter ID: ");
scanf("%s", ptr->id);
printf("Enter first name: ");
scanf("%s", ptr->firstname);
printf("Enter last name: ");
scanf("%s", ptr->lastname);
printf("Enter Points: ");
scanf("%f", &ptr->points);
// update pointer to point at next element
// of the array std
ptr++;
}
But it seems that this doesn't work. What do I have to change?
In the "getDetail" function why when the input is an array we do not use the symbol "&" and when the input is not array we use it?
So why we use only "&" before ptr->points?
Which is the difference?

ptr++; in the getDetail function will update the local variable ptr and it will vanish on returning from the function.
Have getDetail do only getting detail, and have main switch the element to receive the data.
#include <stdio.h>
// student structure
struct student {
char id[15];
char firstname[64];
char lastname[64];
float points;
};
// function declaration
void getDetail(struct student *);
int main(void) {
// student structure variable
struct student std[3];
struct student* ptr = std;
// get student detail
for (i = 0; i < 3; i++) {
printf("Enter detail of student #%d\n", (i + 1));
getDetail(ptr);
// update pointer to point at next element
// of the array std
ptr++;
}
return 0;
}
// function definition
void getDetail(struct student *ptr) {
printf("Enter ID: ");
scanf("%s", ptr->id);
printf("Enter first name: ");
scanf("%s", ptr->firstname);
printf("Enter last name: ");
scanf("%s", ptr->lastname);
printf("Enter Points: ");
scanf("%f", &ptr->points);
}

Related

Why does my output gives a garbage value?

I am learning structure and function and I'm trying to pass a pointer to structure as an argument. My code is to input student name,age and marks. This is my program
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
struct student {
char name[15];
int age;
double marks;
};
void display();
int main(){
struct student *s1;
s1 =(struct student *) malloc(sizeof(struct student));
for(int i=0; i<2; i++)
{
printf("\nEnter details of student %d\n\n", i+1);
printf("Enter name: ");
scanf("%s", s1->name);
printf("Enter age: ");
scanf("%d", &s1->age);
printf("Enter marks: ");
scanf("%f", &s1->marks);
}
display(&s1);
}
void display(struct student *s1){
printf("\nName\tAge\tMarks\n");
for(int i = 0; i<2;i++ )
{
printf("Name: %s",s1->name);
printf("\nAge: %d",s1->age);
printf("\nMarks: %.2lf",s1->marks);
}
}
the code runs but it gave a wrong outputs and garbage value. What did i do wrong?
There are several syntax error. I have included documentation in the code below.
Also, you are overwriting the content of s1 everytime when you are prompting user to input. Test it with two different data for example (name: "alex", age: 19, mark: 100.0 and name: "jason", age: 22, mark: 100.0) your program will output only the later.
To solve this, I would suggest you to allocate your student pointer before looping so that you have two distinct memory for each student and you wont overwrite them in this case.
Basically, each student struct is treated as an array and instead of s1->name you will dereference them as s1[i].name
display function declaration
void display(struct student *s1);
main function
int main()
{
int i;
struct student *s1;
s1 =(struct student *) malloc(sizeof(struct student) * 2); /* 2 = number of students */
for(i=0; i<2; i++)
{
printf("\nEnter details of student %d\n\n", i+1);
printf("Enter name: ");
scanf("%s", s1[i].name);
printf("Enter age: ");
scanf("%d", &s1[i].age);
printf("Enter marks: ");
scanf("%lf", &s1[i].marks); /* Instead of %f, it should be %lf */
}
display(s1); /* Instead of &, it should be s1 */
/* Free heap memory */
for(i=0; i<2; i++)
{
free(s1);
s1 = NULL;
}
return 0;
}
Display function, you need some modification in your display function as well
void display(struct student *s1)
{
int i;
printf("\nName\tAge\tMarks\n");
for(i = 0; i<2;i++ )
{
printf("%s\t",s1[i].name);
printf("%d\t",s1[i].age);
printf("%.2f\t",s1[i].marks); /* Instead of %.2lf, it should be %.2f */
printf("\n");
}
}
Struct for student
struct student
{
char name[15];
int age;
double marks;
};

Structures and arrays in C

I must create a program focusing on the use of structures.
The program will ask the user to enter the number of students for whom he will later add specific information (name, surname, average grade).
For some reason, when I start the the program, I enter the number of students i want, after that I enter the info of the first student and then the program terminates.
Here's what I've tried.
#include <stdio.h>
#include <stdlib.h>
struct student
{
char *name;
char *surname;
float *average;
};
void inputs(struct student *a, int size);
int main()
{
int size;
printf("Enter the number of students: ");
scanf("%d", &size);
struct student *data;
data = (struct student *)malloc(size*sizeof(struct student));
if(data==NULL) {
printf("Cannot allocate memory. The program will now terminate.");
return -1;
}
inputs (data, size);
return 0;
}
void inputs(struct student *a, int size)
{
int j=0;
int i;
for(i=0; i<size; i++) {
printf("Enter the name of the student number %d: ", j+1);
scanf("%s", a->name);
printf("Enter the surname of the student number %d: ", j+1);
scanf("%s", a->surname);
printf("Enter the average grade of the student number %d: ", j+1);
scanf("%f", a->average);
j++;
a++;
}
}
This code works:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct student
{
char name[30];
char surname[30];
float average;
};
void inputs(struct student *a, int size);
int main()
{
int size;
int i=0; // we need i
char string[100];
printf("Enter the number of students: ");
// scanf can be tricky lets use fgets
fgets( string , 99 , stdin );
size= atoi(string);
struct student **data; // array of struct
// get memory for the pointers to pointer
data=(struct student **) calloc( size , sizeof(char *));
// now each struct need space
for( i=0 ; i<size ; i++)
{
data[i] = malloc(sizeof(struct student));
if(data[i]==NULL) {
printf("Cannot allocate memory. The program will now terminate.");
return -1;
}// end if
}// end for loop
// input each student
for( i=0 ; i<size ; i++)
inputs (data[i], i );
return 0;
}
void inputs(struct student *a, int num)
{
int j=0;
char string[100];
// scanf can be tricky lets use fgets
printf("Enter the name of the student number %d: ", num+1);
fgets(a->name, 29, stdin);
printf("Enter the surname of the student number %d: ", num+1);
fgets( a->surname , 29, stdin);
printf("Enter the average grade of the student number %d: ", num+1);
fgets( string , 99, stdin);
a->average=atof(string);
}

How to allocate memory to a typedef struct within array of structs

I have been trying to allocate memory to the pointer variable but it keeps giving me errors or segmentation fault. How do i properly initialize the pointer variable to the course struct?
typedef struct {
char courseId[7];
char courseName[10];
} Course;
struct Student{
char firstName[10];
char lastName[10];
int studentId;
Course *course;
};
int main() {
int numStudents;
printf("How many students do you wish to register?: ");
scanf("%d", &numStudents);
struct Student *student[numStudents];
student[numStudents] = malloc(sizeof(*student[numStudents]));
student[numStudents]->course = malloc(sizeof*(numStudents * Course));
for (int i = 0; i < numStudents; i++) {
printf("Enter student #%d First Name: ", i+1);
scanf("%s", student[i]->firstName);
printf("Enter student Last Name: ");
scanf("%s", student[i]->lastName);
printf("Enter Student ID: ");
scanf("%d", &student[i]->studentId);
printf("Enter Course ID: ");
//student[i]->course = malloc(sizeof(*(student[i]->course)));
scanf("%s", student[i]->course->courseId);
printf("Enter Cousrse Name: ");
//student[i]->course = malloc(sizeof(*(student[i]->course)));
scanf("%s", student[i]->course->courseName);
}
for (int i = 0; i < numStudents; i++) {
printf("Student Name: %s %s\n", student[i]->firstName, student[i]->lastName);
printf("Student ID: %d\n", student[i]->studentId);
printf("Course Code: %s\n", student[i]->course->courseId );
printf("Course name: %s\n", student[i]->course->courseName);
free(student[i]->course);
}
You almost had it, there was a few corrections that needed to be made.
Course object in Student doesn't need to be a pointer. The array of Student structures need to be dynamically allocated then free'd later on. -> is used as a dereference operator but in your case [] is already dereferencing so you would use . instead of -> and when you allocate memory for the array of structures it needs to be the size of the structure multiplied by the number of structures. malloc(sizeof(struct Student)*numStudents);
typedef struct {
char courseId[7];
char courseName[10];
} Course;
struct Student{
char firstName[10];
char lastName[10];
int studentId;
Course course;
};
int main() {
int numStudents;
printf("How many students do you wish to register?: ");
scanf("%d", &numStudents);
struct Student* students = malloc(sizeof(struct Student)*numStudents);
for (int i = 0; i < numStudents; i++) {
printf("Enter student #%d First Name: ", i+1);
scanf("%s", students[i].firstName);
printf("Enter student Last Name: ");
scanf("%s", students[i].lastName);
printf("Enter Student ID: ");
scanf("%d", &students[i].studentId);
printf("Enter Course ID: ");
scanf("%s", students[i].course.courseId);
printf("Enter Cousrse Name: ");
scanf("%s", students[i].course.courseName);
}
for (int i = 0; i < numStudents; i++) {
printf("Student Name: %s %s\n", students[i].firstName, students[i].lastName);
printf("Student ID: %d\n", students[i].studentId);
printf("Course Code: %s\n", students[i].course.courseId );
printf("Course name: %s\n", students[i].course.courseName);
}
free(students);
return 0;
}
I tried to make minimal changes to your code.

C - Passing a pointer to an array to a function to print the array

I have a code like this for a student management system. The input function works fine but I haven't figured out why my output function stop immediately when i call it.( I know that i can not return a local array from a function in C, but i assign the array to a pointer and return that pointer, is it ok?)
Here is my code:
struct Student
{
char name[50];
char birth[25];
char gender[10];
float math, physics;
};
struct Student* input(int n, struct Student *p)
{
int i, id = 1;
struct Student s[n];
getchar();
for(i = 0; i < n; i++)
{
printf("Name: ");
fgets(s[i].name, 50, stdin);
s[i].name[strlen(s[i].name)-1] = '\0';
printf("Date of birth: ");
fgets(s[i].birth,25,stdin);
s[i].birth[strlen(s[i].birth)-1] = '\0';
printf("Gender: ");
fgets(s[i].gender,10,stdin);
s[i].gender[strlen(s[i].gender)-1] = '\0';
printf("Math = ");
scanf("%f", &s[i].math);
printf("Physics = ");
scanf("%f", &s[i].physics);
getchar();
}
p = s;
return p;
}
void outPut(int n, struct Student *p)
{
int i;
for(i = 0; i < n; i++)
{
printf("%s %s %s %f %f\n", p[i].name, p[i].birth, p[i].gender, p[i].math, p[i].physics);
}
}
int main()
{
int n;
struct Student *p, *p1;
int choice;
printf("-----------Student Management-----------");
printf("\n1. Add new students.\n2. Print student list.\n");
do
{
printf("Your choice = ");
scanf("%d", &choice);
switch(choice)
{
case 1:
printf("Number of students = ");
scanf("%d", &n);
input(n,p);
break;
case 2:
outPut(n,p);
break;
}
}
while(choice!=0);
return 0;
}
You are defining your array as a local variable. It means that it will no longer exist after the function ends. To avoid this, declare your array as a pointer and use malloc to initialize it:
struct Student *s = malloc(sizeof(Student) * n);
It will behave as a regular array and you will be able to use itself as the function return.

I'm trying to create a program with a loop that prompts the user to enter data in the array elements

I'm trying to create a program with a loop that prompts the user to enter data in the array elements. And when the user no longer can enter data, print to screen the data entered in a last in, first out order.
And this is my attempt...
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
struct Name_Age
{
char Name[10];
int Age;
};
void printMe(struct Name_Age info)
{
printf("Name: %s\n", info.Name);
printf("Age: %d\n", info.Age);
}
int main()
{
int size = 0, i = 0, j = 0;
struct Name_Age * array_ptr = (struct Name_Age*)malloc((size + 1)* sizeof(struct Name_Age));
struct Name_Age myInfo = *array_ptr;
printf("Enter size of array: ");
scanf("%d\n", size);
for (i = 0; i < size; ++i)
{
printf("Enter Name: \n");
scanf("%s\n", myInfo.Name);
printf("Enter Age: \n");
scanf("%d\n", myInfo.Age);
}
printMe(myInfo);
return 0;
};
First, scanf("%d", &size) replace scanf("%d\n", size), put &size instead of size as argument(You need an address), and put the malloc things after this line of code, because you need an exact size value before malloc. Same thing with all the scanf stuffs.
As you want to print out all your input names and ages in order, I changed your code like this:
#include <stdio.h>
#include <stdlib.h>
struct Name_Age
{
char Name[10];
int Age;
};
void printMe(struct Name_Age *infoList, int size)
{
int i;
for (i = size-1; i >= 0; --i)
{
printf("Name: %s\n", infoList[i].Name);
printf("Age: %d\n", infoList[i].Age);
printf("\n");
}
}
int main()
{
int size, i;
printf("Enter size of array: ");
scanf("%d", &size);
struct Name_Age * array_ptr = (struct Name_Age*)malloc(size* sizeof(struct Name_Age));
for (i = 0; i < size; ++i)
{
printf("Enter Name: \n");
scanf("%s", array_ptr[i].Name);
printf("Enter Age: \n");
scanf("%d", &array_ptr[i].Age);
}
printMe(array_ptr, size);
return 0;
}
Try to test and compare with your code, questions are welcome.
You can use fgets to read strings and cast the string to digits with atoi. The storage is not complete, but with my changes you can read to structs and specify the size of the loop (TODO: Save a list of structs so that you actually can print a list of structs that you have specified.)
#include <stdio.h>
#include <stdlib.h>
struct Name_Age {
char Name[10];
int Age;
};
void printMe(struct Name_Age info) {
printf("Name: %s\n", info.Name);
printf("Age: %d\n", info.Age);
}
int main() {
int size = 0, i = 0, j = 0;
struct Name_Age *array_ptr = malloc((size + 1) * sizeof(struct Name_Age));
struct Name_Age myInfo = *array_ptr;
printf("Enter size of array: ");
char tmp[10];
fgets(tmp, 10,stdin);
size = atoi(tmp);
for (i = 0; i < size; ++i) {
printf("Enter Name: ");
fgets(myInfo.Name, 10,stdin);
printf("Enter Age: ");
fgets(tmp, 10,stdin);
myInfo.Age = atoi(tmp);
}
printMe(myInfo);
return 0;
};
Test
$ ./a.out
Enter size of array: 2
Enter Name: Superman
Enter Age: 25
Enter Name: Batman
Enter Age: 27
Name: Batman
Age: 27
See also this question about fgets fgets how to read int
Obviously using fgets() is a much better approach, but making the fewest amount of changes as possible to your code and still achieving your result is the following:
#include <stdio.h>
#include <stdlib.h>
struct Name_Age
{
char Name[10];
int Age;
};
void printMe(struct Name_Age *info);
int main(void)
{
int size, i;
struct Name_Age *array_ptr;
printf("Enter size of array: ");
scanf("%d", &size);
array_ptr = malloc(size * sizeof *array_ptr);
for (i = 0; i < size; ++i)
{
printf("Enter Name: ");
scanf(" %s", array_ptr[i].Name);
printf("Enter Age: ");
scanf("%d", &array_ptr[i].Age);
printf("\n");
}
for (i = 0; i < size; ++i)
printMe(&array_ptr[i]);
return 0;
}
void printMe(struct Name_Age *info)
{
printf("Name: %s\n", info->Name);
printf("Age: %d\n", info->Age);
}
Note that passing the struct by pointer to the function should be faster, note that you don't need the myInfo struct; you can just directly modify the elements of the array. Note the space before %s in the scanf() line, this is to discard any whitespace (including \n), this is done automatically for %d so it is only necessary for your strings (technically not the first iteration of the loop, but it doesn't fail if no whitespace is found). If you have any questions about why I made the changes I did, please feel free to comment on this answer!
example of fix
//struct Name_Age myInfo = *array_ptr;//Not necessary
printf("Enter size of array: ");
scanf("%d", &size);//remove `\n`, add `&`
//To ensure after the size has been determined
struct Name_Age * array_ptr = (struct Name_Age*)malloc(size * sizeof(struct Name_Age));//Cast is not necessary in C
for (i = 0; i < size; ++i)
{
printf("Enter Name: \n");
scanf("%s", array_ptr[i].Name);//remove `\n`
printf("Enter Age: \n");
scanf("%d", &array_ptr[i].Age);//need `&`
}
for (i = 0; i < size; ++i)
printMe(array_ptr[i]);

Resources