I am trying to code a scheduler in C for practice. Currently my issue is that I am trying to put the "student" object that i created into an array of students called "employees". So i create the student, get its schedule and then dereference the *student and put it in employees[i] array. But when I print the names in the employees array it prints the last entered name repeatedly. I also tried making employee array a pointer (Student *employee) but got the same problem. Any help is appreciated. Thank You
______________________________________________________________________________
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define NUM_SLOTS 24
#define NUM_EMPLOYEES 5
#define BUFF 25
#pragma warning(disable : 4996)
typedef struct Student Student;
typedef struct StudentDay StudentDay;
typedef struct Slot Slot;
//array of strings of all the timeslots
char *timeSlots[NUM_SLOTS] = { "08:00-08:30", "08:30-09:00", "09:00-09:30" , "09:30-10:00" , "10:00-10:30" , "10:30-11:00" , "11:00-11:30" , "11:30-12:00",
"12:00-12:30", "12:30-13:00", "13:00-13:30", "13:30-14:00", "14:00-14:30", "14:30-15:00", "15:00-15:30", "15:30-16:00", "16:00-16:30",
"16:30-17:00", "17:00-17:30", "17:30-18:00", "18:00-18:30", "18:30-19:00", "19:00-19:30", "19:30-20:00"
};
char *daysOfWeek = "MTWRFS";
//data structure represents a day for a student
typedef struct StudentDay {
char name;
//binary slots representing 1 for available -1 for unavailable
int slots[NUM_SLOTS];
};
//data structure represents a student
typedef struct Student {
char *name;
//array of 24 half hour times starting 8am - 8pm
StudentDay week[6];
};
//data structure represents a time slot in a day
typedef struct Slot{
char *time;
char *personAssigned;
int done; // 1 if done assinging
};
//data structure represents a day for coach will
typedef struct WorkDay {
char *name;
Slot slots[NUM_SLOTS];
};
int main() {
printf("Collin College Fitness Center Scheduling System\n");
int numEmployees;
printf("Please enter number of employees\n");
scanf("%d", &numEmployees);
//create an array of student employees
Student employees[BUFF];
//enter which day are you scheduling for
printf("What day are you wanting to schedule, Enter M-Mon, T-Tue, W-Wed, R-Thu, F-Fri, S-Sat?\n");
char day = getchar();
//will possibly need another loop for all siz days right now just one day ex. monday M
for (int i = 0; i < numEmployees; i++) {
Student *student = malloc(sizeof(Student));
//setting name for student
char name[BUFF];
printf("Please enter name for emplyee number %d\n", i + 1);
fgets(name, sizeof(name), stdin);
student->name = name;
printf("Enter the student's class times in military format Example 13:00-14:30 and press enter, input Done when done\n");
//time stores the input class time by coach
char time[BUFF] = "";
while (strcmp(time, "done") != 1 || strcmp(time, "Done") != 1) {
fgets(time, sizeof(time), stdin);
char *temp = time;
//get the index of the class' time slot
int indexOfSlot = getIndexOfString(timeSlots, temp);
//get index of the day we are scheduling for
int dayIndex = getIndexOfChar(daysOfWeek, day);
//for this students particular days' this time slot is made unavailable
student->week[dayIndex].slots[indexOfSlot] = -1;
}
//put this students info in the employees array
employees[i] = *student;
}
for (int k = 0; k < 2; k++) {
printf("employee stored is %s", employees[k].name);
}
system("pause");
return 0;
}
//helper method to get the index of a string in an array
int getIndexOfString(char*names[NUM_SLOTS], char *name) {
for (int i = 0; i < NUM_SLOTS; i++) {
if (strcmp(names[i], name) == 0) {
return i;
}
}
return 0;
}
//helper method to get te index of char in a string
int getIndexOfChar(char *name, char c) {
char *temp = name;
int i = 0;
while (*temp != '\0') {
if (*temp == c) {
return i;
}
temp++;
i++;
}
return 0;
}
Array name is created locally and overwritten on every iteration. You need to allocate a separate string in the heap for every student.
Replace this:
char name[BUFF];
...
fgets(name, sizeof(name), stdin);
With this:
char* name = malloc(sizeof(char)*BUFF);
...
fgets(name, BUFF, stdin);
Related
I need to store multiple distinguishable members in a struct for a personal diary to show different records for each day. I want multiple members like e1 without writing it 365 times. I want a solution that works e1 on a loop or on an array.
struct add
{
char day[365];
char date[365];
char time[365];
char place[365];
char data[365];
};
int main()
{
int i=1;
struct add e1;
while(i!=0)
{
printf("Enter Day:");
gets(e1.day);
printf("Enter Date:");
gets(e1.date);
printf("Enter Time:");
gets(e1.time);
printf("Enter Place:");
gets(e1.place);
printf("Tell me about your day:");
gets(e1.data);
printf("\n\n\n");
printf("Day: %s\n",e1.day);
printf("Day: %s\n",e1.date);
printf("Day: %s\n",e1.time);
printf("Day: %s\n",e1.place);
printf("Day: %s\n\n\n",e1.data);
}
return 0;
}
I don't think its possible to create different variable with each loop, you can refer to this question for info. Instead of making different instances, make your struct in a way so that it stores data for all (365) days. Something like array of strings so that it stores for all days, currently even if you write something like char day[365] it creates separate day for each instance. make something like:
struct add
{
char day[NUMBER_OF_STRING][MAX_STRING_SIZE]; // syntax
// MAX_STRING_SIZE does not need to be 365, i just used it because you used that
// otherwise it does not make sense, date , time etc won't take more than 10 char
char date[365][365];
char time[365][365];
char place[365][365];
char data[365][365];
};
Now keep on adding to a single instance of struct add using for loop, this should be easy.
Also Better approach can be to create a array of struct add itself with your original struct code.
This example does what you want, and you can create as many instance of add as you want.
I limit your loop to run once and have tested that the code works with visual studio 2019:
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#define DAY_SIZ 20
#define DATE_SIZ 40
#define TIME_SIZ 20
#define PLACE_SIZ 120
#define DATA_SIZ (BUFSIZ - 1)
struct add
{
char day[DAY_SIZ];
char date[DATE_SIZ];
char time[TIME_SIZ];
char place[PLACE_SIZ];
char data[DATA_SIZ];
};
struct add* create_add_struct() {
struct add* rec;
rec = (struct add*)malloc(sizeof(struct add));
return rec;
}
void destroy_add_struct(struct add* rec) {
free(rec);
}
void clear_add_struct(struct add* rec) {
memset(rec->day, 0, sizeof(rec->day));
memset(rec->date, 0, sizeof(rec->date));
memset(rec->time, 0, sizeof(rec->time));
memset(rec->place, 0, sizeof(rec->place));
memset(rec->data, 0, sizeof(rec->data));
}
void get_text_from_user(const char prompt[], char *txt, int siz) {
char buf[BUFSIZ];
printf("%s", prompt);
fgets(buf, BUFSIZ, stdin);
memcpy(txt, buf, siz);
}
void fill_add_struct(struct add* rec) {
printf("Do not enter any lines longer than %d\n\n", BUFSIZ);
get_text_from_user("Enter Day:", rec->day, sizeof(rec->day) - 1);
get_text_from_user("Enter Date:", rec->date, sizeof(rec->date) - 1);
get_text_from_user("Enter Time:", rec->time, sizeof(rec->time) - 1);
get_text_from_user("Enter Place:", rec->place, sizeof(rec->place) - 1);
get_text_from_user("Tell me about your day:", rec->data, sizeof(rec->data) - 1);
}
void print_add_struct(struct add* rec) {
printf("\n\n\n");
printf("Day : %s\n", rec->day);
printf("Date : %s\n", rec->date);
printf("Time : %s\n", rec->time);
printf("Place: %s\n", rec->place);
printf("Data : %s\n\n\n", rec->data);
}
int main()
{
// The number of times we want the loop to run
int i = 1;
// Collect data from the user and print it
while (i-- != 0)
{
// Allocate memory and initialize it
struct add* rec = create_add_struct();
clear_add_struct(rec);
// Get data from the user and print it
fill_add_struct(rec);
print_add_struct(rec);
// Release memory
destroy_add_struct(rec);
}
// Return success
return 0;
}
The reason I allocate your structure, is to make sure a stack-overflow does not occur, no pun intended.
If you want to create 365 add structs, you can create them like so:
struct add **records;
records = (struct add **) malloc(sizeof(struct add *) * 365);
for(int idx = 0; idx < 365; ++idx) {
records[idx] = create_add_struct();
clear_add_struct(records[idx]);
/* ... insert code ... */
}
/* ... insert code ... */
// Free memory
for(int idx = 0; idx < 365; ++idx) {
destroy_add_struct(records[idx]);
}
free(records);
I have not tested if the last piece of code compiles and works. Again I use malloc() and free() to avoid a stack-overflow.
typedef struct
{
time_t tm;
char *description;
}entry;
typedef struct day
{
time_t date;
size_t nentries;
struct day *next;
entry entries[];
}day;
and create linked list od days. Every day has array of diary entries.
so as the question says I get a segmentation fault every time I try to enter in a name for the customer. This program does compile and works until it gets to the customer name part. I'm not sure if the problem is with malloc. Could anyone show me what I am doing wrong? I've been trying to figure this out for awhile now with no luck. Thanks
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define END_OF_STRINGS '\0'
#define NEWLINE '\n'
#define MAX_CUSTOMERS 100
#define MIN_CUSTOMERS 2
#define MAX_NAME_LENGTH 20
#define DB_ALLOC_ERR 1
#define QUIT 0
struct customer
{
char *p_last_name[MAX_NAME_LENGTH + 1];
float amount_owed;
int priority;
};
void print_instructions();
int number_of_customers();
void get_accounts(struct customer *p_customer_start, int
customer_amount);
void clean_names(struct customer *p_customer_start, int
customer_amount);
void sort_names(struct customer *p_customer_start, int
customer_amount);
void print_results(struct customer *p_customer_start, int
customer_amount);
int main()
{
struct customer *p_customer;
int customer_amount;
while (print_instructions(), (customer_amount =
number_of_customers()) != QUIT)
{
if ((p_customer = (struct customer *)malloc(sizeof(*p_customer) *
MAX_NAME_LENGTH)) == NULL)
{
printf("\nError #%d occurred in main()", DB_ALLOC_ERR);
printf("\nCannot allocate memory for database of customer ");
printf("\naccountable records");
printf("\nThe program is aborting");
exit (DB_ALLOC_ERR);
}
get_accounts (p_customer, customer_amount);
clean_names (p_customer, customer_amount);
sort_names (p_customer, customer_amount);
print_results(p_customer, customer_amount);
printf("%c", NEWLINE);
free(p_customer);
}
return 0;
}
void print_instructions()
{
printf("\n\nThis program allows you to input customers which owe");
printf("\nyou money (your accounts receivable), and manage these");
printf("\naccounts in a database. You will enter the following:");
printf("\n Customer last name (1-20 characters)");
printf("\n Amount the customer owes (to the exact cent)");
printf("\n Customer priority (1=VIP, 2=Important, 3=Regular)");
printf("\nFrom 2 to 100 customers may be processed.");
return;
}
int number_of_customers()
{
int user_choice;
printf("\n\nGet the customers for the database");
printf("\n--------------------------------------------------");
do
{
printf("\nHow many customers do you have (%d to %d, %d=quit): ", MIN_CUSTOMERS, MAX_CUSTOMERS, QUIT);
scanf ("%d", &user_choice);
} while ((user_choice < MIN_CUSTOMERS ||
user_choice > MAX_CUSTOMERS) && user_choice != QUIT);
return user_choice;
}
void get_accounts(struct customer *p_customer_start, int
customer_amount)
{
struct customer *p_customer;
for (p_customer = p_customer_start; (p_customer - p_customer_start)
< customer_amount; p_customer++)
{
printf("\nCustomer number %d", (int)(p_customer -
p_customer_start + 1));
printf("\n Enter the customer's last name: ");
scanf ("%20s", p_customer->p_last_name[MAX_NAME_LENGTH + 1]);
getchar();
do
{
*p_customer->p_last_name[MAX_NAME_LENGTH] = getchar();
p_customer->p_last_name[MAX_NAME_LENGTH]++;
} while (!NEWLINE);
p_customer->p_last_name[MAX_NAME_LENGTH + 1] = END_OF_STRINGS;
printf("\n Enter the amount owed: ");
scanf ("%f", &p_customer->amount_owed);
do
{
printf("\n Enter the customer's priority (1-3): ");
scanf ("%d", &p_customer->priority);
} while (p_customer->priority < 1 || p_customer->priority > 3);
}
return;
}
void clean_names(struct customer *p_customer_start, int
customer_amount)
{
char *p_fast = p_customer_start->p_last_name[MAX_NAME_LENGTH],
*p_slow = p_customer_start->p_last_name[MAX_NAME_LENGTH];
if (tolower(*p_fast))
*p_slow++ = toupper(*p_fast);
while (*p_fast != END_OF_STRINGS)
{
if (!isspace(*p_fast) || isalpha(*p_fast))
*p_slow++ = tolower(*p_fast);
p_fast++;
}
*p_slow = END_OF_STRINGS;
return;
}
void sort_names(struct customer *p_customer_start, int
customer_amount)
{
char *p_inner[MAX_NAME_LENGTH],
*p_outer[MAX_NAME_LENGTH],
temp[MAX_NAME_LENGTH];
for (p_outer[MAX_NAME_LENGTH] = p_customer_start ->
p_last_name[MAX_NAME_LENGTH]; (p_outer - p_customer_start ->
p_last_name)
< customer_amount; p_outer[MAX_NAME_LENGTH]++)
{
for (p_inner[MAX_NAME_LENGTH] = p_outer[MAX_NAME_LENGTH + 1];
(p_inner - p_customer_start ->
p_last_name) < customer_amount; p_inner[MAX_NAME_LENGTH]++)
{
if (strcmp(p_outer[MAX_NAME_LENGTH],
p_inner[MAX_NAME_LENGTH]))
{
temp[MAX_NAME_LENGTH] = *p_outer[MAX_NAME_LENGTH];
*p_outer[MAX_NAME_LENGTH] = *p_inner[MAX_NAME_LENGTH];
*p_inner[MAX_NAME_LENGTH] = temp[MAX_NAME_LENGTH];
}
}
}
return;
}
void print_results(struct customer *p_customer_start, int
customer_amount)
{
char last_name[MAX_NAME_LENGTH];
float amount_owed = p_customer_start->amount_owed;
printf("\n Here is the accounts receivable customer database");
printf("\n=====================================================");
printf("\n Customer Name Amount Priority");
printf("\n-------------------- --------- -------------");
printf("\n %s $ %.2f ", last_name,
amount_owed);
switch (p_customer_start->priority)
{
case 1:
printf("1 (VIP)");
break;
case 2:
printf("2 (Important)");
break;
case 3:
printf("3 (Regular)");
break;
}
printf("\n\n******* End Of Customer Database Processing *******");
return;
}
i believe a start of your problem is here:
struct customer
{
char *p_last_name[MAX_NAME_LENGTH + 1];
float amount_owed;
int priority;
};
with that code you create 21 pointers to char.
What you want is character pointer to space that will hold MAX_NAME_LENGTH + 1 characters
Therefore you would want something simply like:
struct customer
{
char last_name[MAX_NAME_LENGTH + 1];
float amount_owed;
int priority;
};
I also changed p_last_name to just last_name so to the eyes it reads more logically, but you may call it whatever you like, but to say p_last_name is to imply it's a pointer which is not needed, and it reads poorly
When declaring or defining variables, you read from right to left,
it would then be an array because of [] which is 21 big, called last name and it's an array of the char data type.
Now the thing with C is that arrays and pointers have something in common, or can often be confused... because they are technically the same thing. Any array that you define, which in turn allocates space in memory, is nothing more than a pointer to the beginning of the array, that's it!
when you do something like last_name[7] then the 7 is how many jumps from the beginning of the array, which is always known as last_name in your case. The size of the jump is solely dependent upon the data type of the array when it was defined. In your case it is char which is 1 byte, so a jump of last_name[7] would be 7 bytes away from where last_name points to.
For example if the contents in memory where `last_name` points to is abcdefghijklmnopqrst
then char last_name[MAX_NAME_LENGTH + 1]; would define a variable called last_name which is technically a character pointer to contiguous chunk of memory that is MAX_NAME_LENGTH + 1 bytes because of data type char and it is a pointer to the beginning of that chunk of memory.
*last_name is the same as last_name[0] which deferences the character pointer last_name such that it returns the contents of memory which is a
*(last_name+2) is the same as last_name[2] which is c
Also, in
int main()
{
struct customer *p_customer;
int customer_amount;
this statement struct customer *p_customer; creates one pointer called p_customer that is a pointer which will point to some chunk of memory (hasn't happened yet) that is of the data type struct customer which is defined above. Ok to there. Then at
if ((p_customer = (struct customer *)malloc(sizeof(*p_customer) *
MAX_NAME_LENGTH)) == NULL)
where you use malloc to reserve some chunk of memory for what you are doing, you are really doing sizeof( a pointer )
what you should be doing is (struct customer *) malloc( sizeof( struct customer )) in addition to correctly defining a 21 byte array of characters called last_name in struct customer.
It should read out in English logically, oftentimes from right to left, if it does not then suspect a problem. Also when compiling learn to use -W it can be your friend and alert you to problems like this.
your original code is likely not allocating or reserving a large enough chunk of memory for the number of characters you type in to store in p_last_name.
Let's say for example you are entering the personal information of a student and you create a unique ID number for each student. What I'm having problems with is grouping those strings, and storing them together, so that it can be accessed through the ID.
I tried using memory allocation, however, it did not work out.
I'm quite new to C, so I'm not exactly sure on what to do.
Here is what I used :
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
struct {
int LogID;
char firstname[20];
char lastname[20];
int mark;
char *subjects[100];
} student;
int reg(void);
int main(void) {
reg();
return 0;
}
//Registration function
int reg(void) {
int choice,shift,found,compare, nosub, y, sub, subcount;
char studentname[20];
FILE *fp;
FILE *fp2;
printf("Enter Student Details:\n\nStudent ID: ");
scanf("%d",&student.LogID);
printf("Name: ");
scanf("%s",student.firstname);
printf("Surname: ");
scanf("%s",student.lastname);
printf("How many subjects does the student take? ");
scanf("%d", &nosub);
//Opens a text file and prints the student's ID and firstname
fp2=fopen("subjects.txt","a+");
fprintf(fp2, "\n\n%d\t%s", student.LogID, student.firstname);
int i = 1;
size_t malloc_size = 100; //Allocating memory size to store subjects student is taking
for(i = 0; i < nosub; i++) {
student.subjects[i] = malloc(malloc_size * sizeof(char));
printf("Please enter the subject :\n(1)Mathematics\n(2)English\n(3) Social Studies\n(4)Science\n");
scanf("%d", &sub);
switch (sub) {
case (1) :
printf("Mathematics\n");
break;
case (2) :
printf("English\n");
break;
case (3) :
printf("Social Studies\n");
break;
case (4) :
printf("Science\n");
break;
}
}
for(i = 0; i < nosub; i++) { //Prints subjects to file, but it doesn't work...
fprintf(fp2,"%s\n", student.subjects[i]);
}
fclose(fp2);
free(student.subjects[i]);
student.subjects[i] = NULL;
fp=fopen("studentfile.txt","a+");
//Prints certain student Information into another file...
fprintf(fp,"\n%d\t%s\t%s\t",student.LogID,student.firstname,
student.lastname);
fclose(fp);
printf("Registration has been successful\n");
getchar();
return 0;
}
There were a number of issues I noticed and I'll address some of them, starting with the struct which I recommend defining like this:
struct studentpack {
int LogID;
char firstname[20];
char lastname[20];
int mark;
char *subjects[100];
};
And under your main function, you can define the student entry for filling.
struct studentpack student;
which will be used over and over again in your code, as you did in your example, for filling from the user input.
In the switch you really don't need any parenthesis around the case numbers.
In addition to the printf statement in each case, try something like this:
case 1:
printf("%s\n", "Mathematics");
sprintf(student.subjects + i, "%s", "Mathematics");
break;
which will fill the subjects area that you memory allocated just prior.
Finally, for grouping together the ID's I would suggest starting with something like this:
#define MAXGROUP 1000
struct studentpack *group = calloc(MAXGROUP, sizeof(struct studentpack));
int studentno = 0;
And then after you print your subjects to the file (test that it is working first due to the sprintf change) you would assign to the group like this:
if (studentno < MAXGROUP) {
memcpy(group+studentno, &student, sizeof(struct studentpack));
studentno++;
}
The above will store away the student. Next you will probably want to iterate through the group variable, accessing group[0].LogID, group[1].LogID, etc. (all the way up to a maximum of 1000) just to confirm that all your data is there in memory.
For example you could write a function that steps through looking for a particular LogID and then calls a show or display function containing printf statements to see all the values on screen.
you need an array of students
struct student{
int LogID;
char firstname[20];
char lastname[20];
int mark;
char *subjects[100];
};
struct student students[100];
you now have space for 100 students. They are students[0], students[1],...students[99]
Now you can do
int studno = 0;
While(something)
{
printf("\Enter Student Details:\n\nStudent ID: ");
scanf("%d",&(students[studno].LogID));
....
studno++;
}
After many hours of working on trying to debug this code myself I'm giving up an seeking help. I created a program that is designed to hold a "record", a struct, of my choice and show I know how to utilize/manipulate them in memory. In my code I made a car inventory that allows you to add, delete, and print out structs. My struct looks like the following:
struct car{
char *make;
char *model;
int year;
int mpg;
int mileage;
int cost;
};
I use a menu system of number that allows the user to choose what to do with the struct. Anyways here's where I'm having the issue:
I can add two struct and print them all out just fine. However if I add more than two structs than I run into a seg fault. I've already tried to run GDB on it and I get the following error:
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7a60a03 in _IO_vfprintf_internal (s=<optimized out>, format=<optimized out>,
ap=<optimized out>) at vfprintf.c:1661
1661 vfprintf.c: No such file or directory.
As for how I am taking in this data I have 6 scanf() functions that take in the 6 characteristics of the struct, store them to a temporary variable, malloc for each string, malloc a new car struct called newCar, and set each variable inside struct to its temporary variable. If it's the first car entry then carInventory is equal to newCar. When adding another car the same process occurs except a while loop moves along a new struct called newCarInventory and stores data from carInventory using memcpy(). Below is the actual code I'm using:
void addRecord(){
newCar = (struct car *) malloc(sizeof(struct car)); //Allocates memory for a car entry
int i;
int inventoryAmountTemp = inventoryAmount; //Grabs the global value and stores it to a local variable
//Local variables used to hold onto inputted values
char make[25];
char model[25];
int year;
int mpg;
int mileage;
int cost;
printf("\nMake: ");
scanf("%s", &make);
printf("\nModel: ");
scanf("%s", &model);
printf("\nYear: ");
scanf("%i", &year);
printf("\nMiles Per Gallon: ");
scanf("%i", &mpg);
printf("\nMileage: ");
scanf("%i", &mileage);
printf("\nCost: ");
scanf("%i", &cost);
newCar->make = (char *)malloc(strlen(make)+2); //Allocates memory for string
newCar->model = (char *)malloc(strlen(model)+2);
strcpy(newCar->make, make); //Coppies string into newCar
strcpy(newCar->model, model);
newCar->year = year;
newCar->mpg = mpg;
newCar->mileage = mileage;
newCar->cost = cost;
if(inventoryAmountTemp == 0){
carInventory = newCar;
}
else{
newCarInventory = (struct car *) malloc(inventoryAmountTemp * sizeof(struct car)); //Memory made for a new Car Inventory.
headPtr = carInventory;
headPtr2 = newCarInventory;
tailPtr = newCar;
i = 0;
while(i <= inventoryAmountTemp){
memcpy(&(newCarInventory->make), &(headPtr->make), sizeof(headPtr->make));
memcpy(&(newCarInventory->model), &(headPtr->model), sizeof(headPtr->model));
memcpy(&(newCarInventory->year), &(headPtr->year), sizeof(headPtr->year));
memcpy(&(newCarInventory->mpg), &(headPtr->mpg), sizeof(headPtr->mpg));
memcpy(&(newCarInventory->mileage), &(headPtr->mileage), sizeof(headPtr->mileage));
memcpy(&(newCarInventory->cost), &(headPtr->cost), sizeof(headPtr->cost));
i++;
if(i < inventoryAmountTemp && i != inventoryAmountTemp){
headPtr++;
newCarInventory++;
}
else if(i == inventoryAmountTemp){
headPtr = tailPtr;
newCarInventory++;
}
}
newCarInventory = headPtr2;
carInventory = newCarInventory;
}
inventoryAmountTemp += 1;
accessTemp += 1;
access = accessTemp;
inventoryAmount = inventoryAmountTemp;
}
I know the issue resides from this function because I had fprintf() statements (that I took out in this code) that would test each step. The ones that would fail were the ones inside the while loop the as the loop went around the second time, of the third car entry.
Any guidance would be really appreciated!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
struct car{
char *make;
char *model;
int year;
int mpg;
int mileage;
int cost;
};
int inventoryAmount=0;
struct car* CarList=0;
char *copyString(char *str){
char *buff=0;
if(str){
int l=strlen(str);
buff=malloc(l+1);
if(buff){
for(int i=0;i<=l;i++)
buff[i]=str[i];
}
}
return buff;
}
/*_______________________________________________________
*/
void propmt(const char *msg,const char*fmt,void *output){
printf("\n%s: ",msg);
scanf(fmt,output);
return;
}
/*_______________________________________________________
*/
void addRecord(void){
struct car *newCar ;
//Local variables used to hold onto inputted values
char make[25];
char model[25];
int year;
int mpg;
int mileage;
int cost;
if(CarList){
newCar= realloc(CarList,sizeof(struct car)*(inventoryAmount+1));
}else{
newCar= malloc(sizeof(struct car));
}
if(!newCar){
printf("Failed to allocate new car\n");
exit(1);
}
CarList=newCar;
newCar=&newCar[inventoryAmount];
inventoryAmount++;
propmt("Make","%s", &make);
propmt("Model","%s", &model);
propmt("Year","%i", &year);
propmt("Miles Per Gallon","%i", &mpg);
propmt("Mileage","%i", &mileage);
propmt("Cost","%i", &cost);
newCar->make=copyString( make); //Coppies string into newCar
newCar->model=copyString( model);
newCar->year = year;
newCar->mpg = mpg;
newCar->mileage = mileage;
newCar->cost = cost;
return;
}
/*_______________________________________________________
*/
void listCars(void){
int i;
if(!inventoryAmount){
printf("\nNo cars in inventory\n");
return;
}
for(i=0;i<inventoryAmount;i++){
printf("Make: %s\n" ,CarList[i].make);
printf("Model:%s\n" ,CarList[i].model);
printf("Year:%i\n" ,CarList[i].year);
printf("Miles Per Gallon:%i\n" ,CarList[i].mpg);
printf("Mileage:%i\n" ,CarList[i].mileage);
printf("Cost:%i\n" ,CarList[i].cost);
printf("======================================\n");
}
return;
}
void pause(void){
printf("Press a key to continue");
_getch();
printf("\n");
}
int main(void){
int q;
for(;;){
_clrscr();
printf(
"1 - List cars\n"
"2 - Add new car\n"
"0 - Exit program\n");
scanf("%i",&q);
switch(q){
case 1:
listCars();
pause();
break;
case 2:
addRecord();
pause();
break;
case 0:
return 0;
break;
}
}
return 0;
}
a good sample of using malloc and realloc
Try using backtrace in gdb to see where the segmentation fault originates
I have a nested structure, the "inside structure" is a date structure with the members; day, month and year. The structures are contained in a dynamic array. I would like to loop through the structures and find which struct has the oldest date. I'm new to programming and not quite sure on how to approach this. Please help. Thanks!
#include <stdio.h>
#include <stdlib.h>
//define structure to store students birth date
struct date
{
int month;
int day;
int year;
};
//define structure to store student info and date structure for birth date
struct studentInfo
{
int iD;
struct date birthDate;
int phone;
};
int main(void)
{
//declare and initialize variables
int recNum = 0; //number of records
struct studentInfo * records = NULL; //struct pointer, array
//request user input and store in recNum for record amount
printf("\nHow many students do you need to enter records for?:");
scanf ("%d",&recNum);
//dynamically allocate memory
records = (struct studentInfo*)malloc((sizeof(struct studentInfo)*recNum));
//loop through records and request/store values from user
int count;
int studentNum=1;
for(count=0;count<recNum;count++)
{
printf("Please enter the following for student number %d\n",studentNum);
//request and store student ID
printf("Student ID#:");
scanf ("%d",&records[count].iD);
//request and store student phone number
printf("Student phone# (numbers only, 10 digits):");
scanf ("%d",&records[count].phone);
//error checking, check if phone number is 10 digits
int phoneCount = 0;
int phoneCopy = records[count].phone;
while(phoneCopy != 0)
{
phoneCopy /= 10;
phoneCount++;
}
if (phoneCount != 10)
{
printf("The number you have entered is not 10 digits, please re-enter:");
scanf ("%d",&records[count].phone);
}
//request and store student birthdate
printf("Student birthday (mm/dd/yyyy):");
scanf("%d/%d/%d",&records[count].birthDate.month,&records[count].birthDate.day,
&records[count].birthDate.year);
//test stuff
printf("Student number %d has an ID of %d and a phone number of %d\n", studentNum,
records[count].iD, records[count].phone);
studentNum++;
}
return 0;
}
#define NUMCMP(x,y) (((x) < (y)) ? -1 : ((x) > (y)) ? 1 : 0)
int compar_student_byDate(const struct studentInfo *student1, const struct studentInfo *student2){
struct date date1 = student1->birthDate;
struct date date2 = student2->birthDate;
int tmp;
if((tmp=NUMCMP(date1.year, date2.year))==0){
if((tmp=NUMCMP(date1.month, date2.month))==0)
return NUMCMP(date1.day, date2.day);
else
return tmp;
} else
return tmp;
}
struct studentInfo *oldest(struct studentInfo *records, int recNum){
struct studentInfo *old = records;
int i;
for(i = 1;i<recNum;++i){
if(compar_student_byDate(old, &records[i])>0)
old = &records[i];
}
return old;
}
at main
struct studentInfo *old_student = oldest(records, recNum);
Ok, first I should tell you that this is a question that can have many many many correct answeres.
You could instead of creating an array of strucutures studentInfo, create a tree and whenever you insert a new node into the tree keep the root node as the oldest among many other solutions. Anyway for your simple case, a simple solution could be as follows
Step 0. You want to find
studentInfo *oldest = records;
Step 1. Iterate through the array
studentInfo *traveler;
for(traveler = records; i<recNum; i++, traveler++)
Step 2. Compare the date from oldest and traveler.
if(oldest->birthDate.year > traveler->birthDate.year &&
oldest->birthDate.month > traveler->birthDate.month &&
oldest->birthDate.day > traveler->birthDate.day)
Step 3. Update the oldest record that you have found every time you find one
oldest = traveler;
When you finish the iteration, the oldest record should be the one you are looking for.