Modularizing our code with functions

In this program we introduce modularity by separating these functionalities into well-defined functions, so that the code becomes more organized, reusable, and easier to maintain.
#include <stdio.h>
#define MAX_TITLE 41
#define MAX_AUTHORS 3
#define MAX_NAME 20
struct Author {
char first_name[MAX_NAME];
char middle_initial;
char last_name[MAX_NAME];
};
struct Book {
char title[MAX_TITLE];
struct Author authors[MAX_AUTHORS]; // Nested Author structures
int num_authors; // Number of authors for this book
float value;
};
void readBookDetails(struct Book *book);
void printBookDetails(struct Book book);
int main(void) {
struct Book book1;
readBookDetails(&book1); // Call the function to read details
printf("Book details:\n");
printBookDetails(book1); // Call the function to print details
return 0;
}
// Function to read book details from the user
void readBookDetails(struct Book *book) {
printf("Please enter the book title.\n");
fgets((*book).title, MAX_TITLE, stdin);
book->title[strcspn(book->title, "\n")] = '\0'; // Remove trailing newline
printf("Enter the number of authors (up to %d): ", MAX_AUTHORS);
scanf("%d", &(*book).num_authors);
getchar(); // Consume newline character
// Get information for each author
for (int i = 0; i < book->num_authors && i < MAX_AUTHORS; i++) {
printf("Enter details for author %d:\n", i + 1);
printf(" First name: ");
fgets(book->authors[i].first_name, MAX_NAME, stdin);
book->authors[i].first_name[strcspn(book->authors[i].first_name, "\n")] = '\0';
printf(" Middle initial (or hit space and enter if none): ");
scanf("%c", &book->authors[i].middle_initial);
getchar(); // Consume newline character
printf(" Last name: ");
fgets(book->authors[i].last_name, MAX_NAME, stdin);
book->authors[i].last_name[strcspn(book->authors[i].last_name, "\n")] = '\0';
}
printf("Please enter the price.\n");
scanf("%f", &book->value);
}
// Function to print book details
void printBookDetails(struct Book book) {
printf("%s \nAuthored by : ", book.title);
// Print author names with commas
for (int i = 0; i < book.num_authors; i++) {
printf(" %s %c %s%s", book.authors[i].first_name,
book.authors[i].middle_initial, book.authors[i].last_name,
i < book.num_authors - 1 ? "," : ""); // Comma for all except last
}
printf("\n Price Rs. %.2f\n", book.value);
}
Lets discuss the readBookDetails functions used in this program.
The function header is void readBookDetails(struct Book *book)
It takes pointer to a struct Book variable as an argument.
This function is responsible for reading details about a book from the user and storing them in the provided struct Book variable.
Notice that it accepts the address to the struct Book variable, because whatever assignment operations this function does should reflect on the struct Book book1 variable that main() passes to readBookDetails .
The argument struct Book book1 has been passed-by-reference or you can say that the function has been called-by-reference.
Let's take a closer look at this function.
void readBookDetails(struct Book *book) {
printf("Please enter the book title.\n");
fgets((*book).title, MAX_TITLE, stdin);
book->title[strcspn(book->title, "\n")] = '\0'; // Remove trailing newline
printf("Enter the number of authors (up to %d): ", MAX_AUTHORS);
scanf("%d", &(*book).num_authors);
getchar(); // Consume newline character
// Get information for each author
for (int i = 0; i < book->num_authors && i < MAX_AUTHORS; i++) {
printf("Enter details for author %d:\n", i + 1);
printf(" First name: ");
fgets(book->authors[i].first_name, MAX_NAME, stdin);
book->authors[i].first_name[strcspn(book->authors[i].first_name, "\n")] = '\0';
printf(" Middle initial (or hit space and enter if none): ");
scanf("%c", &book->authors[i].middle_initial);
getchar(); // Consume newline character
printf(" Last name: ");
fgets(book->authors[i].last_name, MAX_NAME, stdin);
book->authors[i].last_name[strcspn(book->authors[i].last_name, "\n")] = '\0';
}
printf("Please enter the price.\n");
scanf("%f", &book->value);
}
It asks for the number of authors contributing to the book, reads it with
scanf.scanfneeds the address ofnum_authors. We can find the address using the&operator.But where is
num_authors? How can we access it?num_authorsis inside thestruct Book book1variable insidemain()How can we access it from inside the
readBookDetails()function?Using the
struct Book *bookparameter insidereadBookDetails()!struct Book *bookhas the address of thestruct Book book1variable insidemain().readBookDetails(&book1);To reach from
struct Book *bookto thestruct Book book1variable insidemain()we have to dereference the book variable:*bookis equivalent tobook1Now next step would be to access the
num_authorsmember using the dot operator.(*book).num_authorsNote that we need the parentheses around
*bookbecause the dot operator has more precedence than the dereferencing*operator that is used onbook.And then we can finally find the address of
num_authorsusing the&operator, so thatscanfknows where to store the input value.scanf("%d", &(*book).num_authors);getchar()consumes the newline character left in the input buffer.Now notice the header of the
forloop.for (int i = 0; i < book->num_authors && i < MAX_AUTHORS; i++)(*book).num_authorscan be written in short using the arrow operator:book->num_authorsIt iterates over the number of authors provided by the user, prompting for each author's details individually:
First name is read using
fgets.Middle initial is read using
scanf.Last name is read using
fgets.
Finally, it prompts the user to enter the book's price and reads it using
scanf.
Now lets take a look at the void printBookDetails(struct Book book)
This function prints the details of a book provided as an argument.
So this function need not have access to the address of struct Book variable.
The argument has been passed-by-value or you can say that the function has been called-by-value.
It prints the title of the book using
printf.It iterates over the authors of the book:
Prints each author's first name, middle initial, and last name using
printf.A comma is printed between authors, except for the last one.
It prints the price of the book using
printf.
Output:


