How to use struct pointer to set char name? - c

struct player {
char name[20];
struct player *next;
};
int main() {
struct player *p;
p.name = "bob";
}
error: request for member 'name' in something not a structure or union
How would I set a char name with a struct?

In that little piece of code you have multiple problems.
The first, about the error you get, you should have been told by just about any book or tutorial, good or bad. You need to use the "arrow" operator ->, as in p->name.
But then you would get another error, because you can't assign to an array, only copy to it.
And when that's done, you still have one more error, and that is your use of an uninitialized pointer. Uninitialized local variables (which is what p) is are really uninitialized. Their values will be indeterminate and seemingly random. Attempting to dereference (what you do with ->) such a pointer will lead to undefined behavior.
In short, I recommend you to go back to your text book, and start over from the beginning.

The simplest fix is to not declare p as a pointer to a struct, but rather an actual struct....and then use strcpy() to set name. C doesn't use = for string assignment like some other programming languages.
struct player {
char name[20];
struct player *next;
};
int main() {
struct player p;
strcpy(p.name, "bob");
}

Related

How to access position of an array of struct using pointer

Answer (see below): When accessing a struct with a pointer, one needs to use the arrow operator "myStruct->structVariable" which is the equivalent to "(*myStruct).structVariable" which is called dereferencing a pointer (getting the value instead of the address). When accessing the struct directly one uses "myStruct.structVariable".
I'm pretty new to C and pointers and am trying to do the following:
I'd like to access an array of structs which is part of another struct. The struct is a pointer which gets passed to a function, in which i would like to access it.
Student has an array of structs which 10 Lectures (also a struct). To simplify the process of adding lectures to a student, i would like to be able to call the function "addLectureToStudent()" and passing the necessary arguments and assign the values to the array of lectures.
typedef struct Lectures {
char name[20];
} Lecture;
typedef struct Students {
char name[20];
Lecture lectures[10];
} Student;
void addLectureToStudent(Student * stud, int position, char lecture_name[20]){
strcpy(stud->lectures[position]->name, lecture_name); //This line doesn't work as expected
}
int main(void) {
Student markus;
strcpy(markus.name, "Markus");
markus.matrikelnummer = 12089548;
addLectureToStudent(&markus, 0, "Programming");
}
My problem is, that when wanting to access strcpy(stud->lectures[postition]->name, lecture_name) it tells me that stud should be a pointer but isn't (thats the best translation i can come up with. It is originally in german..). How do i access the array of lectures properly in this case?
stud->lectures[position] is Lecture, so you should use ., not ->, to access that.
strcpy(stud->lectures[position].name, lecture_name);
There are two ways to access the structure elements, usng a pointer to a structure.
Using dereference operator and dot (* and .)
strcpy((*stud).lectures[position].name, lecture_name);
Using arrow (->)
strcpy(stud->lectures[position].name, lecture_name);
markus.matrikelnummer = 12089548; This is wrong, because there is no element matrikelnummer in structure Student.
General syntax is pointer_name->variable_name and (*pointer_name).variable_name

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

Questions about a college project

I have
the struct:
typedef struct Rental {
int nDays;
float kmsDriven;
char carLicensePlate[LICENSE_PLATE_LENGTH+1];
char *clientName;
char chargingCategory;
} Rental;
Different -Rental type- structs are stored and accessed via a dynamically allocated array of pointers (here is a part of the project):
int main (){
Rental *rentals;
int max_num;
printf("Give a number of rentals you would like to store and manage: ");
scanf("%d", &max_num);
rentals=(Rentals *)malloc(max_num * (sizeof(Rental)))
This is what I have thought of so far but I can't understand it completely...so:
I'm having trouble understanding how *rentals can be an array. I mean shouldn't I declare it at least this way: Rental *rentals[];? I know that if I compile the above code I will see an error...but why?
I've read numerous posts here in Stack Overflow about doing this with double pointers (Rental **rentals;) but the code other people have posted is often very hard for me to read (I don't know all the functions etc. etc.)
Let's say I have the object rentals[0] which will be a pointer towards rentals. If I wanted to pass the struct to a function, should I write:
variable=function(*arguments*... , Rental *rentals[0]);?
rentals is a pointer, not an array, but it is a pointer to the first (zeroth) element of a block of max_num structures, so it can be treated as an array in that you can use rentals[n] to refer to the nth element of the array.
This is not a question and hence it is unanswerable.
Let's say I have the object rentals[0] which will be a pointer towards rentals. If I wanted to pass the struct to a function, should I write: variable=function(*arguments*... , Rental *rentals[0]);?
rentals[0] is not a pointer; it is a struct Rental or Rental.
If you want to pass the structure to the function, you write:
variable = function(…args…, rentals[0]);
If you want to pass a pointer to the structure to the function, you write:
variable = function(…args…, &rentals[0]);
or:
variable = function(…args…, rentals);
These pass the same address to the function.
You should be error checking the call to scanf() to make sure you got a number, and you should error check the number you got (it should be strictly positive, not zero or negative), and you should error check the value returned by malloc().
When you declare an array (for example char buffer[10]; the variable is actually pointing to that array. Pointers and arrays are very close together. In fact when you have a pointer where you store an array of data (just like your case with malloc) you can do something like pointer[0] and pointer[1] to get the correct element.
With a pointer in order to access an element you'd normally use *(pointer +1) to get the element on position 1, this is exactly the same as pointer[1].
When you want to pass a struct in an array, you can either give it by value like this:
void function(struct mystruct var)
{
//...
}
int main()
{
struct mystruct var;
function(var);
}
Or by reference (passing the address instead of the data - this is ideal if your structs are big in size) :
void function(struct mystruct *var)
{
//...
}
int main()
{
struct mystruct var;
function(&var);
}
By using an array, you can do it like this (still by reference):
void function(struct mystruct *var)
{
//...
}
int main()
{
struct mystruct var[10];
function(&var[0]);
}
And using a pointer (to an array) :
void function(struct mystruct *var)
{
//...
}
int main()
{
struct mystruct *var;
var = malloc( sizeof(struct mystruct) *10 );
//This will pass the address of the whole array (from position 0)
function(&var);
//This will pass the address of the selected element
function(&var[0]);
}
As you can see, declaring an array or a pointer is almost the same, expect that you have to initialize the pointer-array yourself (with malloc) and as with anything created with malloc you have to free it yourself too.

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 the code below mean, in regards to structs in C?

I'm really new to C programming and I'm still trying to understand the concept of using pointers and using typedef structs.
I have this code snippet below that I need to use in a program:
typedef struct
{
char* firstName;
char* lastName;
int id;
float mark;
}* pStudentRecord;
I'm not exactly sure what this does - to me it seems similar as using interfaces in Objective-C, but I don't think that's the case.
And then I have this line
pStudentRecord* g_ppRecords;
I basically need to add several pStudentRecord to g_ppRecords based on a number. I understand how to create and allocate memory for an object of type pStudentRecord, but I'm not sure how to actually add multiple objects to g_ppRecords.
defines a pointer to the struct described within the curly bracers, here is a simpler example
typedef struct {
int x;
int y;
}Point,* pPoint;
int main(void) {
Point point = {4,5};
pPoint point_ptr = &point;
printf("%d - %d\n",point.x,point_ptr->x);
pPoint second_point_ptr = malloc(sizeof(Point));
second_point_ptr->x = 5;
free(second_point_ptr);
}
The first declares an unnamed struct, and a type pStudentRecord that is a pointer to it. The second declares g_ppRecords to be a pointer to a pStudentRecord. In other words, a pointer to a pointer to a struct.
It's probably easier to think of the second as an "array of pointers". As such, g_ppRecords[0] may point to a pStudentRecord and g_ppRecords[1] to another one. (Which, in turn, point to a record struct.)
In order to add to it, you will need to know how it stores the pointers, that is, how one might tell how many pointers are stored in it. There either is a size somewhere, which for size N, means at least N * sizeof(pStudentRecord*) of memory is allocated, and g_ppRecords[0] through g_ppRecords[N-1] hold the N items. Or, it's NULL terminated, which for size N, means at least (N+1) * sizeof(pStudentRecord*) of memory is allocated and g_ppRecords[0] through g_ppRecords[N-1] hold the N items, and g_ppRecords[N] holds NULL, marking the end of the string.
After this, it should be straightforward to create or add to a g_ppRecords.
A struct is a compound data type, meaning that it's a variable which contains other variables. You're familiar with Objective C, so you might think of it as being a tiny bit like a 'data only' class; that is, a class with no methods. It's a way to store related information together that you can pass around as a single unit.
Typedef is a way for you to name your own data types as synonyms for the built-in types in C. It makes code more readable and allows the compiler to catch more errors (you're effectively teaching the compiler more about your program's intent.) The classic example is
typedef int BOOL;
(There's no built-in BOOL type in older ANSI C.)
This means you can now do things like:
BOOL state = 1;
and declare functions that take BOOL parameters, then have the compiler make sure you're passing BOOLs even though they're really just ints:
void flipSwitch(BOOL isOn); /* function declaration */
...
int value = 0;
BOOL boolValue = 1;
flipSwitch(value); /* Compiler will error here */
flipSwitch(boolValue); /* But this is OK */
So your typedef above is creating a synonym for a student record struct, so you can pass around student records without having to call them struct StudentRecord every time. It makes for cleaner and more readable code. Except that there's more to it here, in your example. What I've just described is:
typedef struct {
char * firstName;
char * lastName;
int id;
float mark;
} StudentRecord;
You can now do things like:
StudentRecord aStudent = { "Angus\n", "Young\n", 1, 4.0 };
or
void writeToParents(StudentRecord student) {
...
}
But you've got a * after the typedef. That's because you want to typedef a data type which holds a pointer to a StudentRecord, not typedef the StudentRecord itself. Eh? Read on...
You need this pointer to StudentRecord because if you want to pass StudentRecords around and be able to modify their member variables, you need to pass around pointers to them, not the variables themselves. typedefs are great for this because, again, the compiler can catch subtle errors. Above we made writeToParents which just reads the contents of the StudentRecord. Say we want to change their grade; we can't set up a function with a simple StudentRecord parameter because we can't change the members directly. So, we need a pointer:
void changeGrade(StudentRecord *student, float newGrade) {
student->mark = newGrade;
}
Easy to see that you might miss the *, so instead, typedef a pointer type for StudentRecord and the compiler will help:
typedef struct { /* as above */ } *PStudentRecord;
Now:
void changeGrade(PStudentRecord student, float newGrade) {
student->mark = newGrade;
}
It's more common to declare both at the same time:
typedef struct {
/* Members */
} StudentRecord, *PStudentRecord;
This gives you both the plain struct typedef and a pointer typedef too.
What's a pointer, then? A variable which holds the address in memory of another variable. Sounds simple; it is, on the face of it, but it gets very subtle and involved very quickly. Try this tutorial
This defines the name of a pointer to the structure but not a name for the structure itself.
Try changing to:
typedef struct
{
char* firstName;
char* lastName;
int id;
float mark;
} StudentRecord;
StudentRecord foo;
StudentRecord *pfoo = &foo;

Resources