I am trying to create an array of structures containing some basic information. My code is as follows:
typedef struct {
char firstName[30];
char lastName[30];
char street[35];
char city[20];
char state[3];
int zip;
char phone[15];
int accountId;
} Customer;
int main(void) {
int i, customer_number, _zip, _accountId;
struct Customer customer_list[9];
char _firstName[30], _lastName[30], _street[35], _city[20], _state[3], _phone[15];
for (i = 0; i < 10; i++) {
customer_number = 0;
printf("Enter data for customer %d: \n", customer_number);
printf("Enter First Last Phone: ");
scanf("%s%s%s", &_firstName, &_lastName, &_phone);
printf("\nEnter Address (Street City State ZIP): ");
scanf("%s%s%s%d", &_street, &_city, &_state, &_zip);
Customer customer_list[i] = {[i].firstName = _firstName}
}
return 0;
}
It seems like this should work, however I am getting an error saying " i must have constant value" Can anyone push me in the right direction? Thank you!
Customer customer_list[i] = {[i].firstName = _firstName}
This line needs to be
strcpy(customer_list[i].firstName, _firstName);
EDIT: assignment should be done by strcpy()
Related
I'm trying to create an array of Product structs and then print the name and code of each Product in the array, but I keep getting a segmentation fault. I have tried to insert each value without a loop and then printing, and it works, but I'd like to automate it. The function fill_products fills the products array according to the user's input, and the select_products prints each name-code pair for the entire array.
This is my code:
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int code;
char *name;
float price;
} Product;
void select_products(Product *products, int len)
{
int i;
printf("%-30s%s\n", "Name", "Code");
for (i = 0; i < len; i++)
{
printf("%-30s%d\n", products[i].name, products[i].code);
}
return;
}
void fill_products(Product *products, int len)
{
int i, code;
char *name;
float price;
for (i = 0; i < len; i++)
{
printf("Insert product name (%d / %d): ", i + 1, len);
scanf("%s", &name);
printf("Insert product price (%d / %d): ", i + 1, len);
scanf("%f", &price);
products[i].code = i;
products[i].name = name;
products[i].price = price;
}
return;
}
int is_alloc(Product *products)
{
if (products == NULL)
{
printf("Error: memory allocation unsuccessful.\n");
}
return products != NULL;
}
int main(void)
{
int len, n_bytes;
Product *products;
printf("Insert length of array: ");
scanf("%d", &len);
n_bytes = sizeof *products * len;
products = malloc(n_bytes);
if(!is_alloc(products))
{
exit(0);
}
fill_products(products, len);
select_products(products, len);
free(products);
return 0;
}
I keep getting a segmentation fault.
Please enable compiler warnings, and pay attention to them.
This code:
char *name;
...
scanf("%s", &name);
is bogus and doesn't do at all what you intend.
You must either allocate space for name separately (and then not forget to free() it), or make that space available in the Product structure like so:
typedef struct
{
int code;
char name[100];
float price;
} Product;
(this assumes there is a reasonable limit on name length).
Hi I'm inputting a structure of a family with children with those two structures:
typedef struct person {
int id;
char* firstName;
int age;
}person;
typedef struct family {
char* lastName;
person father, mother;
person* children;
int numChildren;
}family;
EDIT: this is the edited function and it still crashes :
int initializeHouse(family **pdata)
{
char temp[SIZE];
int size, i, j;
printf("enter the number of families\n");
scanf("%d", &size);
*pdata = (family*)malloc(sizeof( family)*size);
for (i = 0; i<size; i++)
{
printf("Please enter the last name\n");
scanf("%s", temp);
(*pdata)[i].lastName = (char*)malloc(sizeof(char)* (strlen(temp) + 1));
strcpy(pdata[i]->lastName, temp);
printf("Enter the fathers first name\n");
scanf("%s", temp);
initPerson(temp, &pdata[i]->father.firstName);
printf("enter the fathers ID\n");
scanf("%d", &pdata[i]->father.id);
printf("Enter the fathers age\n");
scanf("%d", &pdata[i]->father.age);
printf("Enter the mothers first name\n");
scanf("%s", temp);
initPerson(temp, &pdata[i]->mother.firstName);
printf("enter the mothers ID\n");
scanf("%d", &pdata[i]->mother.id);
printf("Enter the mothers age\n");
scanf("%d", &pdata[i]->mother.age);
printf("enter the number of children");
scanf("%d", &pdata[i]->numChildren);
(*pdata)[i].children= (person*)malloc(sizeof(person)*(pdata[i]->numChildren));
for (j = 0; j<pdata[i]->numChildren; j++)
{
printf("enter the kids name\n");
scanf("%s", temp);
initPerson(temp, &pdata[i]->children[j].firstName);
printf("enter the kids ID\n");
scanf("%d", &pdata[i]->children[j].id);
printf("Enter the kids age\n");
scanf("%d", &pdata[i]->children[j].age);
}
}
return size;
}
void initPerson(char* str, char** fam)
{
*fam = (char*)malloc(sizeof(char)*(strlen(str) + 1));
strcpy(*fam, str);
}
EDIT: I changed the code and it still doesn't work, and it requires me to write some description so here it is ..
int main() {
int size;
family *a = NULL;
size=initializeHouse(&a);
}
declares a pointer to a family structure. When you pass it's address
size = initializeHouse(&a);
the function gets it as a family**
Okay, we're all on the same page to this point. When you allocate the target of that pointer
*pdata = malloc(sizeof(family) * size);
then *pdata points to an allocated array of structs, not pointers to those structs. Each struct is accessed by (*pdata)[i], which means -> dereference the double pointer pdata to get the address of the first element in the array, then access the array element with a subscript.
So your assignment should be
(*pdata)[i].lastName = malloc(sizeof(char)* (strlen(temp) + 1));
You use the dot . operator to access the members, because the result of the subscript access is a struct, not a pointer to a struct.
This little example using (*pdata)[i]. doesn't crash.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 40
typedef struct person {
int id;
char* firstName;
int age;
}person;
typedef struct family {
char* lastName;
person father, mother;
person* children;
int numChildren;
}family;
int initializeHouse(family **pdata)
{
char temp[SIZE];
int size, i, j;
printf("enter the number of families\n");
scanf("%d", &size);
*pdata = malloc(sizeof(family)*size);
for (i = 0; i<size; i++)
{
printf("Please enter the last name\n");
scanf("%39s", temp);
(*pdata)[i].lastName = malloc(sizeof(char)* (strlen(temp) + 1));
strcpy ( (*pdata)[i].lastName, temp);
}
return size;
}
int main ( void) {
int size;
family *a;
size=initializeHouse(&a);
}
It's important that you understand the memory layout.
family *fam;
family **pdata = &fam;
*pdata = (family*)malloc(sizeof(family)*size);
You have essentialy this: fam is a uninitialized pointer of type family.
pdata is a double pointer initialized with the address of fam. The malloc
call allocates space for size family-objects. By doing *pdata = malloc(...)
you are initializing fam.
This is the basic memory layout you have. base is the address returned by
malloc. slf is the size of struct family object, fpl is the size of a
pointer to a struct family object.
base = address returned by malloc
sfl = sizeof(struct family)
fpl = sizeof(struct family*)
base + 0 base + slf base + 2 * slf
+-----------------+------------------+------------------+
|struct family | struct family | struct family |
+-----------------+------------------+------------------+
base + 0 base + fpl base + 2*fpl base + 3*fpl base + 4*fpl
+------------+------------+------------+------------+-----------+
| pdata[0] | pdata[1] | pdata[2] | pdata[3] | pdata[4] |
+------------+------------+------------+------------+-----------+
The first row shows the memory in terms on struct family objects, the second
row shows you the same memory in terms on pointers (to struct family object).
This is very important distinction, because pdata[i] returns you a
pointer, not the object.
Remember pdata is a double pointer, pdata[i] is the equivalent to pdata + i,
that is the ith pointer begining at base.
Because the size of an struct family is defintitely different that the size of
a pointer, you see that the block don't align, that means
base + slf != base + fpl.
In the first iteration you are lucky, because pdata[0] and (*pdata)[0] are
the same. But pdata[1] and *(pdata)[1] are not the same. So doing
pdata[1]->lastname (instead of (*pdata)[1].lastname) you are accessing at a
wrong location in you allocated memory.
The easiest way to fix you code would be to change the pdata[i] in (*pdata)[i] as shown
in user3121023's answer.
edit
I see that user3121023 has retracted his answer. Basically it did:
printf("enter the fathers ID\n");
scanf("%d", &((*pdata)[i].father.id));
in the loop.
Fixing the pointers may have solved your problem. But the program has a lot of duplicate code and rewriting as follows would help you test a small portion and debug the program easily.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 100
typedef struct person {
int id;
char *firstName;
int age;
} person;
typedef struct family {
char *lastName;
person father, mother;
person *children;
int numChildren;
} family;
void input_string(const char *prompt, char **where) {
char temp[SIZE];
printf("%s\n", prompt);
scanf("%s", temp);
*where = malloc(sizeof(char) * (strlen(temp) + 1));
strcpy(*where, temp);
}
void input_int(const char *prompt, int *where) {
printf("%s\n", prompt);
scanf("%d", where);
}
void input_person(const char *name, person *person) {
char prompt[SIZE];
sprintf(prompt, "Enter the %s's first name", name);
input_string(prompt, &person->firstName);
sprintf(prompt, "Enter the %s's ID", name);
input_int(prompt, &person->id);
sprintf(prompt, "Enter the %s's age", name);
input_int(prompt, &person->age);
}
void input_family(family *fam) {
input_string("Please enter the last name", &fam->lastName);
input_person("father", &fam->father);
input_person("mother", &fam->mother);
input_int("Please enter the number of children", &fam->numChildren);
fam->children = malloc(sizeof(person) * (fam->numChildren));
for (int i = 0; i < fam->numChildren; i++) {
input_person("kid", &(fam->children)[i]);
}
}
int initializeHouse(family **families) {
int size;
input_int("Please enter the number of families", &size);
*families = malloc(sizeof(family) * size);
for (int i = 0; i < size; i++) {
input_family(&(*families)[i]);
}
return size;
}
int main() {
int size = 0;
family *a;
size = initializeHouse(&a);
printf("Successfully inputted %d families", size);
return 0;
}
I'm having problems inputting values into this structure template, please help.
I've got to use char* for those attributes. so it doesn't give an error while inputting data but crashes when its time to display.
#include<stdio.h>
#include<malloc.h>
#include<conio.h>
struct Date
{
int day;
char *month;
int year;
}date;
struct sports_team
{
char *name;
char *city;
int no_of_players;
struct Date creation_date;
};
void main()
{
struct sports_team *my_team;
my_team = (struct sports_team*)malloc(sizeof(struct sports_team)*2);
printf("fill information for teams:\n");
for(int i=0;i<2;i++)
{
printf("\nenter team name:");
scanf("%s",&my_team[i].name);
printf("\nenter team city:");
scanf("%s",&my_team[i].city);
printf("\nenter no. of players:");
scanf("%d",&my_team[i].no_of_players);
printf("\nenter creation day:");
scanf("%d",&(my_team[i].creation_date.day));
printf("\nenter creation month:");
scanf("%s",&(my_team[i].creation_date.month));
printf("\nenter creation year:");
scanf("%d",&(my_team[i].creation_date.year));
printf("\n\n");
}
printf("\n information for teams:\n");
for(int i=0;i<2;i++)
{
printf("%s ",my_team[i].name);
printf("%s ",my_team[i].city);
printf("%d ",my_team[i].no_of_players);
printf("%d ",my_team[i].creation_date.day);
printf("%s ",my_team[i].creation_date.month);
printf("%d ",my_team[i].creation_date.year);
printf("\n\n");
}
free(my_team);
}
you're allocating the structures all right but you're forgetting to allocate memory for char * members: you're writing into uninitialized memory when doing scanf (not to mention that you're passing the address of the pointer, not the pointer itself: don't use & when scanning strings).
For simplicity's sake, you could just put fixed buffer lengths in your structures:
struct Date
{
int day;
char month[20];
int year;
}date;
struct sports_team
{
char name[100];
char city[100];
int no_of_players;
struct Date creation_date;
};
and limit size when scanning (don't use & when scanning strings BTW)
scanf("%99s",my_team[i].name);
scanf("%99s",my_team[i].city);
scanf("%19s",my_team[i].creation_date.month);
Use getchar() instead of scanf().
I have an issue with my code, I changed a few of the functions to accomodate the structure I added, so instead of having variables all over the place, but now it does not work at all. I need it to create a structure person, then it prompts the user to enter the persons name, and age; then it asks for more persons to fill a doubly linked list which stops the loop if nothing is input for the persons name. THEN it spits out the reverse of what I input into the doubly linked list. All help is appreciated ^-^
struct person
{
char name[10][41];
int age[10];
};
int write(struct person *people);
void print(struct person *people);
int main(void)
{
char names[10][41];
int n = 10;
int ages[10];
typedef struct person people;
n = write(people);
print(people);
system("PAUSE");
return 0;
}
int write(struct person *people)
{
int i;
char name[41];
int age[10];
for(i=0; i<=i; i++)
{
fflush(stdin);
printf("Enter full name\n");
gets(people.name);
strcpy(names[i], name);
if(names[i][0] == '\0')
break;
printf("Enter their age\n");
scanf("%d", &age[i]);
ages[i] = age[i];
}
}
void print(struct person *people)
{
int i = 0;
for(i = 0; i < 10; i++)
{
if(names[i][0] == '\0')
break;
printf("%s is %d year(s) old\n", names[i], ages[i]);
}
return i;
}
You are passing the name of a type that you just defined instead of a variable declared of that type, this
typedef struct person people;
should be
struct person people;
Change
n = write(people);
to
n = write(&people);
Remove fflush(stdin) it's undefined behavior.
Do not use gets() it's very unsafe, use fgets() instead
char name[40];
gets(name);
should be
char name[40];
fgets(name, sizeof(name), stdin);
I'm not sure if I'm asking the right question. lets say we have the following
typedef struct {
char month[2];
char day[2];
char year[4];
} dateT;
void dates(dateT* ptrDateList);
int main()
{
dateT* ptrList;
scanf("%d", &n);//number of date entries
ptrList = malloc(n*sizeof(dateT));
for (i=0; i<n; i++)
dates(&ptrList[i]);
}
void dates(dateT* ptrDateList);
{
char inputMonth[2];
char inputDay[2];
char inputYear[4];
scanf("%s",inputMonth);
strcpy(ptrDateList->month,inputMonth);
scanf("%s",inputDay);
strcpy(ptrDateList->day,inputDay);
scanf("%s",inputYear);
strcpy(ptrDateList->year,inputYear);
}
how you compare the value of day in ptrList[2] with lets say the value of day in ptrList[5]
I know that if I did
dateT list2={5,10,2009};
dateT list5={7,10,2009};
I could do
list2.day == list5.day
but how would I do that with the arrays
ptrList[2].day == ptrList[5].day would work if the type was say integer, but as you store the characters you might want to use strcmp, like so:
if ((strcmp(ptrList[2].day,ptrList[5].day) == 0) // same day
note that you need an extra character for the end of string sentinel \0,
so it should be;
typedef struct {
char month[3];
char day[3];
char year[5];
} dateT;
another issue is the way you handle input: can you be sure that the user will provide valid input? for instance you could use scanf("%2s", string); to input the day (of max. length two).
Here's pretty much what jev already explain. Just I thought I might as well post it, since it works.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
char month[3];
char day[3];
char year[5];
} dateT;
void dates(dateT* ptrDateList);
int main()
{
dateT* ptrList;
int i, n;
printf("Enter number of dates: ");
scanf("%d", &n);//number of date entries
ptrList = malloc(n*sizeof(dateT));
for (i=0; i<n; i++)
dates(&ptrList[i]);
if (n > 1) {
if (!strcmp(ptrList[0].day,ptrList[1].day)) {
printf("First two days match.\n");
} else {
printf("First two days don't match.\n");
}
}
return 0;
}
void dates(dateT* ptrDateList)
{
char inputMonth[3];
char inputDay[3];
char inputYear[5];
printf("Enter month: ");
scanf("%2s",inputMonth);
inputMonth[2] = '\0';
strcpy(ptrDateList->month,inputMonth);
printf("Enter Day: ");
scanf("%2s",inputDay);
inputDay[2] = '\0';
strcpy(ptrDateList->day,inputDay);
printf("Enter Year: ");
scanf("%4s",inputYear);
inputYear[4] = '\0';
strcpy(ptrDateList->year,inputYear);
}