Expression must be a modifiable lvalue (pointer to struct) - c

I've looked at similar questions but haven't really found an answer to my problem.
In my program, I have a function, sortdata, as follows:
void sortdata(Person *arr[], int noElements)
{
/* temporary pointer to Person data type to aid with swapping */
Person *tempptr = (Person *)malloc(sizeof(Person));
int i = 0;
/* loop I am working on to sort my data */
if (arr[i]->zip > arr[i + 1]->zip)
{
/* stores value in index i for array inside of temporary pointer */
tempptr->name = arr[i]->name;
}
}
I'm receiving the error described in the question at this line:
tempptr->name = arr[i]->name;
temp is not recognized as a modifiable lvalue. Why is this? I have this code in another function within my program:
while ((gets(teststring)) != NULL && i < 50)
{
/* dynamically allocates memory for each index of the array */
arr[i] = (Person*)malloc(sizeof(Person));
/* takes in data from user/ input file */
strcpy(arr[i]->name, teststring);
gets(arr[i]->address);
gets(arr[i]->citystate);
gets(arr[i]->zip);
printf("\n");
}
I haven't previously initialized arr[] (arr[] is an array of pointers to a structure passed from elsewhere in the program).
How do I make it so that I can store the values in arr[i] within tempptr?
Here is my structure definition in case it is needed:
/* structure defintion with typedef */
typedef struct person{
char name[50];
char address[50];
char citystate[30];
char zip[10];
}Person;
This program is for a class assignment so while I appreciate any efforts to help, I am only concerned with how to be able to store values in tempptr so I can perform swaps. Thank you.

You need to use:
strcpy(tempptr->name, arr[i]->name);
You can't assign a char[50] array, you have to copy to it instead.

You need use strcpy to modify char[].

Related

access to a member of a struct (pointer) with the use of double pointer

hey I am trying to create a program in which I am trying store elements from one array to another with the use of a pointer to pointer but the problem is that is caused undefined behavior I believe that the problem is that I do not pass the elements in members with a proper way
I know it is a vague way of doing this but It is in only for practising reasons
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct student{
char *name;
int *number;
}T;
int main(void) {
char array[10][100]={"araaaa","bbgt","gffkghgh"};
T arr[10][100];
T *p;
T **p1;
p=&arr[0][0];
p1=&p;
int i=0;
for(i = 0 ; i < 3 ; i++)
{ p=arr[i];
strcpy((*p1)->name,array[i]);
}
/*******print_elements*************/
for(i = 0 ; i < 3 ; i++)
{ p=arr[i];
printf("\n the elements are %s",(*p1)-> name);
}
return 0;
}
When you do this:
strcpy ((*p1)->name, array[i]);
(*p1)->name is an uninitialised pointer. What happens, therefore, is in the lap of the gods.
The easiest fix is to modify your student structure such that name is a buffer, rather than a pointer. At the same time, change number to an int, rather than a pointer to an int::
typedef struct student{
char name [100];
int number;
} T;
If you want to keep name as a pointer then you have to allocate some memory before you store your string in it. This should work:
(*p1)->name = strdup (array[i]);
Don't forget to free the memory when done.
T is made of of two pointers, this first one points to a string of characters in memory.
arr is a 2D array that is allocated to store a total of 1000 T structures.
arr[i] would reference a 1D array of T structures within arr
*p1 would essentially be arr[i], since dereferencing p1 gives you p, which was just set to arr[i]. So, that is not a pointer to a T structure, but to an array of T structures. Forcing the cast will likely give you a reference to the first T structure in that row, however.
->name This value is never set. You allocated an array, but "name" is a pointer to memory, not an array of characters, so '->name' is undefined.
I think you need to change arr to be a single dimension array. You aren't using 90% of it.
And, you need to initialize every T struct in that array. You can use malloc or strdup, and then remember to free them all. Or, set the struct to use an array instead.

why is pointer to struct behaving like an array of structs

I have the following code
typedef struct{
int fildes;
char key[MAX_KEYLEN];
} item_t;
static int nitems;
static item_t *items;
FILE *filelist;
int capacity = 16;
char *path, *ptr;
if( NULL == (filelist = fopen(filename, "r"))){
fprintf(stderr, "Unable to open file in content_init.\n");
exit(EXIT_FAILURE);
}
items = (item_t*) malloc(capacity * sizeof(item_t));
nitems = 0;
while(fgets(items[nitems].key, MAX_KEYLEN, filelist)){
/*Taking out EOL character*/
items[nitems].key[strlen(items[nitems].key)-1] = '\0';
// and there's more code below which is not relevant to the question
In the above code,
Item_t is a struct defined as below
typedef struct{
int fildes;
char key[MAX_KEYLEN];
} item_t;
Then, items is defined as
static item_t *items;
items is initialized using the following code
items = (item_t*) malloc(capacity * sizeof(item_t));
Then, the following is done with items
fgets(items[nitems].key, MAX_KEYLEN, filelist)
items is supposed to be a struct. How did it become an array? I said array because, items[nitems] is being done
which made me feel that items is an array of item_t structs
Pointers and arrays can (for the most part) be used interchangeably.
array[i] is just syntatic sugar for *(array+i).
Answer to your question "why is pointer to struct behaving like an array of structs ?"
(The answer below is applicable to any data type regardless of it being structure or some other data type)
When you initialize an array (of any data type) with 'N' elements you are simply asking for memory of size equal to (N * sizeof(data-type)) whose base address is the address of 1st element in the array (i.e. element at index zero).
So when you access any element in an array what you are effectively doing is de-referencing a value stored at particular address in memory.
Example:
#define N 3
int32_t array[N] = {11, 22, 33};
Suppose now I want to print the last element in the array (i.e. element at index 2).
Since I know the base address of array, I can access the elements in the array in following ways:
printf("%d \n", array[2]);
/***** OR *****/
printf("%d \n", *(array + 2));
NOTE:
In second printf()from machine's perspective what is happening is this:
*( base-address + index * sizeof(data-type) )
since from machine's perspective the concept of data-type, array, etc doesn't exist.
(Simplified explanation without touching the assembly level code)
NOTE:
array[i] is just a syntactic-sugar for *(array + i)

Allocating memory for array of structs

I've a struct like the one who follows:
typedef struct author
{
char letter;
char *name[200];
int counter;
} Aut, *i_aut;
It consists of a char, and array of "Strings" and int. My goal is to allocate space in memory for an array of 30 of this kind of structs, therefore I tried something like the following:
i_aut lista_autores=calloc(30,sizeof(Aut));
However, it always returns "segmentation fault". I tried to initialize one at a time too, but with the same result. My question is, how do I allocate memory of this kind and how can I access it later?
Thank you in advance, and sorry for any typo.
the struct member name is an array of 200 pointers.
You may want to assign the result of malloc to elements of the array.
struct author *i_aut;
i_aut = malloc(sizeof *i_aut);
if (i_aut) {
for (size_t k = 0; k < 200; k++) {
i_aut->name[k] = malloc(30);
if (!i_aut->name[k]) /* error */;
/* DONT FORGET TO FREE EACH NAME LATER ON */
}
free(i_aut);
}
try using this
struct author **i_aut;
i_aut=(struct author **)malloc(30*sizeof(struct author*));
for(i=0;i<30;i++)
i_aut[i]=(struct *)malloc(sizeof(struct author));
after this you need not allocate space for name[] seperately.
you have array of 30 elements of type struct author*
and you can access all three type using
i_aut[i]->letter;
i_aut[i]->name[j];
i_aut[i]->counter;
here i<30

Changing values in elements of an array of structs

I am working on an assignment and ran into challenging problem. As far as I'm concerned and from what I've learnt the code that follows should be correct however it does not work. Basically what I am trying to is copy a string value into the variable member of a structure the is part of an array passed into a method as a pointer. What am I missing?
typedef struct
{
char * name; //variable in struct I am trying to access
} Struct;
void foo(Struct * arr) //array of Structs passed into function as a pointer
{
int i = 0;
while(i++ < 2)
{
arr[i].name = malloc(sizeof(char *)); //assigning memory to variable in each Struct
arr[i].name = strdup("name"); //copying "name" to variable in each Struct
printf("C - %s\n", arr[i].name); //printing out name variable in each Struct
}
}
main()
{
Struct * arr; //defining pointer
arr = calloc(2, sizeof(Struct)); //allocating memory so pointer can hold 2 Structs
foo(arr); //calling function foo passing pointer into function
return 0;
}
This code compiles and runs however it does not do what it is designed to do. Forgive me if it is something trivial. I am new to the language C
Two issues:
while(i++ < 2) This line changes the value of i as soon as it checks it, so your loop body will not be the same as it was checked.
arr[i].name = strdup("name"); overwrites the value of the .name pointer, causing a memory leak of the memory you malloc()'ed earlier.
Extending on 2 pointed out correctly already,
arr[i].name = strdup("name");
Even if you use following instead of above,
strcpy(array[i].name, "name");
you haven't allocated enough bytes to store the string i.e. this is wrong
arr[i].name = malloc(sizeof(char *));
// even if pointer is 8 byte here, concept isn't right
Should be something like
arr[i].name = malloc(strlen("name")+1);
// or MAX_SIZE where it is greater than the possible "name".
Or better yet, remove the malloc at all, strdup takes care of allocation itself
This is not answering your question directly, but addresses an issue to big to put into a comment...
Additional issue: You probably did not intend to allocate only a (char *) worth of memory to a variable intended to hold at least "name". Change;
arr[i].name = malloc(sizeof(char *));
to:
arr[i].name = malloc(sizeof(char)*strlen("name")+1); //+1 for '\0'
or better yet, use char *name="name";, then:
arr[i].name = malloc(sizeof(char)*strlen(name)+1);
Even more general (and better):
char *name;
name = malloc(strlen(someInputString)+1);
//do stuff with name...
free(name);
Now, you can allocate name to any length needed based on the length of someInputString.
[EDIT]
Etienz, I wanted to address one more thing, alluded to by #H2CO3 above, but not really explained, that I think might be useful to you:
Regarding your desire to have room for two structs, because you typedef'd your struct, you can simply do something like this: (but I am going to change the name you used from Struct to NAME :) The whole point being that when a struct is created as an array, you do not need to use calloc or malloc to create space for them, it is done as shown below...
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct{
char *name;
}NAME;
//use new variable type NAME to create global variables:
NAME n[2], *pN; //2 copies AND pointer created here
//prototype func
int func(NAME *a);
int main()
{
pN = &n[0]; //pointer initialized here
func(pN); //pointer used here (no malloc or calloc)
printf("name1 is %s\nname 2 is %s", pN[0].name, pN[1].name);
return 0;
}
int func(NAME *a)
{
char namme1[]="andrew";
char namme2[]="billebong";
//You DO have to allocate the members though
a[0].name = malloc(strlen(namme1)+1);
a[1].name = malloc(strlen(namme2)+1);
strcpy(a[0].name, namme1);
strcpy(a[1].name, namme2);
return 0;
}

How can I set a certain value to a member of a struct within multiple functions?

i am a beginner so please cut me some slack on this one. So I have two functions and a struct in a header file I am currently working with.
This is the struct:
typedef struct ArrayList
{
// We will store an array of strings (i.e., an array of char arrays)
char **array;
// Size of list (i.e., number of elements that have been added to the array)
int size;
// Length of the array (i.e., the array's current maximum capacity)
int capacity;
} ArrayList;
Here is the first function, which creates and dynamically allocates memory for an array of strings. Capacity is the length of the internal array and size is the current size (how many strings are in the array which is essentially 0.)
ArrayList *createArrayList(int length){
char **array = NULL;
ArrayList *n;
int size = 0;
if (length > DEFAULT_INIT_LEN)
{
array = malloc(sizeof(int) * length);
n->capacity = length;
}
else
{
array = malloc(sizeof(int) * DEFAULT_INIT_LEN);
n->capacity = DEFAULT_INIT_LEN;
}
if (array == NULL)
panic("ERROR: out of memory in Mylist!\n");
n->size = size;
printf("-> Created new ArrayList of size %d\n", n->capacity);
return *array;
When I try to implement a pointer to the capacity member of the ArrayList struct inside another function within the same file, it is uninitialized instead of set as the value from the previous function. I.e. in createArrayList, n->capacity is equal to 10, but when used in printArrayList it is uninitialized and a random number appears such as 122843753.:
void printArrayList(ArrayList *list)
{
printf("\n%d", list->capacity);
return NULL;
}
My question is, how can I make it so all these functions "share" the same value when referring to the struct members. I.E. the first function prints -> Created new ArrayList of size 10, and the second function prints 10 as well. Also, I have to do this without changing the struct function itself. Sorry if this is a poorly worded question, but I can further clarify if it is confusing. Thanks in advance!
I see a couple of major issues with this code, in createArrayList you are returning array which is a char ** but you should be returning an ArrayList * which is what n is. So it looks like you want to assign array to n->array. The next issue is that n is an ArrayList * but you do not allocate memory for n.

Resources