Stack crashed when pushed value to a struct - c

Hey guys im learning c and im currently working on stack, structure and pointer. Im using visual studio to do my the program and whenever i enter my input the program will crash. I'm able to scope down that the error is coming from the product name. I am also quite confused since it includes pointer character. Anyone can point out my mistakes? thank you
HERE ARE MY CODES
#include<stdio.h>
#include<string.h>
#define MAX 10
int top = -1;
struct Product {
int prodId;
char *prodName;
};
struct Product arrP[MAX];
struct Product pop();
void push(int id, char *name);
int isFull();
int isEmpty();
struct Product pop()
{
struct Product temp;
temp = arrP[top];
top--;
return temp;
}
void push(int id, char *name)
{
top++;
arrP[top].prodId = id;
strcpy(arrP[top].prodName,name);
}
int isFull()
{
if (top == MAX)
return 1;
else
return 0;
}
int isEmpty()
{
if (top == -1)
return 1;
else
return 0;
}
int main()
{
int myID;
char *myName;
//Push the value
printf("Enter the Product id: ");
scanf("%d", &myID);
printf("Enter the Product Name: ");
scanf("%s", &myName);
push(myID, &myName);
printf("%d %s", arrP[top].prodId ,arrP[top].prodName);
}

There are few simple bugs which you can avoid my listening to compiler warning while compiling with -Wall flag.
Case 1:- variable myId suppose to be a integer variable, not a pointer variable. If you want it to be pointer variable then you should allocate memory for it first.
int *myID;
printf("Enter the Product id: ");
scanf("%d", &myID);
Replace with
int myID;
printf("Enter the Product id: ");
scanf("%d", &myID);
Case 2:- variable myName supposed to be array of characters as you want to store product name into it.
char myName;
printf("Enter the Product Name: ");
scanf("%s", &myName);
Replace with
char myName[50];
printf("Enter the Product Name: ");
scanf("%s", myName);
While calling push() function just pass the myName. For e.g
push(myID, myName);
Also this statement
strcpy(arrP[top].prodName,name);
causes problem as prodName is pointer member in of structure, you should allocate memory dynamically for this and then do copy.
arrP[top].prodName = malloc(SIZE);
strcpy(arrP[top].prodName,name);

When you are getting the input using %s in character type variable, the memory adjacent to the address of the char variable gets overwritten thus can cause program crash. if you want to enter a string, you can try it by defining an array of characters (as char my name[MAX], MAX can be a size suitable to you).

Related

Structure function pointer parameter?

Fields of Student:​ name, lastName, studentId, mid1Grade, mid2Grade, finalGrade, average
Fields of Course:​ courseName, courseCode, myStudentArray (array of Student structures),currentStudentCount
Functions:
void createNewStudent(struct Course *myCourse);
void setGradeOfStudent(struct Course *myCourse);
void findAndDisplayAverage(struct Course *myCourse);
struct Student * findStudentByID(int id, struct Course *myCourse);
void displayAverageOfAllStudents(struct Course *myCourse);
void displayAverageOfStudentsInInterval(struct Course *myCourse
ok so I have written the first function but there is an error which I dont understand. First of all the first function and what it does:
createNewStudent:​ Prompt the user to enter name, last name and id of the new student.Values entered by the user are assigned to the fields of the student residing in themyStudentArray ​of course variable pointed by ​myCourse​. ​currentStudentCount ​will be updated so that it designates the slot allocated for the student inserted next.
and my implementation:
#include <string.h>
#include <stdio.h>
struct Student {
char name[50];
char lastname[50];
int id;
int mid1;
int mid2;
int final;
double average;
};
struct Course {
char courseName[50];
char courseCode[50];
struct Student myStudentArray[5];
int currentstudentcount;
};
void createNewStudent(struct Course * myCourse);
void setGradeOfStudent(struct Course * myCourse);
void findAndDisplayAverage(struct Course * myCourse);
struct Student * findStudentByID(int id, struct Course * myCourse);
void displayAverageOfAllStudents(struct Course * myCourse);
void displayAverageOfStudentsInInterval(struct Course * myCourse);
int main() {
struct Student * stud;
int input = 0;
scanf("%d", & input);
if (input == 1) {
createNewStudent(struct Course * myCourse);
}
}
return 0;
}
void createNewStudent(struct Course * myCourse) {
struct Student s1;
printf("Enter name: ");
scanf("%[^\n]%*c", s1.name);
printf("Enter Surname: ");
scanf("%[^\n]%*c", s1.lastname);
printf("Enter id: ");
scanf("%d", & s1.id);
}
When you call the function with the if(input == 1) it gives
error: expected expression before ‘struct’
but I dont understand this beacuse *myCourse is just a pointer to the Course struct isn't it ????
If I can understand this ı will be able to the the next functions I think
Is the function correct ?? I dont know why this doesnt work
Ok I tried to use the struct Student myStudentArray[5]; to get name, lastname,id like so (structs are the same)
void createNewStudent(struct Course *myCourse);
void setGradeOfStudent(struct Course *myCourse);
int main(){
struct Course *myCourse;
int input=0;
scanf("%d",&input);
if(input == 1){
createNewStudent(myCourse);
}
return 0;
}
void createNewStudent(struct Course *myCourse){
myCourse->currentstudentcount=0;
printf("Enter name: ");
scanf("%[^\n]%*c"
,myCourse->myStudentArray[myCourse->currentstudentcount].name);
printf("Enter Surname: ");
scanf ("%[^\n]%*c",
myCourse->myStudentArray[myCourse->currentstudentcount].name);
myCourse->currentstudentcount++;
}
I Keep getting
may be used uninitialized in this may be used uninitialized in this function [-Wmaybe-uninitialized]
and
Segmentation errors
void createNewStudent(struct Course * myCourse)
If you want to create new student, you should use the student struct as the parameter of this function instead of using struct Course.
void createNewStudent(struct Student *s1)
Then, this function becomes as:
void createNewStudent(struct Student *s1) {
printf("Enter name: ");
scanf("%49s", s1->name);
printf("Enter Surname: ");
scanf("%49s", s1->lastname);
printf("Enter id: ");
scanf("%d", & s1->id);
}
If you want to test, in main function, you can declare the value stud or the pointer to struct Student.
For example:
int main() {
struct Student stud;
int input = 0;
scanf("%d", & input);
if (input == 1) {
createNewStudent(&stud);
printf("name: %s\n Surname: %s\n id = %d\n", stud.name, stud.lastname, stud.id);
}
return 0;
}
The complete program for test:
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
struct Student {
char name[50];
char lastname[50];
int id;
int mid1;
int mid2;
int final;
double average;
};
struct Course {
char courseName[50];
char courseCode[50];
struct Student myStudentArray[5];
int currentstudentcount;
};
void createNewStudent(struct Student *s1);
int main() {
struct Student stud;
int input = 0;
scanf("%d", & input);
if (input == 1) {
createNewStudent(&stud);
printf("name: %s\nSurname: %s\nid = %d\n", stud.name, stud.lastname, stud.id);
}
return 0;
}
void createNewStudent(struct Student *s1) {
printf("Enter name: ");
scanf("%49s", s1->name);
printf("Enter Surname: ");
scanf("%49s", s1->lastname);
printf("Enter id: ");
scanf("%d", & s1->id);
}
The output:
#./test
1
Enter name: abc
Enter Surname: def
Enter id: 100
name: abc
Surname: def
id = 100
Update for your question in the comment:
If you want to store student info in an array, you can change the code to:
struct Student myStudentArray[5];
int input = 0;
scanf("%d", & input);
if (input == 1) {
for (int i = 0; i < 5; i++) {
createNewStudent(&myStudentArray[i]);
}
for (int i = 0; i < 5; i++) {
printf("name: %s\nSurname: %s\nid = %d\n", myStudentArray[i].name, myStudentArray[i].lastname, myStudentArray[i].id);
}
}
For Course structure you can create one function as the function createNewStudent but for struct Course to create the new course. After creating new 5 students (for example the code above), you can copy the myStudentArray to new_course.myStudentArray. Then now you have the info of 5 students in new_course. When you copy value from an array to another, you can use memcpy or using one loop to copy each element from one array to another one. Do not use something like myStudentArray = new_course.myStudentArray for the array.
You are making a declaration as a parameter of the createNewStudent() function. In C, functions require expressions as parameters, which is why you got the error message "expected expression...".
So, just create the struct pointer before you call the function:
if (input == 1) {
struct Course *myCourse = malloc(sizeof(struct Course));
createNewStudent(myCourse);
}
Notice the use of malloc(), which returns a pointer to a place in memory of sufficient size to hold that particular Course struct. When dealing with pointers to structs, you need to allocate memory for the structs that will ultimately be pointed to, in order to avoid dereferencing unallocated regions of memory.
In your function CerateNewStudent, the proper way to address the variables into which to place the data read by scanf should be:
myCourse->myStudentArray[myCourse->currentstudentcount].name
as the variable to read name into. Use this syntax for all data items to read. After that, increment the counter:
myCourse->currentstudentcount++;
Note: what is missing in all your functions (and in the assignment?) is a way to create a course. The students created are all added to courses. First a course should be created and then students can be added to it.

I cannot store integer in structure

I created a struct Book with the properties.I let the user to create the structure objects with for-loop.Like Books[i] Books1, Books2 etc...
The problem is that i cant store integer values in the structure.
The code is given below.
#include <stdlib.h>
#include <stdio.h>
struct Book {
int ID[];
char book_name[80];
char author_name[50];
int pblsh_date[];
};
struct Book *Books;
void Create();
int main() {
int count;
printf("How many books do you want to enter? ");
scanf("%d", &count);
Create(count);
//Show
printf("ID\t\tName\tAuthor\tPublish Year\n");
for (int i= 0; i < count; i++)
printf("%d\t%s\t%s\t%d\n", Books[i].ID, Books[i].book_name, Books[i].author_name, Books[i].pblsh_date);
if (Books) {
free(Books);
}
getchar();
return 0;
}
void Create(int count) {
Books = (struct Book*) malloc(count * sizeof(struct Book));
int i;
for (i = 0; i < count; i++) {
printf("%d. Book's ID: ", i+1);
scanf("%d", Books[i].ID);
printf("Book's name: ");
scanf("%s", Books[i].book_name);
printf("Author: ");
scanf("%s", Books[i].author_name);
printf("Publish Year: ");
scanf("%d", Books[i].pblsh_date);
}
}
The definition of the structure that you posted contains two empty arrays: int ID[]; and int pblsh_date[];. Since you did not specify a size and the compiler is not throwing an error, it is not allocating any storage for the array data: the arrays are zero-length and you are overwriting the data that follows them when you scanf into them.
Since you only want a single integer, the correct way to define the structure is
struct Book {
int ID;
char book_name[80];
char author_name[50];
int pblsh_date;
};
The only other change you need to make to your program is the arguments to scanf: scanf("%d", &(Books[i].ID)); and scanf("%d", &(Books[i].pblsh_date));. The reason is that scanf requires the address of the place you want to put the result. While scanf("%s", Books[i].book_name); works as is, you need to add the & operator to int variables. book_name is an array, which in C is treated as a pointer containing the address of the buffer you want to write to. ID is an int, so you need to get its address to know where to write to. Notice how you already did this in main with scanf("%d", &count);.

How to accept character array input into a structure in C?

I've got this structure, a simple one that holds student name and marks. When I'm trying to read user input into the name(char array), I get a warning indicating something on the lines of :
format %s expects char *, but has char*[20]
I know this is because char arrays cannot be assigned in C, so strcpy has to be used. This question on SO has a good reasoning. However,how do I fix the warning in my program? Don't think I can use strcpy here.
#include <stdio.h>
typedef struct _student
{
char name[20];
unsigned int marks;
} student;
void read_list(student list[], int SIZE);
void print_list(student list[], int SIZE);
int main()
{
const int SIZE=3;
student list[SIZE];
//function to enter student info.
read_list(list, SIZE);
//function to print student info
print_list(list, SIZE);
return 0;
}
void read_list(student list[], int SIZE)
{
int i;
char nm[20];
for (i=0;i<SIZE;i++)
{
printf("\n Please enter name for student %d\n", i);
scanf("%s",&list[i].name);
printf("\n Please enter marks for student %d\n", i);
scanf("%u", &list[i].marks);
}
}
void print_list(student list[], int SIZE)
{
int i;
printf("\t STUDENT NAME STUDENT MARKS\t \n");
for(i=0;i<SIZE;i++)
{
printf("\t %s \t %u\n", list[i].name, list[i].marks);
}
}
The program does give a correct output, but the warning remains.
Try this code:
for (i=0;i<SIZE;i++)
{
printf("\n Please enter name for student %d\n", i);
scanf("%s",list[i].name);
printf("\n Please enter marks for student %d\n", i);
scanf("%u", &list[i].marks);
}
This is because & used in scanf statement is to get the address.
In your case you use array name i.e. name and array name itself is providing the address. Remember array name gives the base address of an array.
change scanf("%s",&list[i].name); to scanf("%s",list[i].name);. Delete &. Because basically array name represents base address. No need to mention address of array for scanning the string.
Remove the & in the scanf that scan in a string using %s to eliminate the warning. So change
scanf("%s",&list[i].name);
to
scanf("%s",list[i].name);
This is because the name of the char array decays to a pointer to its first element
line 33:
scanf("%s",&list[i].name);//wrong
scanf("%s",list[i].name);//right
The name of an array is synonym for the location of the initial element , thus in your code, variable 'name' is the address of name[0]. You don't need to use & on 'name' to get the address of the array.Just use 'name' itself.

Pointer to an array of structures

I'm currently trying to write a program for a student database assignment. After manually setting 3 elements of the structure array, the next 3 students' details are inputted by the user.
I am trying to write a function that finds the oldest age of the 6 students and returns it as a student_t entry at index max. I'm struggling with how to actually give the function the pointer that is pointing to the first element of the array stdt[6] and then using the pointer within the function. I also have no idea how I would go about returning to main the entry that has the highest age. If I'm trying to say that the value of an element of array of structures is equal to some other integer (max), doesn't that mean that max is now some other block of memory with an integer value and not linked to the array? So I'm not sure how I would return the entry that has the highest age after the function determines the max age.
This is all I've written so far:
#include <stdlib.h>
#include <stdio.h>
typedef struct {
char *name;
char *surname;
char *UUN;
char *department;
char gender;
int age;
}student_t;
student_t findOldest(student_t *studentarr, int len){
int i;
int x;
int max;
max=0;
for(i=0;i<len;i++){
(p+i).age=x;
if(x>max){
x=max;
}
}
}
int main() {
int i;
student_t stdt[6]={{"John","Bishop","s1234","Inf",'m',18},{"Lady","Cook","s2345","Eng",'f',21},{"James","Jackson","s33456","Eng",'m',17}};
student_t *p=&stdt[0];
for(i=3;i<6;i++) {
printf("First name: \n");
scanf("%s",stdt[i].name);
printf("Last name: \n");
scanf("%s",stdt[i].surname);
printf("UUN: \n");
scanf("%s",stdt[i].UUN);
printf("Department: \n");
scanf("%s",stdt[i].department);
printf("Gender (m/f): \n");
scanf("%c",stdt[i].gender);
printf("Age: \n");
scanf("%d",stdt[i].age);
}
findOldest(p,6);
return 0;
}
This should work.
student_t findOldest(student_t *p, int len){
int i;
student_t max = *(p+0);
for(i=1;i<len;i++)
{if((*(p+i)).age > max.age)
max = *(p+i);
}
return max;
}
You want to return the student so keep the student in your max variable not the age. And to refer to pointers either use
(p+i)->age > max.age
or use
(*(p+i)).age > max.age
But there are other problems with the code.

Program with array of structs crashes

I have an array with multiple structs. When i ask the user to enter data the first time everything works but when i ask again for the next position in the array the program crashes. If this method doesn't work souldn't the program crash in the beginning? Is something wrong with malloc?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct student {
char name[50];
int semester;
};
struct prof {
char name[50];
char course[50];
};
struct student_or_prof {
int flag;
int size;
int head;
union {
struct student student;
struct prof prof;
}
}exp1;
struct student_or_prof *stack;
void init(int n)
{
stack = malloc(n);
}
int push(struct student_or_prof **pinx,int *head,int n)
{
char name[50];
printf("\nn= %d\n",n);
printf("\nhead= %d\n",*head);
if(*head==n)
{
printf("Stack is full.\n");
return 1;
}
char x;
printf("Student or Professor? [s/p] ");
getchar() != '\n';
scanf("%c",&x);
if(x=='s')
{
getchar() != '\n';
pinx[*head]->flag = 0;
printf("\n\nGive student's name: ");
fgets(pinx[*head]->student.name,sizeof(pinx[*head]->student.name),stdin);
printf("\nGive student's semester: ");
scanf("%d",&(pinx[*head]->student.semester));
printf("\nName = %s\tSemester = %d",pinx[*head]->student.name,pinx[*head]->student.semester);
}
else if(x=='p')
{
getchar() != '\n';
pinx[*head]->flag = 1;
printf("\n\nGive professor's name: ");
fgets(pinx[*head]->prof.name,sizeof(pinx[*head]->prof.name),stdin);
printf("\nGive course: ");
fgets(pinx[*head]->prof.course,sizeof(pinx[*head]->prof.course),stdin);
printf("\nName = %s\tCourse = %s\n",pinx[*head]->prof.name,pinx[*head]->prof.course);
}
(*head)++;
printf("\nhead= %d\n",*head);
}
int main()
{
int n,i;
printf("Give size: ");
scanf("%d",&n);
init(n);
for(i=0;i<n;i++)
push(&stack,&exp1.head,n);
return 0;
}
You need to malloc the structure not n
malloc(sizeof(struct student_or_prof)*n)
EDIT:
And your code crashes again because pinx is a double pointer, so this operation is not valid:
pinx[*head]->flag = 0;
this is equivalent to:
*(pinx + *head)->flag = 0;
Since you are not changing what stack points to, you are better off using a single pointer instead of a double pointer.
So instead you should change your push API:
int push(struct student_or_prof *pinx,int *head,int n)
and call it like:
push(stack,&exp1.head,n);
malloc allocates the given number of bytes.
You have to multiply n with the size of your struct, to allocate enough memory.
pinx does not point to an array, so pinx[*head] is going to access invalid memory unless *head is zero.
I think you meant (*pinx)[*head] , which accesses the N-th element of the array you allocated via malloc. For example (*pinx)[*head].prof.name etc.
BTW, your head number doesn't seem to be used at all, except for exp1.head, maybe it'd be better to remove head from the struct, and just have a single variable head?

Resources