Instantiating a new struct from pointers in C - c

This is part of a homework assignment that I've benn struggeling with for days now.
So we define this struct
typedef enum { male = 0, female } gender;
struct person {
char name[30];
gender genderValue;
int age;
float weight;};
Now, we are given this function
int add(char* name, char* genderValueString, int age, float weight){}
And we are asked to construct a new person inside that function.
I tried different methods but keep getting errors and can't even get the name right.
struct person newperson = {.name = *newname, //...rest of code..};
only read the first character and ignores the rest.
How do I get the values passed into a newperson person.
This doesn't work either :
char newname[30];
strcpy_s(newname, 30, name);
struct person newperson = { .name = newname //...}

There's two problems:
The first is that you dereference the pointer variable newname. That gives you the value the pointer is pointing to, which is really just the first letter of the string.
The second problem is that you can't initialize an array with a pointer or another array. You have to copy arrays. For string you should use strcpy (or strcpy_s if it's available).

Related

Initializing and accessing char array in struct

I cannot seem to find a way to initialize a struct without getting segmentation fault .
Here is the assignment `
int id = 5;
// scanf ("%10d", &id);
printf("Please give an name\n");
char *tmpName = (char*)malloc(MAXSTRING * sizeof(char));
fgets(tmpName,MAXSTRING,stdin);
student newStudent = (student){ .id = id , .name = tmpName };
printf("%d",newStudent.id);
printf("%s",newStudent.name);
`
And here is the struct itself
#define MAXSTRING 256
typedef struct{
char *name;
int id;
}student;
I can successfully initialize the struct , but I cannot get access to the name variable , any thoughts?
EDIT : Answers submitted at the time offered nothing , the problem was the way the struct was initialized
char tmpName[MAXSTRING] = {0};
scanf("%s",tmpName);
student newStudent = { .id = id };
strcpy(newStudent.name,tmpName );
This block fixed the issue , will close the topic.
You define a pointer
char *tmpName;
you do nothing to make it actually point to some useable space, especially there is no malloc() or similar.
The you have scanf() (if successful...) write to the pointer, but a string, not any meaningful address. I.e. if that string is not extremely short, you certainly write beyond.
scanf("%s",&tmpName);
Do not be surprised by segfaults, be surprised if there are none.
Later on you then read from where that weird non-pointer points to...
To solve, insert a malloc() after the pointer definition. Alternatively use fixed array of char as an input buffer.
Use the pointer itself, not its address, in scanf() to write the string into the malloced space. (Or the array identifier.)
The rest is the typical set of problems with having enough space, failing to scan, without checking return value etc. Here is a great set of basic hints for getting input right:
How to read / parse input in C? The FAQ
When you declare char name[MAXSTRING], you are telling your compiler that it will always have the exact length of MAXSTRING.
When the compiler hears that, he will most likely replace your string with a lot of static char members.
#define MAXSTRING 4
typedef struct{
char name[MAXSTRING];
int id;
}student;
Would be extended and compiled more like so :
#define MAXSTRING 4
typedef struct{
char name0;
char name1;
char name2;
char name3;
int id;
}student;
Although you would still need to access those using the syntax name[index], as you declared an array, the array pointer is in fact nowhere to be found. So you can't directly assign it.
This is basically what happens with any fixed-length array, they won't allow you to asign them since their content is directly stored in the stack or in the datastructure enclosing it.
You would need to declare.
typedef struct{
char *name;
int id;
}student;
To get a char array pointer of variable length that you can assignate.
That should answer your question, now, as stated by someone in your comment section, there are other things wrong in your code and even with the correct structure, you will probably be unnable to do what you want since scanf is probably returning an arror right now. ^^'
Try allocating the memory beforehand doing so :
char *yourstring = (char*)malloc(MAXSTRING * sizeof(char));
And of course, don't forget to free when you don't need either the string or your student structure :
free(yourstring);
Then again, there's another small issue with your assignement since you do something like this :
.name = *yourstring
While using pointers, prefixing them with * will access the value at the pointed address.
Supposing char *yourstring = "I love cats.";
Doing .name = *yourstring will result in .name being equal to 'I' character, which is first in the array pointed to by yourstring. (Most compiler would complain and ask you to cast.. do not do that.)
So what you really need to do is to assign the pointer to your .name array pointer.
.name = yourstring

Passing in a character string in a linked list struct

I have declared my struct as
struct linkedStruct
{
char name;
int size;
enum groupstatus status;
struct linkedStruct* next;
};
I am trying to pass a char* name variable(a string of characters) in my code into a single node of this struct.
For example, user enters in Jon, i want my char name to store the character string Jon.
I am having some trouble figuring how to go about this. I tried just simply stating (assuming my node name is temp)
temp->name = name;
However when I print out the name value when I store it, printf returns nothing.
I originally had it as name[30] in my struct, as we are to assume that the name is less than 30 characters, however this ultimately confused me more because I kept getting errors when trying to store the name into the struct with a for loop.
Other implementation of my struct
struct linkedStruct
{
char name[30]; //now a character array
int size;
enum groupstatus status;
struct linkedStruct* next;
};
The code was
for(int i = 0; i< sizeof(name); i++){
name[i] = temp->name[i];
//seemed totally wrong to do but I had no idea how to go about it
}
I was just wondering how I would go about storing it in either situation, as my current code does not work. In my name[30] implementation, I have no idea how to state/access the array notation of the struct.
It's not possible. A variable of type char has room for exactly one character.
If you know names are limited to 30 characters, you should have
char name[30];
in the structure declaration. Strings in C are copied using strcpy(), so you'd do something like this to set the name inside the structure:
struct linkedStruct temp;
strcpy(temp.name, "hello");
You need:
strcpy(temp->name, name);
Instead of:
temp->name = name;
Which copies a string from the pointer temp->name to memory at pointer name.
Note
You must ensure that name string doesn't contain more than 29 characters.

C - Incompatible types in assignment - structs and character arrays

Alright so the gist of my situation is that I'm stuck receiving an incompatibles types in assignment when trying to initialize my struct. I am fairly new to C and understanding pointers proves quite the challenge for me but I have looked at similar questions to this error and tried different fixes and have had no luck so far. If someone could fix this for me, you would be my hero.
struct Employee {
char* name[100];
int birth_year;
int starting_year;
};
struct Employee* make_employee(char* name, int birth_year, int starting_year);
int main(){
//some main stuff code
}
struct Employee* make_employee(char* name, int birth_year, int starting_year){
struct Employee* newEmpl = (struct Employee*)malloc(sizeof(struct Employee));
newEmpl->name = name;
newEmpl->birth_year = birth_year;
newEmpl->starting_year = starting_year;
return newEmpl;
}
The assignment errors occurs on the name = name line. I don't know why.
Also if I switch that line with
strcpy(&(newEmpl->name), name);
I get:
warning: passing argument 1 of 'strcpy' from incompatible pointer type
I've tried to find the problem for 2 hours, and no luck, thought I'd give a shot here.
char* name[100];
is an array of pointers to char but:
char* name;
is a pointer to char.
Here:
newEmpl->name = name;
You are trying to assign a pointer to char to the array but you cannot in C assign a pointer to an array! In fact you cannot assign anything to an array in C.
Check you are using the correct types in your program. Are you sure you want to use char *name[100]; and not char name[100]; (an array of char)? Then to copy a string it, use strcpy or strncpy and not the = operator as you cannot assign something to an array.
In your structure, change
char* name[100]; //an array of pointers to character
to
char name[100]; // a character array
Then, in your make_employee() function, instead of
newEmpl->name = name; //arrays cannot be assigned
use
strcpy(newEmpl->name, name); // copy the contains of name to newEmpl->name
or
strncpy(newEmpl->name, name, 99); // limit to 99 elements only + terminating null
Notes:
Please do not cast the return value of malloc() and family.
Please check for the success of malloc() and family before using the returned pointer.

What does this snippet from Exercise 16 from "Learn C The Hard Way" mean?

I am learning C from this blog. Below is some code from the blog:
struct Person *Person_create(char *name, int age, int height, int weight)
{
struct Person *who = malloc(sizeof(struct Person));
assert(who != NULL);
who->name = strdup(name);
who->age = age;
who->height = height;
who->weight = weight;
return who;
}
I have the following doubts:
Is Person_create the name of this function? How could a function name be a pointer? What does it signify?
Why strdup(String Duplicate) is used just for name, not other fields like height, age, etc.
For it would be clear the function declaration can be written the following way
struct Person * Person_create(char *name, int age, int height, int weight);
That is the function name is Person_create and the function returns an object of type struct Person *. As you can see in its definition the function returns who that is defined as
struct Person *who = malloc(sizeof(struct Person));
You could write even the function declaration for example like
struct Person * ( Person_create(char *name, int age, int height, int weight) );
Take into account that for example all the following declarations are equivalent
int *p;
int* p;
int * p;
As for the second your question then it seems that data member name is declared like
char *name;
You need to allcoate memory that will be pointed to by name that to store the string pointed by parameter name in this memory. Function strdup does two things. It allocates required memory and copies string pointed by the parameter to the allocated memory and returns pointer to that memory.
As for other data members of the structure then they are not pointers. They are objects (though a pointer is also an object but it points to other object that has to be stored somewhere). So you need not to allocate memory that to store data in these objects. The memory for these data members will be allocated when an instance of the structure will be created.
Person_create is a function. It could also be written as struct Person* Person_create which would be syntactically identical. Whether to put the space next to the type or next to the name is a a debate as old as the C language which I refuse to get involved in.
As you might have noticed, the name-string is a pointer. When you would do just who->name = name; you wouldn't copy the string. You would just copy the pointer to a string. The result would be that you have two pointers which point to the same string. Why is this a problem? Imagine you make some change the name in one of the structs. The change would then also affect the other struct. This is likely not your intention.
That's why you need strdup(). It stands for "string duplicate". It creates a copy of a string and returns a pointer to the newly created string which can then be handled independently from the original.
Person_create() is a function, which returns struct Person * (a pointer to a Person struct). It could also be written as following: struct Person * Person_create() or struct Person* Person_create().
strdup() is used only for the name variable, as name is the only string (char*/char array in C) variable in the Person struct.
So why do you need to use strdup() on char* and you do not have to use similar functions for types like int?
This is because in C you pass by value, meaning that you will pass a value of an int age (which you can assign using =) and a value of char*. The *char pointer points to same place in memory, which ends with \0 (symbol of string/char array termination in C). Therefore you have to use a separate function to copy all the characters between where char* name points to when passed to the function and the \0 (together with the \0).

display a specified index of a pointer char*

I am trying to point on a specified character in a string contained on a structure
here my code
typedef struct{
char *name;
int age;
}PERSON, *person;
int main(){
person serenity;
serenity = (person)malloc(sizeof(PERSON));
strcpy(&(serenity->name),"Serenity");
printf("%c",*(&(serenity->name)+1));
}
here i wanted to display the second character which is 'e' but it shows 'n' instead
anyone can explain me what is wrong with this,
thank you
You have not allocated memory for name
typedef struct{
char *name;
int age;
}PERSON, *person;
int main(){
person serenity;
serenity = malloc(sizeof(PERSON));
serenity->name = malloc(sizeof("Serenity")); //<< Missing
strcpy((serenity->name),"Serenity");
printf("%c",*((serenity->name)+1)); // << Also you want the value in pointer name NOT its address
return 0;
}
Outputs e. Also since you tagged C there is no need to cast the return type of malloc.
Okay, okay... All of those answers aside, if you do not aim to change the characters inside the string "Serenity" in the future, you could just do the following:
#include <stdio.h>
typedef struct{
const char *name; // <-- added const
int age;
}PERSON, *person;
int main( ){
person serenity;
serenity = (person) malloc( sizeof( PERSON ) );
serenity->name = "Serenity"; // <-- simply assigned the pointer with the
// address to the array of constant characters
printf( "%c", *( serenity->name + 1 ) ); // <-- changed this
}
This statement
serenity = (person)malloc(sizeof(PERSON));
allocates the structure
typedef struct{
char *name;
int age;
}PERSON
however name is kept uninitialized and points somewhere in memory causing a crash when you copy to it.
So instead of
strcpy(&(serenity->name),"Serenity");
write
serenity->name = strdup("Serenity");
which is the same as
serenity->name = malloc(strlen("Serenity")+1);
strcpy(serenity->name,"Serenity");
don't forget to free that string as well later.
Try printf("%c",*(serenity->name+1));, also do strcpy(serenity->name,"Serenity");.
If you have a pointer char* name; you access the second element by doing name[1] or *(name+1). &name will give you the address where the pointer address of name is stored. This is not what you want here.
Another issue in your program is that you never allocate memory for the variable name. You need a serenity->name = (char*)malloc(128);. But using an arbitrary length like 128 is very dangerous in combination with strcpy. Use strncpy instead of strcpy to work around this.

Resources