I have a struct defined as following:
typedef char *element_t;
typedef
struct {
element_t *array; /* start of the array */
int capacity; /* number of elements the array */
int length; /* used portion of array, 0..capacity */
} list;
I am trying to access the array that *array points to and assign it a char value and print it.
I'm a bit rusty with C but this is how i'm trying to do it:
list.array[0] = "a";
printf("%s\n", list.array[0]);
This makes my program crash. Any fixes?
EDIT: I should also mention that I have done the following initialisations too:
element_t* array[LMAX];
list.array= *differentArray;
Seems to work for me:
typedef char *element_t;
typedef
struct {
element_t *array; /* start of the array */
int capacity; /* number of elements the array */
int length; /* used portion of array, 0..capacity */
} list;
int main(int argc, char **argv)
{
element_t array[2] = {"foo", "bar"};
list list;
list.array = array;
list.capacity = sizeof(array)/sizeof(array[0]);
list.length = 1;
printf("%s\n", list.array[0]);
return 0;
}
You are most likely forgetting to assign list.array to point to a valid array.
typedef char *element_t; Don't hide pointers behind typedefs, this is bad practice as it makes the code unreadable. element_t *array will be the same as char** array. Is this actually what you want?
list.array[0] = "a"; suggests that you intended "array" to be an array of pointers? Where do you allocate the actual array? Where do you initialize the struct? list.array[0] is pointing into la-la-land rather than at allocated memory, as far as I can tell from the posted code.
Also, the array of pointers need to be of type const char*, since you are pointing at string literals.
Change your initialization to:
element_t differentArray[LMAX];
list.array = &differentArray[0];
The rest of your code should work as is after this change. You don't need any further allocations as long as you only keep putting literals like "a" into it.
Related
I allocated some data in a dynamic array of a struct. Can I iterate that struct * without knowing it's size somehow?
Would this work?
int main() {
struct *foo = NULL;
//struct filling
iterate_foo(foo);
}
void iterate_foo(struct *foo) {
int i=0;
while (foo[i] != NULL) { // Would this work?
//something
}
}
The only way that can work is if you have a sentinel value in the array that indicates the end. Strings in C work that way.
For instance, if you invoke strcpy(a, b), then characters from b will be copied to a until and including the value zero. If there's no zero terminator within the b array, or if a is not big enough to hold all the characters, the function call leads to undefined behavior.
If you don't want to use a sentinel value, you have the option of passing the size as a separate parameter. Another way is to wrap things in a container struct, like this:
struct container {
struct mystruct *data;
size_t size;
}
Furthermore, struct *foo = NULL; is wrong. It has to be something like struct mystruct *foo = NULL;
But if you have this code:
void foo(T *ptr) {
// Do something
}
int main(void) {
T *a = malloc(N * sizeof *a);
T b[N];
foo(a);
foo(b);
}
Then it's completely impossible for foo to figure out N in a portable way. In some cases, believe that the implementation of malloc stores the size right before the data. But don't try to exploit that. It will only cause severe head ache.
i have the following structure:
typedef struct Course {
int course_id;
char* course_name;
int prior_course_id;
StudentTree* students;
} Course;
and the following function i need to implement:
void createReport(FILE* courses[], int numOfCourses, FILE* studentFile, char* reportFileName
as you can see i get an array of FILE*, each cell contains different file pointer.
my intention is to create an array that each cell is Course* type, and initialize each cell with a Course struct containing the data read from the courses files.
what is the correct way to declare it inside the function?
do i need to dynamically allocate memory for it, or it can be done in compilation?
i've tried
Course* course_array[numOfCourses] = {NULL};
Course* course_array[numOfCourses] = NULL;
but it won't compile.
thanks for your help
You declare an array of structs the same way you declare an array of ints or FILE *s:
Type variableName[numberOfElements];
Before C99 (and barring compiler specific extensions), creating an array with a variable number of elements on the stack wasn't supported. So make sure that you are targeting the correct standard. In your case, assuming C99 support, the following should work:
Course *course_array[numOfCourses];
Because you intend to initialize each of the elements in the array, there is no need to zero them out.
You would then access the elements like this:
course_array[0] = malloc(sizeof(Course))
course_array[0]->course_id = 2;
/* etc. */
Now if you can't assume C99 support, things get a bit more tricky but not much:
Course *course_array = malloc(sizeof(Course *) * numOfCourses);
After that you can access course_array with the same array notation:
course_array[0] = malloc(sizeof(Course))
course_array[0]->course_id = 42;
/* etc. */
Once you're doing with the array, you'll need to make sure that you free any of the memory that you allocated:
for (i = 0; i < numOfCourses; i++) {
free(course_array[i]);
}
/* If you malloc'd course_array, then you need this too */
free(course_array);
Course* course_array[numOfCourses] = {NULL};
This is good, but it creates array of Course *. So you need to allocate memory for each pointer in course_array before accessing it.
Something like
course_array[0] = malloc(sizeof(Course));
course_array[0]->course_id = someid;
When you define the array in the first place, you shouldn't need to allocate memory. You're defining the array on the stack, and the elements of the array are just pointers.
I think what you should do is first define the array, and then initialize each element with a malloc call. For example:
Course* course_array[numOfCourses];
for(int i = 0; i < numOfCourses, i++) {
course_array[i] = (Course*)malloc(sizeof(Course));
My favorite way:
typedef struct {
int a;
char b;
float c;
}DATA;
//then use typdef'ed DATA to create array (and a pointer to same)
DATA data[10], *pData;
//then, in function, you can initialize the pointer to first element of array this way:
int main(void)
{
pData = &data[0];
return 0;
}
Your example code would look like this:
typedef struct {
int course_id;
char* course_name;
int prior_course_id;
StudentTree* students;
} COURSE;
//then in function:
COURSE course[numOfCourses]
I have this array filled up with characters in my maze.c file:
char normalMazeArray[6][12]; dynamically filled as mazeArray[row][column]
Now I want to pass what the array to the mazeArray that is located in my struct (maze.h)
my struct is called:
typedef struct {
char mazeArray;
} maze_t;
I have tried copying it as follows:
maze_t* maze;
char normalMazeArray[6][12]; // filled with info
typedef struct {
char mazeArray;
} maze_t;
maze->mazeArray = normalMazeArray;
however it is not working,
anyone who could help me?
The thing what you're trying to do is not exactly possible. There are two slightly different solutions you can use, though.
normalMazeArray is of type char [6][12] - it's an array. You can either copy its contents to the same type of array using memcpy():
typedef struct {
char mazeArray[6][12];
} maze_t;
memcpy(maze->mazeArray, normalMazeArray, sizeof(normalMazeArray));
or if your normalMazeArray persists throughout the lifetime of the program, you can assign a pointer to it in the structure:
typedef struct {
char (*mazeArray)[12];
} maze_t;
maze->mazeArray = normalMazeArray;
Wait, how??
First of all, maze is a pointer, so you can't have maze.mazeArray. Second of all, maze->mazeArray is of type char, while mazeArray is of type char**. No can do.
You should write a function which allocates char** array, and then strdups strings from mazeArray. Or, if you want ownership transfer, and not just copy, you could go like this:
typedef struct {
char** mazeArray;
} maze_t;
maze_t maze;
maze.mazeArray = mazeArray;
I was writing a structure from a book, and then see how it does initialization.
I don't get it, how he does that.
struct node
{
char target[50];
char stack[50];
char *s,*t;
int top;
}
Initialization function:
void init
{
p->top = -1;
strcpy(p->target,"");
strcpy(p->stack,"");
p-t = p->target;
p->s="";
}
So I want know how he is using strcpy to initialize an array or char.
He is not doing it. The statement strcpy(p->target,""); does not initialize the 50 positions of the array. It just puts a 0 in the first position. (See this reference.)
Have a look at the example in this: http://www.cplusplus.com/reference/clibrary/cstring/strcpy/
I have an array inside a struct like so:
typedef struct mystruct{
const char *myarr[30];
} mystruct;
I need to grow this array later in the program to 60 elements by creating a new array, duplicating the content, and then changing myarr to point to the new array.
I have tried the following:
const char newtable[n];
s->*myarr = newtable;
But gcc complains:
error: incompatible types in assignment
Any ideas as to the right way to accomplish this?
Assuming that you indeed want your array to contain char *s, not chars, you should define your structure like this:
typedef struct {
const char **myarr;
/* I assume you actually have more members here */
} mystruct;
and initialize it like this:
mystruct s;
s.myarr = (const char **) malloc(30 * sizeof(const char *));
if (!s.myarr) { /* handle out-of-memory condition somehow */ }
Then you can later extend it with realloc():
const char **tmp = (const char **) realloc(s.myarr, 60 * sizeof(const char *));
if (tmp) s.myarr = tmp;
else { /* handle out-of-memory condition somehow */ }
(Note that, if realloc() returns NULL, the original value of s.myarr will still be valid.)
Don't allocate it as an array inside the struct. Just leave it as a pointer:
const char *myarr;
Then this'll work:
const char newtable[n];
s->myarr = newtable;
You can still use it like an array, e.g.
char c = s->myarr[20];
You declare an array of pointer, not a pointer point to a array.
typedef struct { // no need mystruct here
const char *myarr;
} mystruct;
const char newtable[60];
s->myarr = newtable;
But const char *myarr is different from const char (*myarr)[30], and you didn't actually create a new array by const char newtable[60];, you maybe need malloc instead.
So growing memory region at runtime should really involve dynamic memory allocation. I'd suggest something like this:
typedef mystruct {
char *data;
} mystruct;
[...]
char *ptr = realloc(s->data, 60); // that will copy your previous data over
if (ptr != NULL) {
s->data = ptr;
}
I don't think it has to be much more complicated than that really... especially you should avoid declaring a 60 elements array statically in the .data/.rodata section...
Hope it helps,