(C) Array of Structs and moving data to it - c

I am looking to do the following:
struct def:
struct mystruct {
char cArr[500];
}
global:
struct mystruct **ptr;
int count = 0;
in main:
ptr = malloc(20*sizeof(struct test *));
for (int i = 0; i != 20 ; i++) {
ptr[i] = malloc(sizeof(struct test));
}
in some function that is called 20 times:
char burp[500];
//put whatever I want in burp;
ptr[count]->cArr = burp //is this right? Or do I have to memcpy to it, and if so how?
count++;
So at the end I will sequentially fill in the array of mystruct with the chars that I want. I tried doing this with char** but had no luck; I am now wrapping it in a struct as it helps me visualize what is going on.
So I want a global array of char[500], where everytime a function is called it puts that char[500] into the index (that is either passed into the function or also global).
Any advice is appreciated; Ofc I will need to free at the end every index of the array as well.
Thanks!
edit:
so would something like:
memcpy(ptr[count]->cArr, burp, 500);
work then?

#include <stdio.h>
#include <stdlib.h>
struct mystruct
{
char *cArr;
// U were trying to assign array using = operator
// Remember its not like in STL where u can perform deep copy of a vector
};
struct mystruct **ptr;
int count = 0;
int main()
{ int i;
ptr = malloc(20*sizeof(struct mystruct *));
for (i = 0; i != 20 ; i++)
{
ptr[i] = malloc(sizeof(struct mystruct));
}
char burp[500]="No this is not correct boy.";
//put whatever I want in burp;
(*ptr+count)->cArr = burp ;
// Assigning pointer to a pointer , OK. Remember pointer != Array.
//is this right? Or do I have to memcpy to it, and if so how?
//count++; // Has no use in your code, enclose in a loop to then use it.
printf("%s\n",(*ptr + count)->cArr); // This works , I think.
}
For arrays i.e. char cArr[500],
If you want to use memcpy u can use it :
memcpy((*ptr+count)->cArr, burp, 500);
Strcpy also works :
strcpy((*ptr+count)->cArr, burp);
Two points are important :
Assignment of pointers to pointers is allowed, but deep copy of array is not.
**ptr is a double pointer.So, (*ptr + count ) or ptr[count] is a pointer to struct.
2nd point is not required for your answer.

You can use strcpy to copy the string.
strcpy(ptr[count]->cArr,burp);
But strcpy terminates on null character. So, make sure your character string(i.e burp) is properly initialized.

I guess all that you wanted to do is to store some text in your structure for later usage.
struct mystruct {
char carr[500];
}
struct mystruct *ptr = NULL;
int count = 0;
main{
...
ptr = malloc( 20 * sizeof(struct test) );
//Function call func()
...
//After performing work
free( ptr );
}
//Some function
func() {
char burp[500];
// burp has some data fed
memcpy( ptr[count]->carr, burp, 500 );
}

Related

Allocating memory to a struct member pointer in C

I have a structure with a member that I need to pass to a function by reference. In that function, I'd like to allocate memory & assign a value. I'm having issues somewhere along the line - it seems that after the code returns from allocateMemory, the memory that I had allocated & the values that I assigned go out of scope (this may not be exactly what is happening, but it appears to be the case).
#include <stdio.h>
#include <stdlib.h>
typedef struct myStruct_t
{
char *myString;
} myStruct;
void allocateMemory(void *str);
int main(void) {
myStruct tmp = {
.myString = NULL
};
myStruct *p = &tmp;
allocateMemory(p->myString);
//allocateMemory(&(p->myString)); //also tried this
printf("%s", p->myString);
return 0;
}
void allocateMemory(void *str)
{
str = malloc(8);
((char *)str)[0] = 'a';
((char *)str)[1] = 0;
}
If I print the value of str inside of allocateMemory, the 'a' is successfully printed, but if I attempt to print p->myString in main, my string is empty.
Can anyone tell me what I'm doing wrong?
You need to pass address of the structure member and then you can change (aka allocate memory) to it. In your version of the function, you are not taking a pointer not reference of a pointer, so you can change the content of memory referenced by the pointer but not the pointer itself.
So change your function to
void allocateMemory(char **ret_str)
{
char *str = malloc(8);
str[0] = 'a';
str[1] = 0;
*ret_str = str;
}
And then call it as
allocateMemory(&p->myString)
An alternative way of writing the same function Rohan did, eliminating the need to define any new variables:
void allocateMemory(char **str, size_t size) {
*str = malloc(size);
(*str)[0] = 'a';
(*str)[1] = '\0';
}
Note that I pass a size parameter to justify using malloc() in the first place.

C malloc array of structs of strings

I'm trying to create an array of structs (of arrays) and am a bit unsure of the malloc required. First I define my struct,
typedef struct {
char *str1, *str2, *str3, *str4;
} player;
Then in main I need to initialize the structure, and malloc the strings inside of it,
player1 player;
player1.str1 = malloc(100);
// and the rest
But this is just for one structure. How do I malloc an array of these structures? Do I need to have a for loop and create N instances of the struct?
I'm guessing there's a line that's something like
playerArray* = malloc(N * sizeof(player))
The end goal is to have something I can access using, say,
printf("%s\n", playerArray[i].str1)
After I've read stuff into it. Thanks.
Yes, you need to loop and allocate the strings for each instance of the struct. I suggest you create a function that looks something like this:
#define PLAYER_STR_LENGTH 100
typedef struct {
char* str1, str2, str3;
// ...
} player;
player* create_player() {
player* p = malloc(sizeof(player));
if (p == NULL) {
// out of memory, exit
}
p->str1 = malloc(PLAYER_STR_LENGTH);
if (p->str1 == NULL) {
// out of memory, exit
}
// allocate more stuff...
return p;
}
It is also a good idea to make a matching function free_player to clean up afterwards. You could also pass parameters to the create_player() function if you want to set values at the time of allocation.
To make an array of players, simply create an array of player pointers and then loop over it and allocate each player struct like so:
player** players = malloc(N * sizeof(player*));
for(int n = 0; n < N; n++)
players[n] = create_player();

initialize the struct pointer

typedef struct
{
char *s;
char d;
}EXE;
EXE *p;
For the above struct how do I initialize the structure with pointer? I know for a non-pointer we do EXE a[] = { {"abc",1}, {"def",2} }; . Similarly Is it possible with a pointer after allocating the memory? Say like p[] = { {"abc",1},.. so on} . Basically I want to initialize dynamically. Thanks.
We can initialise the structure with pointer as below
example:
int i;
char e[5]="abcd";
EXE *p=malloc(sizeof(*p));
for(i = 0;i < 5;i++)
*(p+i)=(EXE){e,i+48};
First you need to allocate some memory for that char * and after that use strcpy library function to copy data for structure element.
p->s = strcpy(s,str); //where str source, from where you need to copy the data
I hope this will help. Though I can give you full code for that, But I want you to try.
You can use this
Dynamically allocate C struct?
and it is a duplicate question.
You have to understand how do allocated pointer works:
Suppose you've allocated memory for three structs Ptr = malloc(3*sizeof(EXE)).
Then when you add 1 to Ptr, it comes to the next struct. You have a block of memory divided by 3 (3 smaller blocks of memory for each struct).
So, need to access to the elements of the 1st struct and then move the pointer to the next one.
Here you can understand how it works:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
char *s;
char d;
} EXE;
int main()
{
int i;
EXE *Ptr;
Ptr = malloc(3*sizeof(EXE)); // dymnamically allocating the
// memory for three structures
Ptr->s = "ABC";
Ptr->d = 'a';
//2nd
Ptr++; // moving to the 2nd structure
Ptr->s = "DEF";
Ptr->d = 'd';
//3rd
Ptr++; // moving to the 3rd structure
Ptr->s = "XYZ";
Ptr->d = 'x';
//reset the pointer `Ptr`
Ptr -= 2; // going to the 1st structure
//printing the 1st, the 2nd and the 3rd structs
for (i = 0; i < 3; i++) {
printf("%s\n", Ptr->s);
printf("%c\n\n", Ptr->d);
Ptr++;
}
return 0;
}
Notice:
- If you have a variable of a struct use . opereator to access to the elements.
- If you have a pointer to a struct use -> operator to access to the elements.
#include <stdio.h>
#include <stdlib.h>
struct EXE {
int a;
};
int main(){
struct EXE variable;
struct EXE *pointer;
pointer = malloc(sizeof(struct EXE)); // allocating mamory dynamically
// and making pointer to point to this
// dynamically allocated block of memory
// like here
variable.a = 100;
pointer->a = 100;
printf("%d\n%d\n", variable.a, pointer->a);
return 0;
}

C - split/store string of X length into an array of structs

I'm trying to split a string every X amount of characters, and then store each line in an array of structs. However, I'm wondering what would be a short and efficient way of doing it. I thought that maybe I could use sscanf, but not very sure how to. Any help will be appreciated. So far I have:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct st {char *str;};
int main ()
{
struct st **mystruct;
char tmp[] = "For configuration options (arch/xxx/config.in, and all the Config.in files),somewhat different indentation is used.";
size_t max = 20, j = 0; // max length of string
size_t alloc = strlen(tmp)/max + 1;
mystruct = malloc(alloc * sizeof *mystruct);
for (j = 0; j < alloc; j++)
mystruct[j] = malloc(sizeof *mystruct[j]);
const char *ptr = tmp;
char field [ max ];
int n;
while (*ptr != '\0') {
int line = sscanf(ptr, "%s", field, &n); // not sure how to use max in here
mystruct[j]->str = field;
field[0]='\0';
if (line == 1)
ptr += n;
if ( n != max )
break;
++ptr;
++j;
}
return 0;
}
So when I iterate over my struct, I can get something like:
For configuration op
tions (arch/xxx/conf
ig.in, and all the C
onfig.in files),some
what different inden
tation is used.
You could use strncpy.
FYI:
char field [ max ];
while (...) {
mystruct[j]->str = field;
Two problems with this: (1) every struct in your array is going to end up pointing at the same string, which will have the value of the last thing you scanned, (2) they are pointing to a variable on the stack, so when this function returns they will be trashed. That doesn't manifest itself visibly here (e.g. your program doesn't explode) because the function happens to be 'main', but if you moved this to a separate routine and called it to parse a string, you'd get back garbage.
mystruct doesn't need to be pointer to pointer. For a 1D array, just allocate a block N * sizeof *myarray for N elements.
A common C idiom when dealing with structs is to use typedef so you don't have to type struct foo all the time. For instance:
typedef struct {
int x, y;
} point;
Now instead of typing struct point pt you can just say point pt.
If your string is not going to change after you split it up, I'd recommend using a struct like this:
struct st {
char *begin;
char *end;
};
or the alternative:
struct st {
char *s;
size_t len;
};
Then instead of creating all those new strings, just mark where each one begins and ends in your struct. Keep the original string in memory.
One option is to do it character-by-character.
Calculate the number of lines as you are currently doing.
Allocate memory = (strlen(tmp) + number_of_lines) * sizeof(char)
Walk through your input string, copying characters from the input to the newly allocated memory. Every 20th character, insert a null byte to delimit that string. Save a pointer to the beginning of each line in your array of structs.
Its easy enough?
#define SMAX 20
typedef struct {char str[SMAX+1];} ST;
int main()
{
ST st[SMAX]={0};
char *tmp = "For configuration options (arch/xxx/config.in, and all the Config.in files),somewhat different indentation is used.";
int i=0,j;
for( ; (st[i++]=*(ST*)tmp).str[SMAX]=0 , strlen(tmp)>=SMAX; tmp+=SMAX );
for( j=0;j<i;++j )
puts(st[j].str);
return 0;
}
You may use (non C standard but GNU) function strndup().
#define _GNU_SOURCE
#include <string.h>
struct st {char *str;};
int main ()
{
struct st *mystruct; /* i wonder if there's need for double indirection... */
char tmp[] = "For configuration options (arch/xxx/config.in, and all the Config.in files),somewhat different indentation is used.";
size_t max = 20, j = 0; // max length of string
size_t alloc = (strlen(tmp) + max - 1)/max; /* correct round up */
mystruct = malloc(alloc * sizeof mystruct);
if(!mystruct) return 1; /* never forget testing if allocation failed! */
for(j = 0; j<alloc; j++)
{
mystruct[j].str = strndup(tmp+alloc*max, max);
}
}

Typedef and complex declaration in C

Related to this question.
What is wrong with the following code?
typedef char (*p)[20] ptr;
ptr myFunction () {
char sub_str[10][20];
return sub_str;
}
int main () {
ptr str;
str = myFunction();
}
Syntactically:
Change
typedef char (*p)[20] ptr;
To
typedef char (*ptr)[20];
To understand the syntax of typedef-declarations like this. Imagine you want to rename type T to type U. Declare a variable of type T named U and prefix the declaration with 'typedef'. That's all.
Semantically:
See my and other answers to your linked question. This is still undefined behavior
You're returning a pointer to memory that will not exist anymore when myFunction() returns.
The main problem is that substr is local to myFunction, and once myFunction exits it no longer exists, so the pointer you return will no longer be valid.
Secondly, you are not using typedef correctly. The proper syntax would be
typedef char (*ptr)[20];
Syntactically,typedef basically acts like a storage class specifier similar to static or extern (although the semantics are different). Basically, you figure out the declaration for an object
char (*ptr)[20]; // ptr is a pointer to a 20-element array of char
and then add the typedef to it:
typedef char (*ptr)[20];
Somehow myFunction needs to allocate memory in such a way that it isn't destroyed as soon as the function exits. Here's one option:
typedef char (*ptr)[20];
ptr myFunction(size_t count)
{
/**
* Dynamically allocate a block of N 20-element arrays of char
*/
ptr p = malloc(sizeof *ptr * count);
return p;
}
int main(void)
{
ptr str = myFunction(10);
size_t i, j;
for (i = 0; i < 10; i++)
for (j = 0; j < 20; j++)
str[i][j] = ...;
...
free(str);
return 0;
}

Resources