How to access position of an array of struct using pointer - c

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

Related

How to use struct pointer to set char name?

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

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.

How to access the members of a struct within a struct via a double pointer?

As part of a school assignment, I am given a structure with a double pointer to another structure inside it. I will need to be able to access the members of the nested structure within a function, but am having no luck doing so.
Here is the code I have been given
#include<stdio.h>
#include <stdlib.h>
/*Given code, do not change */
typedef struct
{
char* ID;
char* PassWord;
}Account, *pAccount, **ppAccount;
typedef struct
{
unsigned int numAccounts;
ppAccount accounts;
}FleaBay,*pFleaBay;
void FleaBayInit(pFleaBay); /* Initialise the FleaBay instance */
int main(void)
{
FleaBay e;
FleaBayInit(&e); /* Call to the function */
return 0;
}
/* end of given code */
Here is my attempt:
void FleaBayInit(FleaBay *pFleaBay){ /* Initialise the FleaBay instance */
Account ac1 = {"test1", "test2"}, *pac1 = &ac1;
pFleaBay ->numAccounts = 0;
pFleaBay ->accounts = &pac1;
}
I'm having no trouble accessing the member within the non-nested struct, but I cannot figure out how to access the members of the nested Account structure. Thought that maybe I would need to create an Account object first, point to it, and assign the value of the pointer to the accounts member within pFleaBay, but when I test with printf("%s",pFleaBay->accounts);, I get some random characters.
In the structure
typedef struct
{
char* ID;
char* PassWord;
}Account, *pAccount, **ppAccount;
ppAccount is a pointer to a pointer, which is often used to represent a dynamic array of pointers.
In the second structure
typedef struct
{
unsigned int numAccounts;
ppAccount accounts;
}FleaBay,*pFleaBay;
you have the number of the accounts, which would be the number of the elements in the dynamic array. So, in your code you could access one of the accounts using the syntax pFleaBay->accounts[n]. This means that you would want to allocate an array of pointers in your function either using malloc or calloc.
pFleaBay->accounts = calloc(pFleaBay->numAccounts, sizeof(pAccount));
Then you can allocate each of the accounts.
In your FleaBayInit(), ac1 is a local variable, and pac1 is initialized as a pointer to ac1. As a local variable, ac1's lifetime is limited to one function call. After the function returns, ac1 no longer exists, and any pointer that points to it becomes invalid.
Moreover, FleaBay.accounts is an Account **, but you try to assign an Account * to it (pac1). Not only does that pointer become invalid when the function returns, it isn't even the correct type. This is actually odd; I don't see any reason why FleaBay.accounts should not be simply an Account *.
Edited to add:
On second thought, FleaBay.accounts could be an Account ** because it is meant to point to a dynamic array of Account *, as opposed to a dynamic array of Account. That would offer some advantages, particularly if Account objects must be independent of FleaBays.
In that case, the simplest way to initialize a FleaBay would probably be this:
void FleaBayInit(FleaBay *pFleaBay){ /* Initialise the FleaBay instance */
pFleaBay->numAccounts = 0;
pFleaBay->accounts = NULL;
}
Whether that is actually appropriate, however, depends on how you intend to implement other code that manipulates FleaBays -- especially code that adds or removes accounts.

Runtime initialization of structure member in C ( member name decided at run )

I'm wondering for a solution to the below problem. Please help.
Problem:
struct s{
int a;
int b;
}st;
I want a function to initialize the values at runtime. The problem is that I want to make it generic, so I want to pass the member name as input to the function and get it initialized.
fun_init(char* mem, int val)
{
// Find offset of the member variable in struct 'st'
// Assign the value
}
One straight solution is to use string comparision on the member name. But if I happen to add some extra variables at a later time, I'll have to modify the function, which I don't want.
Hope I was able to frame the ques clearly.
Thanks
C does not provide a way to find a symbol by name. See this thread for more information.
The simplest solution here is to use an associative array.
Read this thread if you need to mix value-types. (In your example, all value types are int, so you might not need this.)
void fun_init(int *storage, int val) {
*storage = val;
}
void something_else(void) {
struct s {
int a;
int b;
} st;
fun_init(&st.a, 42);
}
However, if you need to dynamically determine the key name, you are doing something wrong. If you need to store key/value pairs, perhaps you would be interested in the hashtable.
I'm guessing you want to initialize struct from either user input or persistency.
A solution involves creating an associative array as mentioned by #Domi.
The array is filled with key/value pairs such as (const char*, unsigned).
The key is the name of struct member and the value is the offset from the start of the struct.
Each struct will need to have a function that initializes the above array. You can get an offset to a member via the offsetof macro.
This will NOT work with structs that have bit fields (sub byte named members).

C lists - Accessing a member of a struct and printing it

I'm having some trouble with lists in C.
I made this struct:
typedef struct str {
char * str;
struct str * prox;
struct str * ant;
} cadena;
Then in the main I start the list with its first pointer to NULL.
cadena * lista = NULL;
Then I made a function where the user can add new elements to the lists (strings in the "str" member) and I manage the pointers to build the list. That seems to work OK. I hope.
But when I want to print a member of one node, it I'm trying to use something like this, and its not working:
void showdata (cadena *lista) {
int i=0;
while (lista.str[i] != '\0')
{
printf("%c\n",str[i]);
i++;
}
}
I'm getting these errors:
from line "while (lista.str[i] != '\0')"
.error: request for member ‘str’ in something not a structure or union
(why is it expecting a structure? I thought I'm accessing a member there)
from line "printf("%c\n",str[i]);"
.error: ‘str’ undeclared (first use in this function)
(isn't it declared with the struct?)
I'm surely doing something really wrong, but I cannot understand which is the right way to access a char member and print it.
Thank you in advance.
lista.str[i]
should be
lista->str[i]
anywhere you have a pointer to a struct you use -> not .
Try:
while (lista->str[i] != '\0')
printf("%c\n",lista->str[i++]);
It's a pointer notation problem. C can be confusing in this way.
lista.str[i]
doesn't work because C doesn't recognize the "." as moving to a field. This can be a problem for people like myself who were used to C# or other OOP languages, where you can use the "." to modify properties of an object, like
control.visibility = "False"
In C, structs are based on pointers, so you need to use the -> like Keith said. You're pointing to a location in memory, or the "location" in the struct where a certain field is. Think of it that way, and you shouldn't have too many problems.
C also allows you to use the "."... but only if you strongly type the reference. For you, that would mean going
(*lista).str[i]
so that your reference to the lista instance is seen as a pointer to the struct.
So, in review, either
lista->str[i]
or
(*lista).str[i]
should work.

Resources