Having trouble printing out my structure array in c - c

My current project in class is to make a program that acts as a phone book using structs. I have coded out the 'add contacts' function and the 'show contacts' function, but when I have more than one contact, the 'show contacts' function shows gibberish for all of the contacts expect for the most recent one. Can anybody help me find the problem?
Here is my current code. If anything is confusing let me know and I will try to respond as fast as I can.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct contact { // Data structure that holds contact information
char FirstName[10]; // Array for first name
char LastName[10]; // Array for last name
int PhoneNum; // Phone number
};
int main (){
// Setting up variables
int Function = 0;
int Choice = 0;
char FName[200][10];
char LName[200][10];
int PNum = 0;
int n = 1;
struct contact *con[200];
int b = 0;
do{ // Will loop through the main function until the user decides to exit the program
// Prints out the main menu of the phone book
printf("\nPhone Book");
printf("\n[1] Add a contact");
printf("\n[2] Delete a contact");
printf("\n[3] Show contacts");
printf("\n[4] Exit program");
printf("\n\nWhat function would you like to use?\n"); // Asks for user input
scanf("%d", &Choice);
switch(Choice){
case 1: // Case to add a contact into the phone book
printf("\nYou chose to add a contact.");
printf("\nFirst name: ");
scanf("%s", &FName[b]);
printf("\nLast name: ");
scanf("%s", &LName[b]);
printf("\nPhone number (Numbers only): ");
scanf("%d", &PNum);
printf("\nRecord added to the phone book");
// Records the information given into the structure
struct contact *con = (struct contact*)malloc(n*sizeof(struct contact));
int a = (n - 1);
printf("\na is %d", a);
strcpy(con[a].FirstName, FName[b]);
strcpy(con[a].LastName, LName[b]);
con[a].PhoneNum = PNum;
int b = (b+1);
n++;
printf("\nn is %d", n);
// Prints out the given information
printf("\nNew contact:");
printf("\nFirst name: %s", con[a].FirstName);
printf("\nLast name: %s", con[a].LastName);
printf("\nPhone number: %d", con[a].PhoneNum);
printf("\n");
break;
case 2: // Case to delete a contact from the phone book
printf("\nYou chose to delete a contact.");
break;
case 3: // Case to see all of the entered contacts
printf("\nYou chose to show the contacts.");
for(a = 0; a < (n - 1); a++){
printf("\nContact #%d", a);
printf("\nFirst name: %s", con[a].FirstName);
printf("\nLast name: %s", con[a].LastName);
printf("\nPhone number: %d", con[a].PhoneNum);
printf("\n");
}
break;
case 4:
printf("Goodbye!");
break;
}
}while (Choice != 4);
return 0;
}
This is the output I get when I run my code.
Phone Book
[1] Add a contact
[2] Delete a contact
[3] Show contacts
[4] Exit program
What function would you like to use?
1
You chose to add a contact.
First name: Test
Last name: 1
Phone number (Numbers only): 1234567
Record added to the phone book
a is 0
n is 2
New contact:
First name: Test
Last name: 1
Phone number: 1234567
Phone Book
[1] Add a contact
[2] Delete a contact
[3] Show contacts
[4] Exit program
What function would you like to use?
1
You chose to add a contact.
First name: test
Last name: 2
Phone number (Numbers only): 8901234
Record added to the phone book
a is 1
n is 3
New contact:
First name: test
Last name: 2
Phone number: 8901234
Phone Book
[1] Add a contact
[2] Delete a contact
[3] Show contacts
[4] Exit program
What function would you like to use?
3
You chose to show the contacts.
Contact #0
First name: Pq
Last name: q
Phone number: 1095516483
Contact #1
First name: test
Last name: 2
Phone number: 8901234

There are some issues on your code:
1> Scope of variable a, b, con should be in main function, you are override the scope of variable a, b from main function scope to in-case scope by re-declare them inside case block code.
int b = b+1;
int a = (n-1);
struct contact *con = (struct contact*)malloc(n*sizeof(struct contact));
In case block code, please just assign them new value:
b = b+1;
a = (n-1);
con = (struct contact*)malloc(n*sizeof(struct contact));
2> The con pointer should be changed from
struct contact *con[200];
by define a initialized size for it. and if the size is out of range, we need to realloc the con in case of add new item:
int size = 200;
struct contact *con = (struct contact *)malloc(size * sizeof(struct contact));
// in case of the size of out of range
if (n >= size)
{
size = size * 2;
con = (struct contact*)realloc(con, size * sizeof(struct contact));
}
Here is my solution:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct contact { // Data structure that holds contact information
char FirstName[10]; // Array for first name
char LastName[10]; // Array for last name
int PhoneNum; // Phone number
};
int main() {
// Setting up variables
int Function = 0;
int Choice = 0;
char FName[200][10];
char LName[200][10];
int PNum = 0;
int n = 1;
int size = 200;
struct contact *con = (struct contact *)malloc(size * sizeof(struct contact));
int b = 0, a = 0;
do { // Will loop through the main function until the user decides to exit the program
// Prints out the main menu of the phone book
printf("\nPhone Book");
printf("\n[1] Add a contact");
printf("\n[2] Delete a contact");
printf("\n[3] Show contacts");
printf("\n[4] Exit program");
printf("\n\nWhat function would you like to use?\n"); // Asks for user input
scanf("%d", &Choice);
switch (Choice) {
case 1: // Case to add a contact into the phone book
printf("\nYou chose to add a contact.");
printf("\nFirst name: ");
scanf("%s", &FName[b]);
printf("\nLast name: ");
scanf("%s", &LName[b]);
printf("\nPhone number (Numbers only): ");
scanf("%d", &PNum);
printf("\nRecord added to the phone book");
// Records the information given into the structure
if (n >= size)
{
size = size * 2;
con = (struct contact*)realloc(con, size * sizeof(struct contact));
}
a = (n - 1);
printf("\na is %d", a);
strcpy(con[a].FirstName, FName[b]);
strcpy(con[a].LastName, LName[b]);
con[a].PhoneNum = PNum;
b = (b + 1);
n++;
printf("\nn is %d", n);
// Prints out the given information
printf("\nNew contact:");
printf("\nFirst name: %s", con[a].FirstName);
printf("\nLast name: %s", con[a].LastName);
printf("\nPhone number: %d", con[a].PhoneNum);
printf("\n");
break;
case 2: // Case to delete a contact from the phone book
printf("\nYou chose to delete a contact.");
break;
case 3: // Case to see all of the entered contacts
printf("\nYou chose to show the contacts.");
for (a = 0; a < (n - 1); a++) {
printf("\nContact #%d", a);
printf("\nFirst name: %s", con[a].FirstName);
printf("\nLast name: %s", con[a].LastName);
printf("\nPhone number: %d", con[a].PhoneNum);
printf("\n");
}
break;
case 4:
printf("Goodbye!");
break;
}
} while (Choice != 4);
return 0;
}

You're defining a new variable called con inside of your switch statement. This variable mask the variable of the same name defined at the top of the function. This is the one you're adding a record to.
When you later go to print the list, it's actually reading from this inner con. However, since you're re-entering the switch statement, the variable's contents is uninitialized because you jump over the initializer because of the switch and you invoke undefined behavior. You get "lucky" that you're able to print the last instance read in, probably because the variable still happened to contain the old value from the last iteration.
Also, the outer version of con is declared as an array of pointers. You probably want just a pointer here so it can point to a dynamically allocated array.
So define con like this:
struct contact *con = NULL;
And change the "add" case to not define the variable. Also, you don't need separate variables to read in the values. You can read them directly into an instance of the struct:
n++;
con = realloc(n*sizeof(struct contact));
printf("\nYou chose to add a contact.");
printf("\nFirst name: ");
scanf("%s", con[n-1].FirstName);
printf("\nLast name: ");
scanf("%s", con[n-1].LastName);
printf("\nPhone number (Numbers only): ");
scanf("%d", &con[n-1].PhoneNum );
printf("\nRecord added to the phone book");
printf("\nn is %d", n);
printf("\nNew contact:");
printf("\nFirst name: %s", con[n-1].FirstName);
printf("\nLast name: %s", con[n-1].LastName);
printf("\nPhone number: %d", con[n-1].PhoneNum);
printf("\n");
Then you'll also need to move a down to the "show" portion:
for( int a = 0; a < (n - 1); a++){

As #Some programmer dude suggested you need to reallocate your array if you want to make it bigger and keep your data.
So essentially something like this
// Records the information given into the structure
struct contact *con = (struct contact*)malloc(n*sizeof(struct contact));
should be at the start of your main function like so:
// dynamically allocate memory which can hold e.g. 1 struct
struct contact *con = malloc(sizeof(struct contact));
and when you resize your memory chunk on the heap, that is what malloc does for you, you should resize or realloc it like so:
// grow array
con = realloc(con, n * sizeof(struct concat));
Read the man page for further Information: realloc man page, or type man 3 realloc or man realloc on your terminal.
EDIT
As #dbush suggested
You declare 2 variables named con. At the start struct contact *con[200]; and in the switch statement you allocate memory and save it into struct concat *con.
So the reason why you still get undefined results on option "3" (show all contact) is, that you actually are reading the contacts from the array struct contact *con[200]; and not from the memory pointed by struct contact *con;
Greetings

Related

Understanding references to members in a struct within a struct, as well as how to dynamically allocate memory for struct members

I've looked at a few different questions with regards to the problem I am facing and while I feel like I've gained some insight I definitely have questions that I could use help with, so I wanted to solve a problem and get some help with the issues I'm facing in solving it.
I have an employee registry, I want to create a structure "Employee" that contains the data fields that I need for each employee. Within those fields I want another structure for their "Date of Birth" which has 3 ints within the struct - referring to month/date/year of birth. (See below)
typedef struct DOB {
int month;
int day;
int year;
} Birthdate;
typedef struct EmployeeInfo {
int empID;
char *firstName;
char *lastName;
Birthdate date;
double salary;
} Employee;
Now I want my program to output a menu of choices and prompt the user for input that could lead to several options those being:
Insert a new employee
Update/change info about an employee
Search for a specific employee
Display all information about all employees
int main() {
//create the array of Items
Employee * employeeRecord = (Employee * ) malloc(N * sizeof(Employee));
Birthdate * birthRecord = (Birthdate * ) malloc(N * sizeof(Birthdate));
int empID;
double salary;
Employee Employee;
Birthdate Birthdate;
char opt;
while (1) {
dispayMenu();
printf("Enter your Choice: ");
scanf(" %c",&opt);
switch(opt) {
case 'i':
printf("\nEnter empID: ");
scanf("%d", & Employee.empID);
printf("Enter firstName: ");
scanf("%s", Employee.firstName);
printf("Enter lastName: ");
scanf("%s", & Employee.lastName);
printf("Enter Date of Birth (month/day/year format): ");
scanf("%d-%d-%d", &Employee.date.month,&Employee.date.day,&Employee.date.year);
printf("Enter Employee salary: ");
scanf("%lf", & Employee.salary);
insertItem(employeeRecord, Employee);
break;
case 'u':
printf("\nEnter empID to update: ");
scanf("%d", & empID);
updateItem(employeeRecord, empID);
break;
case 's':
printf("\nEnter empID to search: ");
scanf("%d", &empID);
searchItem(employeeRecord, empID);
break;
case 'd':
printData(employeeRecord);
break;
case 'q':
quit(employeeRecord);
break;
default:
printf("%c is not a valid choice", opt);
}
}
}
The first question I have is - how can I dynamically update the size of the array that contains all the employees? I get a segmentation fault currently; I don't want to globally create the size of the array; but I know I only need to update it when I have to add an Employee to the registry - so when I call the insert function - but I don't know how to keep a count for a variable in main that updates when insert is called.
The second question is in regards to changing the date of birth - I know I have to use -> operator somewhere so that I can access the fields within the second structure, but when I use it currently it tells me that the type is mismatched - its an int but expects type char*. So how do I access data within the structures to change from the update() function.
void updateItem(Employee * employeeRecord, int empID) {
int i;
char chng;
for (i = 0; i < current_size; i++)
{
if (employeeRecord[i].empID == empID)
{
printf("What data do you wish to update?: ");
scanf(" %c", &chng);
switch (chng)
{
case '1':
printf("\nEnter new First Name: ");
scanf("%s", &Employee.firstName);
break;
case '2':
printf("\nEnter new Last Name: ");
scanf("%s", &Employee.lastName);
break;
case '3':
printf("\nEnter new Date of Birth: ");
// scanf("%d", &empID);
// searchItem(employeeRecord, empID);
break;
case '4':
printf("\nEnter new salary: ") break;
case '5':
printf("\nReturning to main menu.");
break;
default:
printf("%c is not valid, try it again.", opt);
}
}
break;
}
else{
printf("Employee Not Found");
}
}
I've described it above, but essentially can't seem to reference the items within a struct correct and am having trouble correctly calling functions from main - says the implicit declaration doesn't match the type of the function, but that might have to do with errors within those functions themselves.
You store your Employees in a dynamically allocated array, then use realloc() to resize the array:
void insertItem(Enployee **employees, size_t *n, Employee e) {
Employee *tmp = realloc((n+1) * sizeof(Employee));
if (!tmp) {
// fail
}
*employees = tmp;
memcpy(*employees + *n, e, sizeof(Employee));
(*n)++;
}
int main(void) {
// ...
Employee *employees = NULL;
size_t n = 0;
// ...
case 'i': {
Employee *e = malloc(sizeof(Employee));
scanf("%d", e->empID);
// ...
insertItem(&employees, &n, e);
}
// ...
}
As employees and n belong together it would make sense to create a struct to hold them.
Within the Employee struct Birthdate date is also a struct. You use . to access members of a struct via a value, and -> if you have a pointer. In updateItem() you pass in an Employee *employeeRecord and use it as an array so you you either do:
employeeRecord[i].date.month = ...
// or
(employeeRecord + i)->date.month = ...
You can only reference functions already declared so you want main() last. The other good option is to add declarations for your functions at the top.

Make a 2D array in a struct, store strings inside array

I have to make a library system using structs and pointers, that registers a person with their name, ID, phone number, and the name of the books (maximum 3). I have created a struct for every borrower, and I am trying to store input taken by the user, specifically at the part of getting the book titles, to store into an array of other structs (for other borrowers). I have to be able to free the locations of the borrowers once they return all books, so I'd have to use dynamic memory for that.
This is the code I have so far, not sure how exactly I would go about storing every borrower using pointers.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX_NAME_SZ 256
#define CLEAR() system("CLS")
struct borrower
{
char name[20];
char lastName[20];
char id[7];
char phoneNumber[10];
char titleOfBook[3][20];
};
int main(void)
{
struct borrower b;
char op;
do
{
puts("\n1) Register borrower");
puts("2) Find by ID");
puts("3) Show All");
puts("4) Erase by ID");
puts("0) Exit");
printf("Option:");
setbuf(stdin, 0);
opc=getchar();
switch(op)
{
case '1':
RegisterBorrower(&b);
break;
case '2':
//showID();
break;
case '3':
//showAll();
break;
case '4':
//erase();
break;
case '0':
break;
}
}while (op!=48);
return 0;
}
void RegisterBorrower(struct borrower *b)
{
CLEAR();
setbuf(stdin,0);
printf("ID: "); gets(p->id);
printf("Name: "); gets(p->name);
printf("Last Name: "); gets(p->lastName);
setbuf(stdin,0);
printf("Phone Number: "); gets(p->phoneNumber);
int numberOfBooks=0, cont=0, i;
char bookTitle[20];
printf("How many books do you want to take out?(max 3): ");
scanf("%d", &numberOfBooks);
setbuf(stdin,0);
if(numberOfBooks<=3 && numberOfBooks>0)
{
for(i=0; i<numberOfBooks; i++)
{
setbuf(stdin,0);
printf("Book Title: "); gets(bookTitle);
strcpy(p->titleOfBook[i][0], bookTitle);
}
}else
{
printf("You cannot take out this amount of books.");
}
}
Everything "works" (doesn't crash) up until the part I ask for the book titles, it only runs once. Any help would be greatly appreciated.
EDIT:
My problem was that I used
strcpy(p->titleOfBook[i][0], bookTitle);
which only copies to one character because of the [0]. I changed it to
strcpy(p->titleOfBook[i], bookTitle);
and it worked fine.

I want to store the сustomer information in an array of customers

this for adding new costumer.
typedef struct date{
int d,m,y;
}date;
typedef struct client{
int *id;
char *nom [30];
char *prenom [30];
date date;
char *adresse[30] ;
char *tel [30];
}client;
client cl;
void ajouter (){
int age;
printf("give first name:\n");
scanf("%s",&cl.nom);
printf("give last name:\n");
scanf("%s",&cl.prenom);
printf("give adresse:\n");
scanf("%s",&cl.adresse);
printf("give tel num:\n");
scanf("%s",&cl.tel);
printf("give date of birth :\n");
scanf("%d %d %d",&cl.date.d, &cl.date.m, &cl.date.y);
cl.id=1;
if(2019-cl.date.y<18)
printf("refuse");
else
printf(" succes\n");
printf("your informations:\n");
printf(" first name: %s \n last name: %s \n adresse: %s \n tel num: %s \n date of birth : %d/%d/%d \n ID: 0000000%d",cl.nom,cl.prenom,cl.adresse,cl.tel,cl.date.d,cl.date.m,cl.date.y,cl.id);
cl.id++;
}
the problem is when i add the 1st costumer i dont know how to store the informations
i want to save it without using files.
i am beginner and i know maybe its wrong what am doing
but am trying to do my best to make this code
int main()
{
int a,age;
char t[100];
printf("----------- menu ------------\n");
printf("add customer : 1\n");
printf("remove customer : 2\n");
printf("search for customer : 3\n");
scanf("%d",&a);
switch(a){
case(1):ajouter(a);break;
}
return 0;
}
i didnt finish it yet
Salut,
If I understood well, you wish to store a client's data in an array in RAM.
I believe you are using C, hence vectors are not really an option.
So instead, you have either the option of having an array of fixed size, which could be useful in certain situations but generally not, or having a dynamic array, which can be kind of hard to understand when begginning but you shouldn't have much trouble.
In the case a fixed-size array works for you, here's an example of how you'd do it:
//Declaring the client array
#define nClientsTableau 100
int nClients = 0;
client clients[nClientsTableau];
...
//Adding a new client, keep in mind it's just an example
ajouter();
clients[nClients] = cl;
nClients++;
if(nClients == nClientsTableau) printf("Max amount of clients reached");
Then for the second option, building a dynamic array. Different ways of doing it exist, here is a simple way to perform it for your code:
//Declaring the client array
client* clients = NULL;
client* clients2 = NULL;
int nClients = 0
//Adding a new client
ajouter();
nClients++;
clients2 = (client*)realloc(clients, nClients * sizeof(client));
clients = clients2; //NOTE: You should probably check for clients2 not being NULL first
clients[nClients - 1] = cl;
//Ending the program
free(clients);
I sincerely hope this helps. Apart from that, I'd like to tell you that your code is excellent for a beginner, just try having some naming conventions.

Array of Pointers to Structs referencing

I'm writing a "nano social network", just by registering a member and connecting them using pointers in a structure. I'm trying to use a connect function in which I'm not sure I'm writing it in a correct way because the program crashes when I try to run it and I get 0 errors and 0 warnings (warnings at high level using CodeBlocks).
First I register at least 2 members and then when I try to connect them via the connect() function I get that the user I wish to connect with does not exist which is part of the condition in the function. Is it that the users I'm registering don't get saved in the memory? Or am I writing something wrong?
The connect function can be simplified by all means but I will do that once I'm clear with my mistakes.
The code:
#include <stdio.h>
#include <stdlib.h>
struct member{
int num;
char name[10];
struct member *m1;
struct member *m2;
struct member *m3;
struct member *m4;
struct member *m5;
}*ptr[5];
void addmember(){
int i;
printf("Enter new members details:\n");
for(i=0; i<4; i++){
ptr[i] = malloc(sizeof(struct member));
printf("\n Enter ID number:\n");
scanf("%d", &ptr[i]->num);
printf("\n Enter Name:\n");
scanf("%s", ptr[i]->name);
}
printf("\n Added member details are:");
for(i=0; i<4; i++){
printf("\n ID number : %d", ptr[i]->num);
printf("\nName : %s", ptr[i]->name);
}
}
void connect(){ //when always typing the first username
int i=0;
printf("Please type in your user name : \n");
scanf("%s", ptr[i]->name);
if(ptr[i]->name == ptr[0]->name){ //being first user connecting.
printf("Please type existing member name you wish to connect with :\n");
scanf("%s", ptr[i]->name);
if(ptr[i]->name == ptr[1]->name){
ptr[0]->m1 = ptr[1]->m1;
ptr[1]->m2 = ptr[0]->m2;
printf("member 1 connected with member 2!\n");
}
else if(ptr[i]->name == ptr[2]->name){
ptr[0]->m1 = ptr[2]->m1;
ptr[2]->m3 = ptr[0]->m3;
printf("member 1 connected with member 3!\n");
}
else if(ptr[i]->name == ptr[3]->name){
ptr[0]->m1 = ptr[3]->m1;
ptr[3]->m4 = ptr[0]->m4;
printf("member 1 connected with member 4!\n");
}
else if(ptr[i]->name == ptr[4]->name){
ptr[0]->m1 = ptr[4]->m1;
ptr[4]->m5 = ptr[0]->m5;
printf("member 1 connected with member 5!\n");
}
else{
printf("User you typed in does not exist\n");
}
}
}
int main(){
int op = 0;
printf("Welcome to NSN, please register 4 members to proceed to options menu.\n");
addmember(); //adding 4 members
//general member section
printf("Now please select an option by typing option number\n");
while(op != 3){
printf("\n");
printf("1. Add new member.\n 2. Connect with member.\n 3. Exit\n");
printf("Enter your choice:\n");
scanf("%d", &op);
switch(op){
case 1:
addmember();
break;
case 2:
connect();
break;
case 3:
printf("Bye!\n");
exit(0);
break;
default:
printf("Invalid choice!\n");
}
}
return(0);
}
As stated before when I use the connect function after having registered at least 3 members and typing an existing name I always get the answer "User you typed in does not exist", is this somehow that I'm not saving this in memory or am I missing a function?
You cannot compare char arrays like this, you're comparing addresses these pointers point to:
ptr[i]->name == ptr[0]->name
You have to use strcmp function:
strcmp(ptr[i]->name, ptr[0]->name)
And also, think about your connect function - why is it using the first member for input - scanf("%s", ptr[i]->name);? You rather want to type in member A and B's names, find their positions in ptr array, then connect them.
I also don't get why you have these five pointers to member in member itself. You already have an array.

How to approach and optimize code in C

I am new to C and very much interested in knowing how to approach any problem which has more than 3 or 4 functions, I always look at the output required and manipulate my code calling functions inside other functions and getting the required output.
Below is my logic for finding a students record through his Id first & then Username.
This code according to my professor has an excessive logic and is lacking in many ways, if someone could assist me in how should I approach any problem in C or in any other language it would be of great help for me as a beginner and yes I do write pseudo code first.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct{
int id; //Assuming student id to be unique
int age;
char *userName; //Assuming student userName to be unique
char *dept;
}student; // Alias "student" created for struct
student* createstruct(); // All function prototype declared
student* createArray();
void addstruct(student* s2);
void searchChar(student* s2,int num);
void searchInt(student* s2,int num);
student* createstruct() // function createStruct() to malloc data of struct student.
{
student *s;
s = (student*)malloc(sizeof(student));
s->userName = (char*)malloc(sizeof(char)*32);
s->dept = (char*)malloc(sizeof(char)*32);
printf("please enter id ");
scanf("%d",&s->id);
printf("please enter age ");
scanf("%d",&s->age);
printf("please enter userName ");
scanf("%31s",s->userName);
printf("please enter department ");
scanf("%31s",s->dept);
printf("\n");
return s;
}
student* createArray()
{
student *arr; //declaration of arr poiter, type struct student
arr = (student*)malloc(sizeof(student)*10); // memory allocated for a size of 10
return arr;
}
void addstruct(student *s2) // function for adding data to the structures in array
{
int i,num;
student* s1;
printf("please enter the number of records to add:");
scanf("%d",&num);
printf("\n");
if(num>0 && num<11)
{
for(i=0;i<num;i++) // if user want to enter 5 records loop will only run 5 times
{
s1 = createstruct();
s2[i].id = s1->id; // traversing each element of array and filling in struct data
s2[i].age = s1->age;
s2[i].userName = s1->userName;
s2[i].dept= s1->dept;
}
}
else if(num>10) // if user enters more than 10
{
for(i=0;i<10;i++) // loop will still run only 10 times
{
s1 = createstruct();
s2[i].id = s1->id;
s2[i].age = s1->age;
s2[i].userName = s1->userName;
s2[i].dept = s1->dept;
}
printf("Array is full"); // Array is full after taking 10 records
printf("\n");
}
searchInt(s2,num); // Calling searchInt() function to search for an integer in records
searchChar(s2,num); // Calling searchChar() function to search for a string in records
free(s1);
free(s2);
}
void searchChar(student* s2,int num) // function for searching a string in records of structure
{
char *c;
int i;
c = (char*)malloc(sizeof(char)*32);
printf("please enter userName to search ");
scanf("%31s",c);
printf("\n");
for (i=0;i<num;i++) //num is the number of struct records entered by user
{
if ((strcmp(s2[i].userName,c)==0)) //using strcmp for comparing strings
{
printf("struct variables are %d, %d, %s, %s\n", s2[i].id,s2[i].age,s2[i].userName,s2[i].dept);
break;
}
else if(i == num-1)
{
printf("nothing in userName matches: <%s>\n",c);
break;
}
}
}
void searchInt(student* s2,int num) //searchs for an integer and prints the entire structure
{
int i,z;
printf("please enter id to search ");
scanf("%d",&z);
printf("\n");
for (i=0;i<num;i++)
{
if (s2[i].id == z)
{
printf("struct variables are %d, %d, %s, %s\n\n", s2[i].id,s2[i].age,s2[i].userName,s2[i].dept);
break;
}
else if(i == num-1)
{
printf("nothing in id matches: <%d>\n\n",z);
break;
}
}
}
int main(void)
{
student *s2;
s2 = createArray();
addstruct(s2);
return 0;
}
I'm not going to go into optimizing, because if you wanted better theoretical performance you would probably go with different data structures, such as ordered arrays/lists, trees, hash tables or some kind of indexing... None of that is relevant in this case, because you have a simple program dealing with a small amount of data.
But I am going to tell you about the "excessive logic" your professor mentioned, taking your searchInt function as an example:
for (i=0;i<num;i++)
{
if (s2[i].id == z)
{
printf("struct variables are %d, %d, %s, %s\n\n", s2[i].id,s2[i].age,s2[i].userName,s2[i].dept);
break;
}
else if(i == num-1)
{
printf("nothing in id matches: <%d>\n\n",z);
break;
}
}
The thing here is that every time around the loop you're testing to see if you're at the last element in the loop. But the loop already does that. So you're doing it twice, and to make it worse, you're doing a subtraction (which may or may not be optimized into a register by the compiler).
What you would normally do is something like this:
int i;
student *s = NULL;
for( i = 0; i < num; i++ )
{
if( s2[i].id == z ) {
s = &s2[i];
break;
}
}
if( s != NULL ) {
printf( "struct variables are %d, %d, %s, %s\n\n",
s->id, s->age, s->userName, s->dept );
} else {
printf("nothing in id matches: <%d>\n\n",z);
}
See that you only need to have some way of knowing that the loop found something. You wait for the loop to finish before you test whether it found something.
In this case I used a pointer to indicate success, because I could then use the pointer to access the relevant record without having to index back into the array and clutter the code. You won't always use pointers.
Sometimes you set a flag, sometimes you store the array index, sometimes you just return from the function (and if the loop falls through you know it didn't find anything).
Programming is about making sensible choices for the problem you are solving. Only optimize when you need to, don't over-complicate a problem, and always try to write code that is easy to read/understand.

Resources