Code:
struct T_Name
{
char *First;
char *Middle;
char *Last;
};
struct T_FullName
{
char *Title;
struct T_Name Name;
char *Suffix;
};
struct T_Person
{
struct T_FullName *FullName;
int Age;
char Sex;
struct T_Person *BestFriend;
};
typedef struct T_Person *ptrPerson;
ptrPerson pFriend[10];
struct T_Person Person[10];
How could I write necesarry code to dynamically allocate memory to store a value in pFriend[2]->FullName->Name.First?
Assuming you know the length of the first name to store,
// Allocate memory for FullName.
Person[2].FullName = malloc(sizeof(T_FullName);
// Allocate memory for the first name.
Person[2].FullName->Name.First = malloc(FIRSTNAME_LENGTH);
Your pFriend is a pointer variable, so you have to allocate memory for pointer variable first. Then after allocation of the memory again your FullName is pointer type , so we need to allocate memory for it, Finally your Name member in FullName is not a pointer type , so you can use First from Name with a . operator to allocate memory for it.
//Allocate space for T_Person
pFriend[2] = malloc(sizeof(T_Person);
//Allocate space for FullName
pFriend[2]->FullName = malloc(sizeof(T_FullName);
//Allocate space for First Name
pFriend[2]->FullName->Name.First = malloc(sizeof(urstringlength));
pFriend[2] = malloc( sizeof *pFriend[2] );
pFriend[2]->FullName = malloc( sizeof *pFriend[2]->FullName );
pFriend[2]->FullName->First = malloc( strlen(the_name) + 1 );
strcpy(pFriend[2]->FullName->First, the_name);
Note that you probably don't actually want to do this, it will be difficult to use this jumble of structures. You should at least set pointers which aren't in use to NULL , so that your other code can tell which pointers point to allocated memory and which ones don't.
Also, Person is unused in this example. If you wanted pFriend[i] to point at Person[i] you have to say that explicity; replace my first line with:
pFriend[2] = &Person[2];
Related
I want to be create a struct, but I also want to write its array or string elements with dynamic memory allocation.
struct st {
char *name[40];
int age;
};
For "name" string should I use malloc before struct, or can I use it in struct also.
1)
char *name = malloc(sizeof(char)*40);
struct st {
char *name;
int age;
};
2)
struct st {
char *name = malloc(sizeof(char)*40);
int age;
};
Are both of them true or is there any mistake? And if both of them are true, which one is more useful for other parts of code?
You need to create an instance of the structure, an actual variable of it. Then you need to initialize the members of the structure instance in a function.
For example, in some function you could do
struct st instance;
instance.name = malloc(...); // Or use strdup if you have a string ready
instance.age = ...;
An option would be to have a pointer in the struct however allocate memory outside of the struct within the function you use it.
e.g.
struct st {
char* n;
int a;
};
void foo() {
char* name = malloc(sizeof(char) * 40);
int age = 0;
struct st s = (struct st) {
.n = name,
.a = age,
};
/* TO DO */
free(name);
}
Declaring a type does not create lvalues (like variable). It defines the format of the lvalue. In 1), you have correctly declared a struct type, but you seem to have assumed the similarity of the "name" variable in struct declaration will associate the pointer "name" to struct member "name". It does not work that way.
2) is syntactically/symantically wrong. You simply cannot assign a malloc() to non-lvalue (as you are declaring a type struct)
So, create a variable out of struct type as you have created in 1) and allocate memory in the struct variable member.
typedef struct st {
char *name;
int age;
} st_type;
st_type st_var;
st_var.name = (char *) malloc(sizeof(char) * 40); // This is how you will allocate the memory for the struct variable.
Remember, before you can do dynamic allocation, you need to have a lvalue just like you did for standalone "name" variable.
I have the following code and I am trying to assign a value to the structure name but it is returning me segment core error. Why is that?
struct group {
char *name;
struct user *users;
struct xct *xcts;
struct group *next;
};
int add_group(Group **group_list_ptr, const char *group_name) {
Group *newGroup = malloc(sizeof(Group));
strcpy(newGroup->name, group_name);
}
You have malloc-ed the struct, but you did not malloc the string. The pointer inside the struct is uninitialized, so you cannot strcpy anything into it yet.
You have to allocate memory for your string, assign that memory to name, and only then do strcpy:
Group *newGroup = malloc(sizeof(Group));
newGroup->name = malloc(strlen(group_name)+1); // +1 for '\0' terminator
strcpy(newGroup->name, group_name);
I have a struct like this:
struct students {
char *names[MAXLENGTH];
};
How would I initialize the struct using malloc?
I tried
struct students student1 = {malloc(MAXLENGTH * sizeof(char**))};
but that gave me a "missing braces around initializer" error.
I'm new to C, so I'm not sure how to fix this.
You can allocate an instance of the struct like this:
struct students *pStudent = malloc(sizeof *pStudent);
This will allocate the array of string pointers (since it's part of the struct students), but not set the pointers to point at anything (their values will be undefined).
You need to set each individual string pointer, for instance like so:
pStudent->names[0] = "unwind";
This stores a pointer to a literal string. You can also allocate memory dynamically:
pStudent->names[1] = malloc(20);
strcpy(pStudent->names[1], "unwind");
of course, if you malloc() space you must remember to free() it. Don't mix literal strings with dynamically allocated ones, since it becomes impossible to know which ones need free()ing.
This is totally wrong struct students student1 = {malloc(MAXLENGTH * sizeof(char**))};
Try this code.
struct students* Student1 = malloc(sizeof(struct students ));
Student1->names[0] = malloc(sizeof(NAME_MAX));
scanf("%s",Student1->names[0]);//It may be first name. I think you want like this .
You have to use a for loop like this :
#define MAX_NAME_LENGTH 20
struct student s;
for(int i = 0; i < MAXLENGTH; ++i)
{
s.names[i] = malloc(sizeof(char) * MAX_NAME_LENGTH);
}
I'm having trouble making a database based on a singly-linked list in C,
not because of the linked list concept but rather the string fields in the struct themselves.
This is an assignment in C and as far as I know (I'm a newbie), C doesn't recognize 'string' as a data type.
This is what my struct code looks like:
typedef struct
{
int number;
string name;
string address;
string birthdate;
char gender;
} patient;
typedef struct llist
{
patient num;
struct llist *next;
} list;
I was thinking of making a struct for the strings themselves so that I can use them in the struct, like this:
typedef struct string
{
char *text;
} *string;
Then I will malloc() each one of them when it is required to make new data of the string type (array of char).
typedef struct string
{
char *text;
} *string;
int main()
{
int length = 50;
string s = (string) malloc(sizeof string);
s->text = (char *) malloc(len * sizeof char);
strcpy(s->text, patient.name->text);
}
Can someone help me figure this out?
Thank you.
On strings and memory allocation:
A string in C is just a sequence of chars, so you can use char * or a char array wherever you want to use a string data type:
typedef struct {
int number;
char *name;
char *address;
char *birthdate;
char gender;
} patient;
Then you need to allocate memory for the structure itself, and for each of the strings:
patient *createPatient(int number, char *name,
char *addr, char *bd, char sex) {
// Allocate memory for the pointers themselves and other elements
// in the struct.
patient *p = malloc(sizeof(struct patient));
p->number = number; // Scalars (int, char, etc) can simply be copied
// Must allocate memory for contents of pointers. Here, strdup()
// creates a new copy of name. Another option:
// p->name = malloc(strlen(name)+1);
// strcpy(p->name, name);
p->name = strdup(name);
p->address = strdup(addr);
p->birthdate = strdup(bd);
p->gender = sex;
return p;
}
If you'll only need a few patients, you can avoid the memory management at the expense of allocating more memory than you really need:
typedef struct {
int number;
char name[50]; // Declaring an array will allocate the specified
char address[200]; // amount of memory when the struct is created,
char birthdate[50]; // but pre-determines the max length and may
char gender; // allocate more than you need.
} patient;
On linked lists:
In general, the purpose of a linked list is to prove quick access to an ordered collection of elements. If your llist contains an element called num (which presumably contains the patient number), you need an additional data structure to hold the actual patients themselves, and you'll need to look up the patient number every time.
Instead, if you declare
typedef struct llist
{
patient *p;
struct llist *next;
} list;
then each element contains a direct pointer to a patient structure, and you can access the data like this:
patient *getPatient(list *patients, int num) {
list *l = patients;
while (l != NULL) {
if (l->p->num == num) {
return l->p;
}
l = l->next;
}
return NULL;
}
I think this solution uses less code and is easy to understand even for newbie.
For string field in struct, you can use pointer and reassigning the string to that pointer will be straightforward and simpler.
Define definition of struct:
typedef struct {
int number;
char *name;
char *address;
char *birthdate;
char gender;
} Patient;
Initialize variable with type of that struct:
Patient patient;
patient.number = 12345;
patient.address = "123/123 some road Rd.";
patient.birthdate = "2020/12/12";
patient.gender = 'M';
It is that simple. Hope this answer helps many developers.
While Richard's is what you want if you do want to go with a typedef, I'd suggest that it's probably not a particularly good idea in this instance, as you lose sight of it being a pointer, while not gaining anything.
If you were treating it a a counted string, or something with additional functionality, that might be different, but I'd really recommend that in this instance, you just get familiar with the 'standard' C string implementation being a 'char *'...
You could just use an even simpler typedef:
typedef char *string;
Then, your malloc would look like a usual malloc:
string s = malloc(maxStringLength);
This does not work:
string s = (string)malloc(sizeof string);
string refers to a pointer, you need the size of the structure itself:
string s = malloc(sizeof (*string));
Note the lack of cast as well (conversion from void* (malloc's return type) is implicitly performed).
Also, in your main, you have a globally delcared patient, but that is uninitialized. Try:
patient.number = 3;
patient.name = "John";
patient.address = "Baker street";
patient.birthdate = "4/15/2012";
patient.gender = 'M';
before you read-access any of its members
Also, strcpy is inherently unsafe as it does not have boundary checking (will copy until the first '\0' is encountered, writing past allocated memory if the source is too long). Use strncpy instead, where you can at least specify the maximum number of characters copied -- read the documentation to ensure you pass the correct value, it is easy to make an off-by-one error.
I want to copy values into a struct using a pointer.
I keep getting segmentation fault from this small piece of code.
struct companyInfo
{
double sharePrice;
char companyName[100];
};
int main()
{
struct companyInfo * pdata = NULL;
strcpy(pdata->companyName, "sdfsd");
exit(0);
}
You aren't allocating any space for the struct, just a pointer that is null.
struct companyInfo * pdata = NULL;
pdata = calloc( 1, sizeof(struct companyInfo) );
if( pdata != NULL )
{
strncpy(pdata->companyName, "sdfsd", sizeof(pdata->companyName) - 1);
}
Note: calloc() will also zero out the memory for you, as opposed to malloc() which will just allocate. Also, you should check the return of these functions to make sure the pointer is not NULL.
Important: Any memory allocated using malloc(), calloc(), ex.. needs to be explicitly freed.
Example:
if( pdata != NULL )
{
free( pdata );
}
exit(0);
companyInfo is a pointer to a struct, and that pointer is pointing to NULL. So when you try to dereference it, you get the seg fault. You either need to use malloc to allocate some space for the struct pointer to point to, or declare the struct on the stack.
For the purposes of your exercise, I would go with option 2, as it's simpler. Just do:
int main()
{
struct companyInfo pdata;
strcpy(pdata.companyName, "sdfsd");
exit(0);
}
Because there is no * after companyInfo, pdata is not a pointer to a struct, but a struct.
Try this:
int main() {
struct companyInfo pdata;
pdata.companyName = "sdfsd";
}
You can set all variables in the struct at once:
struct companyInfo pdata = { 2.3425, "company" };
Tip: Use typedef before using a struct:
typedef struct companyInfo companyInfo;
So you don't have to type "struct companyInfo" every time. You can now simply use:
companyInfo pdata;
Hope I helped :)
The problem isn't with using a struct, but with trying to use a null pointer. Try something like this:
struct companyInfo *pdata = malloc(sizeof(*pdata));
strcpy(pdata->name, "sdfsd");