Segmentation fault after entering in a string from struct - c

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.

Related

Can you put a dynamic pointer to a regular array in C

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

C programming : Grouping multiple strings and searching for it using an Unique key

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++;
}

Not able to write a string to a *char[]

I've been at this for hours with little progress made. I need to know why exactly my program is crashing when scanf() is called. The error message: "Segmentation fault; core dumped" leads me to believe that I'm not allocating memory to the dynamic array correctly. If this is the case could someone tell me how I can correctly allocate memory to add one struct to the array?
#include <stdio.h>
#include <stdlib.h>
/*
*
*/
enum Subject{
SER = 0, EGR = 1, CSE = 2, EEE = 3
};
struct Course{
enum Subject sub;
int number;
char instructor_name[1024];
int credit_hours;
}*course_collection;
int total_courses = 0;
int total_credits = 0;
void course_insert();
void resizeArray();
int main(int argc, char** argv) {
int choice = 0;
while(choice != 4){
printf("Welcome to ASU, please choose from the menu"
"choices.\n\n");
printf("_____________________________________________\n\n");
printf("Menu:\n 1.Add a class\n 2. Remove a class\n"
" 3.Show classes\n 4.Quit");
printf("\n\nTotal credit hours: %d\n\n", total_credits);
printf("\n\n_________________________________________");
scanf("%d", &choice);
if(choice == 1){
resize_array(total_courses);
course_insert();
}
else if(choice == 3)
print_courses();
}
return (EXIT_SUCCESS);
}
void resize_array(int total_courses) {
course_collection = malloc(total_courses +
sizeof(course_collection));
}
void print_courses() {
int i;
for(int i = 0; i < total_courses; i++){
printf("\nInstructor: %s\n\n",
course_collection[i].instructor_name);
}
}
void course_insert(){
printf("\n\nEnter the instructor's name\n\n");
scanf("%s" , course_collection[total_courses].instructor_name);
total_courses++;
}
//will crash just after scanf();
//must press 1 & enter for correct output
After entering a few instructor names I choose the third option from the menu and that should iterate through the array and print each instructor's name but all I get are blanks lines and the last instructor name I imputed.
UPDATE
#user3545894 I've tried this and it seems to work fine but I still get the issue with the output not being correct. I should be able to iterate through the array and print the strings in each subscript.
The problem came from malloc(total_courses + sizeof(course_collection))
You only allocate array of pointer of course_collection.
You need allocate memory for whole the struct Course
It should be malloc(total_courses * sizeof(struct Course))
User this malloc(total_courses + sizeof(struct Course)) instead of malloc(total_courses + sizeof(course_collection))
segmentation fault due to memory allocation mostly for arrays
arr[n] we use it till '0' to 'n-1' { carefully observe not 'n'}

allocating in heap memory array of pointers to struct

I'm trying to make simple data base by using structure like
struct Employee{
char* name;
int ID;
int GPA;
int salary;
};
i know how i can allocate one pointer of the struct type in heap by using that
struct Employee* emp=malloc(sizeof(Employee));
my problem now that i'm not very good in allocating processes and i want
to allocate N number of pointer of the struct in the heap and i can't use arrays because the size will not be knows until running time
any suggestions ?
Yes, you need to allocate the memory dynamically, i.e. allocate a new heap block for every new struct Employee.
You can do this for example using realloc when the size changes:
yourArrayPtr=realloc(yourArrayPtr,newsize * sizeof(struct Employee));
The realloc function basically assigns a new amount of memory for the data pointed by its return value. It is a convenient way of expanding, or shrinking a dynamically allocated array. newsize here is the new number of elements of your array, and it is multiplied by the size of one Employee structure, rendering the total amount of space needed for your new array. The return value of realloc is assigned to your array pointer, so that it points specifically to this newly allocated space. In this case it could be used like this:
struct Employee* emp= NULL;
And then when you need it:
int n = 8;
emp = realloc (emp, n * sizeof(struct Employee));
Keep in mind, that you still have to free this memory.
You can now initialize and access this data:
emp[3] = {value1, value2, value3, ...};
As far as structures go, you could also think of another data structure - a linked list, where every structure contains a pointer to its successor. You can read about it here: http://www.cprogramming.com/tutorial/c/lesson15.html
In your case, it would be sth like:
struct Employee{
char* data;
struct Employee* next;
};
As others mentioned, you can use malloc to create as many entries of employee details in heap and store them in a dynamic list(linked list). i have given an example code, you can start from here and extend it, if you want to save the employee details before exiting, you can write it to a binary file and read it back when you run the program again(based on your needs), since once you program exits all the data will be lost.
#include <stdio.h>
#include <stdlib.h>
// Max length for employee name
const unsigned int MAX_NAME_LEN = 100;
typedef struct Employee{
char* name;
unsigned int ID;
int GPA;
float salary;
} EMPLOYEE ;
typedef struct emp_database_entry {
EMPLOYEE data;
struct emp_database_entry *next;
} EMPLOYEE_ENTRY;
typedef EMPLOYEE_ENTRY* EMPLOYEE_DATABASE;
// to create a new employee
EMPLOYEE_ENTRY* createEmployee() {
EMPLOYEE_ENTRY *newEmp = (EMPLOYEE_ENTRY*)malloc(sizeof(EMPLOYEE_ENTRY));
printf("Enter Employee Name:");
newEmp->data.name = (char*)malloc( MAX_NAME_LEN * sizeof(char) );
scanf("%s",newEmp->data.name);
printf("Enter employee ID:");
scanf("%u",&newEmp->data.ID);
printf("Enter employee GPA:");
scanf("%u",&newEmp->data.GPA);
printf("Enter employee salary:");
scanf("%f",&newEmp->data.salary);
newEmp->next = 0;
return (newEmp);
}
// add a new employee to database
EMPLOYEE_DATABASE addEmployee(EMPLOYEE_DATABASE db) {
EMPLOYEE_ENTRY *newEmp = createEmployee();
if(db == NULL) {
// add the first entry
db = newEmp;
} else {
// add it to the top
newEmp->next = db;
db = newEmp;
}
return (db);
}
// Search for Employee using ID
EMPLOYEE_ENTRY* searchEmployee(EMPLOYEE_DATABASE db, unsigned int ID) {
EMPLOYEE_ENTRY *employee = db;
if(employee == NULL) {
printf("There are no Employees in the database\n");
return (NULL);
}
// Search till the end, if a match is found return the
// pointer to employee
while( employee != NULL ) {
if( employee->data.ID == ID )
return (employee);
else
employee = employee->next;
}
return (NULL);
}
void printOneEmployee( EMPLOYEE_ENTRY *employee ) {
printf("Employee Details\n");
printf("Name : %s\n",employee->data.name);
printf("ID : %u\n",employee->data.ID);
printf("GPA : %d\n",employee->data.GPA);
printf("Salary: %f\n\n",employee->data.salary);
}
// Print all employee details
void printAllEmployee( EMPLOYEE_DATABASE db ) {
EMPLOYEE_ENTRY *employee = db;
// traverse till the end and print one by one
while( employee != NULL ) {
printOneEmployee(employee);
employee = employee->next;
}
}
// freeing allocated memory
void freeDatabase(EMPLOYEE_DATABASE db) {
EMPLOYEE_DATABASE employee = 0;
while( db != NULL ) {
employee = db;
db = employee->next;
free(employee->data.name);
free(employee);
}
}
void displayOption( EMPLOYEE_DATABASE db ) {
int option = -1;
while( option != 5 ) {
printf("\nEmployee DataBase\n");
printf("1: Add a Employee\n");
printf("2: Search Employee\n");
printf("3: Print All Employee\n");
printf("4: Exit\n");
printf("Enter a number for the choice: ");
scanf("%d",&option);
if( option > 4 || option < 0 ) {
option = -1;
}
switch( option ) {
case 1:
db = addEmployee(db);
break;
case 2:
int ID;
if(db != NULL){
printf("Enter the Employee ID: ");
scanf("%d",&ID);
printf("Search Result1: ");
printOneEmployee(searchEmployee(db, ID));
}
else
printf("No Employees in the database\n");
break;
case 3:
printAllEmployee(db);
break;
case 4:
freeDatabase(db);
printf("DataBase Deleted\nExiting..");
exit(0);
default:
printf("Invalid Option!. Try Again!.\n");
}
}
}
int main() {
EMPLOYEE_DATABASE db = 0;
displayOption(db);
return (0);
}
Of course you can use arrays if you use C99. In C99 you can do things like:
scanf("%d", &N);
struct Employee emp[N];
emp[0].ID = 123;
if you are using gcc (or MinGW), just be sure to compile with -std=c99
On the other hand, if you just want to create an array on the heap, you can do something like:
scanf("%d", &N);
struct Employee* emp=malloc(N*sizeof(Employee));
emp[0].ID =123;
...
// do not forget to deallocate emp
free(emp);

How do you assign values entered in a structure to an array?

I'm having a little trouble doing this. I'm creating a program that will store individuals information by ID number using a structure. I need to store then in an array then search through it with a for loop (easy). Whenever I try to compile I get an error saying request for member "blah blah" in something not a structure or union.
I'm getting this error for the final printf statement.
#include <stdio.h>
#include <stdlib.h>
struct infoStruct
{
int studentID;
int year;
int month;
int day;
int phone;
int end;
};
int main (void)
{
int students = 0;
struct infoStruct *info = NULL;
while (info.end != -1) {
students = students + 1;
printf("Enter student information (ID, day, month, year, phone)\n");
printf("Enter -1 following the phone number to end the process to continue enter 0\n");
info = malloc(sizeof(struct infoStruct) * students);
scanf("%d %d %d %d %d %d", &info.studentID, &info.day, &info.month, &info.year, &info.phone, &info.end);
}
printf("You entered %d student(s)\n", students);
printf("Enter Student ID\n");
scanf("%d", info.studentID);
}
First, your array should be of type infoStruct.
You should know the value of students. Then you can do something like:
for (int i=0;i<students;++i)
{
scanf(%d %d"[...],&infoArray[i].studentID, &infoArray[i].year[...]);
}
"info" is a pointer. So to access its values you should unreference it. As you are using array of struct you can do it in the following way:
scanf("%d %d %d %d %d %d", &info[some_counter].studentID, &info[some_counter].day, &info[some_counter].month, &info[some_counter].year, &info[come_counter].phone, &info[come_counter].end);
Also it is better to use realloc() call to change size of array of structs and fix in some way end of loop condition. Now it makes a crash because info is NULL and right before start you are trying to dereference this NULL pointer.
Loop with realloc() may look like following code:
while (true) {
printf("Enter student information (ID, day, month, year, phone)\n");
printf("To finish enter word \"end\"\n");
struct infoStruct *new_info = realloc(info, (students+1)*sizeof(struct infoStruct));
if (new_info == NULL) {
printf("Out of memory! errno = %s\n", strerror(errno));
break;
} else {
info = new_info;
}
result = scanf("%d %d %d %d %d %d",
&info[students].studentID,
&info[students].day,
&info[students].month,
&info[students].year,
&info[students].phone,
&info[students].end
);
if (result != 6) {
students--;
info = realloc(info, sizeof(struct infoStruct) * students);
break;
}
students++;
}
This:
int students = 0;
...
int infoArray [students];
...
while()
{
students = students + 1;
...
}
Will not work. You have to declare the size of your array a priori and it can't change during run-time without explicitly reallocating it.
What you can do is:
printf("What's the number of students you want?\n");
scanf("%d", &students);
...
int infoArray [students];
...
while(i++ < students)
{
// collect the data...
...
}
Since you can't change the size of the array dynamically in C without explicitly reallocating it, you will have to go for a linked list solution if you want a dynamic solution.
infoArray is declared a int. It does not provide structure elements like
infoArray.studentID. That causes the compiler to complain ... something not a structure or union.
infoArray [students]; with int students = 0; is questionable too.
You'd get (rewritten to suit the need. However, with some open questions):
#include <stdio.h>
#include <stdlib.h>
#define MAX_STUDENTS 200
typedef struct {
int studentID;
int year;
int month;
int day;
int phone;
int end;
} info_TYPE;
int main (void)
{
info_TYPE infoArray [MAX_STUDENTS];
int students = 0;
while (infoArray[students].end != -1) {
printf("Enter student information (ID, day, month, year, phone)\n");
printf("Enter -1 following the phone number to end the process to continue enter 0\n");
scanf("%d %d %d %d %d %d", &infoArray[students].studentID, &infoArray[students].day, &infoArray[students].month, &infoArray[students].year, &infoArray[students].phone, &infoArray[students].end);
students = students + 1;
if (students >= MAX_STUDENTS) break;
}
if (infoArray[students - 1].end = -1) printf("You entered %d student(s)\n", students);
printf("Enter Student ID", infoArray[students - 1].studentID);
// no idea what this line was for, presumably another previous attempt.
scanf("%d", infoArray[students - 1].studentID);
// getting tired to follow the speed at which the question is modified, presumably last edit here!
}
The compiler is complaining because
printf("Enter Student ID", infoArray.studentID);
treats infoArray.studentID as a structure member, which it is not.

Resources