Assign a string pointer in a struct - c

I'm learning about C and having trouble with this. It does compile but the result is unexpected.
In my code, I have a struct:
typedef struct {
char *title[50];
float price;
} Book;
In the main, I am asking the user for number of books they want to have in the library. Then let them initialize the attributes of each book.
Finally, print them out to the terminal using Display function.
void Display(Book* lib, int n);
int main() {
int n;
printf("Enter the number of books:\n" );
scanf("%d", &n);
if(n <= 0) {
printf("Invalid number of book.");
return 1;
}
Book *lib = (Book *) malloc(n * sizeof(Book));
if(lib == NULL) {
printf("The memory is full");
return 1;
}
for(int i = 0; i < n; ++i) {
char title[50];
float price;
printf("Book no.%d\n", i);
printf("Book Title: ");
scanf("%s", title);
printf("Book Price: ");
scanf("%f", &price);
printf("\n");
*(lib+i)->title = title;
(lib+i)->price = price;
}
Display(lib, n);
return 0;
}
The code compiles successfully, but the result is like this:
Enter the number of books:
2
Book no.0
Book Title: AAAA
Book Price: 1.0
Book no.1
Book Title: BBBB
Book Price: 9.9
----Displaying----
Book no.0
Book Title: BBBB
Book Price: $1.000000
Book no.1
Book Title: BBBB
Book Price: $9.900000
The title of the first book is wrong and it is the title of the second book.
Why does this happen? And how should I fix it?
Thank you
Edit: One of the requirements in my assignment is the title of Book must be of type char*
Edit 2: I realized my mistake when having 50 pointers of type char now. How should I fix it?

In your struct defintion:
typedef struct {
char *title[50];
float price;
} Book;
You don't have an array of char (which can hold a string) but an array of pointers to char each of which can point to a string.
Also, this doesn't do what you expect due to the definition of the price member:
*(lib+i)->title = title;
Change the definition to:
typedef struct {
char title[50];
float price;
} Book;
And read directly into the struct fields instead of temp variables to avoid copying:
printf("Book Title: ");
scanf("%s", lib[i].title);
printf("Book Price: ");
scanf("%f", &lib[i].price);
Alternately, you can define title as a char *:
typedef struct {
char *title;
float price;
} Book;
In which case you have to allocate space for the pointer to point to:
lib[i].title = malloc(50);
printf("Book Title: ");
scanf("%s", lib[i].title);
Note that you can't have it point to a local like you did before because that local goes out of scope at the end of the loop, making the pointer invalid.

If you have to use a pointer, you'll need to use dynamic allocation.
The structure member should be declared as a pointer, not an array of pointers:
typedef struct {
char *title;
float price;
} Book;
Then the loop should allocate memory for a copy of the title, and copy the title into it.
for(int i = 0; i < n; ++i) {
char title[50];
float price;
printf("Book no.%d\n", i);
printf("Book Title: ");
scanf("%s", title);
printf("Book Price: ");
scanf("%f", &price);
printf("\n");
(lib+i)->title = malloc(strlen(title)+1); // +1 for the trailing null
strcpy((lib+i)->title, title);
(lib+i)->price = price;
}

Before you updated your post the declaration of the data member title of the structure
typedef struct {
char *title[50];
float price;
} Book;
is incorrect (in the context of the program it does not make sense). The structure should look like
typedef struct {
char title[50];
float price;
} Book;
That is each book has one title and not 50 pointers to titles.
And instead of this statement
*(lib+i)->title = title;
you have to write at least like
#include <string.h>
//...
strcpy( ( lib+i )->title, title );
As for your output then you assigned the address of the same local variable title to the first pointer of the array
char *title[50];
of each element of the dynamically allocated array.
Pay attention to that you should free the dynamically allocated memory when it is not used any more. For example
free( lib );
Edit: One of the requirements in my assignment is the title of Book
must be of type char*
After you updated your post then in this case the structure definition should look like
typedef struct {
char *title;
float price;
} Book;
And you will need to allocate dynamically memory for entered title of an object of the structure.
You could do it for example the following way. I suppose that you want to use pointers instead of the subscript operator.
( lib + i )->title = malloc( strlen( title ) + 1 );
strcpy( ( lib + i )->title, title );
In this case before freeing the allocated array pointed to by the pointer lib you will need to free also each allocated character array like for example
for ( int i = 0; i < n; i++ )
{
free( ( lib + i )->title );
}
free( lib );

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.

How do I insert char* to array of structures?

the task is to dynamically allocate memory for the array of structures and then fill them from keyboard. I was able to dynamically allocate and fill amount of pages for each of the struct instance in array, but when I try to add char* to it by doing something like:
strcpy(myArray[i]->author, authorName);
But every time I get segmentation error, so what am I doing wrong?
Is it possible that problem is actually in memory allocation?
Here is the code
#include <stdlib.h>
#include <string.h>
struct Book {
char* author;
char* title;
int pages;
int pubYear;
int copies;
};
void allocList(struct Book **myArray, int booksAmount);
void fillKeyboard(struct Book **myArray, int booksAmount);
int main(void) {
struct Book *booksList = NULL;
int booksAmount = 3;
allocList(&booksList, booksAmount);
fillKeyboard(&booksList, booksAmount);
return 0;
}
void allocList(struct Book **myArray, int booksAmount) {
*myArray = (struct Book*) malloc(sizeof(struct Book) * 100);
printf("memory for %d books was allocated \n", booksAmount);
}
void fillKeyboard(struct Book **myArray, int booksAmount) {
int i = 0;
char* authorName = "author name";
while (booksAmount--) {
printf("book number %d \n", i + 1);
printf("enter amount of pages: ");
scanf("%d", &(*myArray)[i].pages);
printf("\nenter author: ");
strcpy(myArray[i]->author, authorName);
printf("%s is \n", authorName);
i++;
printf("\n");
}
}
Thank you.
myArray[i].author is a string.
so (in C) an array of char.
as an array you need to allocate it with a malloc
myArray[i].author=malloc(sizeof(char) * 100);
your while loop should look like this:
while (booksAmount--) {
myArray[i].author=malloc(sizeof(char) * 100);
printf("book number %d \n", i + 1);
printf("enter amount of pages: ");
scanf("%d", &(myArray)[i].pages);
printf("\nenter author: ");
strcpy(myArray[i].author, authorName);
printf("%s is \n", authorName);
i++;
printf("\n");
}
keep in mind that 100 is a "magic number" so if the author name is longer than 100 character it's not going to work
edit: same thing with the title, you need to allocate the needed memory in your array's element
If you care about memory, you should not create an array of 100 books. A good way to avoid such allocations is linked lists, so your program will always allocate just the needed memory. Your Book struct would look like this:
struct Book {
char* author;
char* title;
int pages;
int pubYear;
int copies;
struct Book *next;
};
The program will certainly be a bit more complex, but the result is a clean memory usage, and a truly dynamic program.

Data Structure about struct array

Recently, I took a subject called Data structure. I've created a program to try out my knowledge but don't know why the program did not work. I can't figure it out so I post it here to ask for solution. I hope people can help me. I am newbie here. So please ignore my opinion if my opinion is found annoying.
#include <stdio.h>
int main()
{
struct Book
{
char title[50];
int year;
float price;
};
int i;
struct Book books[50];
books[0].title="Bullshit";
books[0].year=132;
books[0].price=146.9;
books[1]=(struct Book){"Money",1344,189.4
};
for(i=0;i<2;i++)
{
printf("Book Title is : %s\n",books[i].title);
printf("Book Year is %d\n",books[i].year);
printf("Book price is %3.2f\n",books[i].price);
printf("\n\n");
}
}
1 I would make declaration of struct rather outside main than inside
2 Try changing char title[50] to char *title
#include <stdio.h>
struct Book {
char *title;
int year;
float price;
};
int main() {
int i;
struct Book books[50];
books[0].title = "Bullshit";
books[0].year = 132;
books[0].price = 146.9;
books[1] = (struct Book) {"Money", 1344, 189.4
};
for (i = 0; i < 2; i++) {
printf("Book Title is : %s\n", books[i].title);
printf("Book Year is %d\n", books[i].year);
printf("Book price is %3.2f\n", books[i].price);
printf("\n\n");
}
}
Why it didn't worked before?
In c arrays are not assignable by = operator.
You could do something like instead title[0] = 'B'; title[1] = 'u', etc....(or use strcpy which does it for you).
char *x is not really an array, it's just pointer to single char.
If we write x = "abc", we are telling the compiler: set x to 'a', next byte to 'b', next to 'c', and next to 0(not '0', just zero).
And when you do printf("%s",x), the printf function prints chars from the place in memory specified by x until it see 0 byte.
char *x = "abcd";
char *y = x;
while(*y != 0){ // this loop acts like printf("%s",x);
printf("%c",*y);
y++;
}
See also this and this question.
Or if you are using c++, not c, use std::string:
#include <cstdio>
#include <string>
struct Book {
std::string title;
int year;
float price;
Book(std::string t, int y, float p) {
title = t;
year = y;
price = p;
}
};
int main() {
int i;
Book books[50];
books[0].title = "Bullshit";
books[0].year = 132;
books[0].price = 146.9;
books[1] = Book(std::string("Money"), 1344, 189.4);
for (i = 0; i < 2; i++) {
printf("Book Title is : %s\n", books[i].title.c_str());
printf("Book Year is %d\n", books[i].year);
printf("Book price is %3.2f\n", books[i].price);
printf("\n\n");
}
}
this
books[0].title="Bullshit";
is not valid. title is defined as char[50]. Either do
strcpy(books[0].title, "BS");
This will copy the bytes of BS to title. Or do
struct Book
{
char *title;
int year;
float price;
};
...
books[0].title = strdup("BS");
This sets title up as a pointer to a char string. strdup will allocate space for the string and copy BS to that space. You will have to free that allocated space.
Or - the best. Use std::string
struct Book
{
std::string title;
int year;
float price;
};
....
books[0].title = "BS";
And as a final thought - life goes better with std::vector instead of raw arrays

Trying to input a strcture, first time works great, second time crashes

Hi I'm inputting a structure of a family with children with those two structures:
typedef struct person {
int id;
char* firstName;
int age;
}person;
typedef struct family {
char* lastName;
person father, mother;
person* children;
int numChildren;
}family;
EDIT: this is the edited function and it still crashes :
int initializeHouse(family **pdata)
{
char temp[SIZE];
int size, i, j;
printf("enter the number of families\n");
scanf("%d", &size);
*pdata = (family*)malloc(sizeof( family)*size);
for (i = 0; i<size; i++)
{
printf("Please enter the last name\n");
scanf("%s", temp);
(*pdata)[i].lastName = (char*)malloc(sizeof(char)* (strlen(temp) + 1));
strcpy(pdata[i]->lastName, temp);
printf("Enter the fathers first name\n");
scanf("%s", temp);
initPerson(temp, &pdata[i]->father.firstName);
printf("enter the fathers ID\n");
scanf("%d", &pdata[i]->father.id);
printf("Enter the fathers age\n");
scanf("%d", &pdata[i]->father.age);
printf("Enter the mothers first name\n");
scanf("%s", temp);
initPerson(temp, &pdata[i]->mother.firstName);
printf("enter the mothers ID\n");
scanf("%d", &pdata[i]->mother.id);
printf("Enter the mothers age\n");
scanf("%d", &pdata[i]->mother.age);
printf("enter the number of children");
scanf("%d", &pdata[i]->numChildren);
(*pdata)[i].children= (person*)malloc(sizeof(person)*(pdata[i]->numChildren));
for (j = 0; j<pdata[i]->numChildren; j++)
{
printf("enter the kids name\n");
scanf("%s", temp);
initPerson(temp, &pdata[i]->children[j].firstName);
printf("enter the kids ID\n");
scanf("%d", &pdata[i]->children[j].id);
printf("Enter the kids age\n");
scanf("%d", &pdata[i]->children[j].age);
}
}
return size;
}
void initPerson(char* str, char** fam)
{
*fam = (char*)malloc(sizeof(char)*(strlen(str) + 1));
strcpy(*fam, str);
}
EDIT: I changed the code and it still doesn't work, and it requires me to write some description so here it is ..
int main() {
int size;
family *a = NULL;
size=initializeHouse(&a);
}
declares a pointer to a family structure. When you pass it's address
size = initializeHouse(&a);
the function gets it as a family**
Okay, we're all on the same page to this point. When you allocate the target of that pointer
*pdata = malloc(sizeof(family) * size);
then *pdata points to an allocated array of structs, not pointers to those structs. Each struct is accessed by (*pdata)[i], which means -> dereference the double pointer pdata to get the address of the first element in the array, then access the array element with a subscript.
So your assignment should be
(*pdata)[i].lastName = malloc(sizeof(char)* (strlen(temp) + 1));
You use the dot . operator to access the members, because the result of the subscript access is a struct, not a pointer to a struct.
This little example using (*pdata)[i]. doesn't crash.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 40
typedef struct person {
int id;
char* firstName;
int age;
}person;
typedef struct family {
char* lastName;
person father, mother;
person* children;
int numChildren;
}family;
int initializeHouse(family **pdata)
{
char temp[SIZE];
int size, i, j;
printf("enter the number of families\n");
scanf("%d", &size);
*pdata = malloc(sizeof(family)*size);
for (i = 0; i<size; i++)
{
printf("Please enter the last name\n");
scanf("%39s", temp);
(*pdata)[i].lastName = malloc(sizeof(char)* (strlen(temp) + 1));
strcpy ( (*pdata)[i].lastName, temp);
}
return size;
}
int main ( void) {
int size;
family *a;
size=initializeHouse(&a);
}
It's important that you understand the memory layout.
family *fam;
family **pdata = &fam;
*pdata = (family*)malloc(sizeof(family)*size);
You have essentialy this: fam is a uninitialized pointer of type family.
pdata is a double pointer initialized with the address of fam. The malloc
call allocates space for size family-objects. By doing *pdata = malloc(...)
you are initializing fam.
This is the basic memory layout you have. base is the address returned by
malloc. slf is the size of struct family object, fpl is the size of a
pointer to a struct family object.
base = address returned by malloc
sfl = sizeof(struct family)
fpl = sizeof(struct family*)
base + 0 base + slf base + 2 * slf
+-----------------+------------------+------------------+
|struct family | struct family | struct family |
+-----------------+------------------+------------------+
base + 0 base + fpl base + 2*fpl base + 3*fpl base + 4*fpl
+------------+------------+------------+------------+-----------+
| pdata[0] | pdata[1] | pdata[2] | pdata[3] | pdata[4] |
+------------+------------+------------+------------+-----------+
The first row shows the memory in terms on struct family objects, the second
row shows you the same memory in terms on pointers (to struct family object).
This is very important distinction, because pdata[i] returns you a
pointer, not the object.
Remember pdata is a double pointer, pdata[i] is the equivalent to pdata + i,
that is the ith pointer begining at base.
Because the size of an struct family is defintitely different that the size of
a pointer, you see that the block don't align, that means
base + slf != base + fpl.
In the first iteration you are lucky, because pdata[0] and (*pdata)[0] are
the same. But pdata[1] and *(pdata)[1] are not the same. So doing
pdata[1]->lastname (instead of (*pdata)[1].lastname) you are accessing at a
wrong location in you allocated memory.
The easiest way to fix you code would be to change the pdata[i] in (*pdata)[i] as shown
in user3121023's answer.
edit
I see that user3121023 has retracted his answer. Basically it did:
printf("enter the fathers ID\n");
scanf("%d", &((*pdata)[i].father.id));
in the loop.
Fixing the pointers may have solved your problem. But the program has a lot of duplicate code and rewriting as follows would help you test a small portion and debug the program easily.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 100
typedef struct person {
int id;
char *firstName;
int age;
} person;
typedef struct family {
char *lastName;
person father, mother;
person *children;
int numChildren;
} family;
void input_string(const char *prompt, char **where) {
char temp[SIZE];
printf("%s\n", prompt);
scanf("%s", temp);
*where = malloc(sizeof(char) * (strlen(temp) + 1));
strcpy(*where, temp);
}
void input_int(const char *prompt, int *where) {
printf("%s\n", prompt);
scanf("%d", where);
}
void input_person(const char *name, person *person) {
char prompt[SIZE];
sprintf(prompt, "Enter the %s's first name", name);
input_string(prompt, &person->firstName);
sprintf(prompt, "Enter the %s's ID", name);
input_int(prompt, &person->id);
sprintf(prompt, "Enter the %s's age", name);
input_int(prompt, &person->age);
}
void input_family(family *fam) {
input_string("Please enter the last name", &fam->lastName);
input_person("father", &fam->father);
input_person("mother", &fam->mother);
input_int("Please enter the number of children", &fam->numChildren);
fam->children = malloc(sizeof(person) * (fam->numChildren));
for (int i = 0; i < fam->numChildren; i++) {
input_person("kid", &(fam->children)[i]);
}
}
int initializeHouse(family **families) {
int size;
input_int("Please enter the number of families", &size);
*families = malloc(sizeof(family) * size);
for (int i = 0; i < size; i++) {
input_family(&(*families)[i]);
}
return size;
}
int main() {
int size = 0;
family *a;
size = initializeHouse(&a);
printf("Successfully inputted %d families", size);
return 0;
}

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);.

Resources