Strings dynamic allocation in C - c

I'm working with C. Can you tell me if this is the right way to allocate memory for a struct which contains a string?
struct _TipoLista {
char info[10];
struct _TipoLista *next;
};
typedef struct _TipoLista *TipoLista;
...
TipoLista el;
el = malloc(sizeof(TipoLista));
If a try to create a list in this way, I always get errors when I try to insert the 2nd element while. However, if I change "info" from char[10] to an int my code always works.

el = malloc(sizeof(*el));
or
el = malloc(sizeof(struct _TipoLista));
or initializing while declaring the struct
struct _TipoLista {
char info[10];
struct _TipoLista *next;
}obj1;
In the first two cases it's dynamic memory allocation 3rd is static memory allocation

el = malloc(sizeof(*el));
TipoLista has size of a pointer so that's not what you really want.

You should try the following
el = malloc(sizeof(struct _TipoLista));
Or define a typedef for this structure.

You are trying to do a typedef i.e., an alias for the strucuture. Typedef in turn means that "from this point onwards *struct _TipoLista* will be called as *TipoLista "
If you want to have a linked list of type "struct _TipoLista", then this could help.
struct _TipoLista {
char info[10];
struct _TipoLista *next;
};
typedef struct _TipoLista TipoLista;
int main()
{
TipoLista *Tptr = malloc(sizeof(TipoLista) );
/** Rest is history */
}

Hope this can be useful:
typedef struct {
char info[10];
struct _TipoLista *next;
} TipoLista;
TipoLista* construct_lista()
{
TipoLista* ret = malloc(sizeof(TipoLista));
ret->next = NULL;
return ret;
}
void destruct_lista(TipoLista* lista)
{
TipoLista* next;
while (lista != NULL)
{
next = lista->next;
free(lista);
lista=next;
}
}
void insert_into_list(TipoLista* lista, char* element)
{
while (lista->next != NULL)
lista = lista->next;
lista->next = construct_lista();
strcpy(lista->next->info, element);
}

Related

Void * that saves different structs

typedef struct s_list
{
void *content;
struct s_list *next;
} t_list;
typedef struct s_env
{
char *key;
char *val;
struct s_env *next;
} t_env;
typedef struct s_heredoc
{
char *term;
char *delimiter;
char *heredoc;
} t_heredoc;
typedef struct s_cmd
{
char *cmd;
char *path;
int istream;
int ostream;
} t_cmd;
typedef struct s_table{
char **paths;
char **reserved;
char *cmdline;
t_list *cmds;
} t_table;
I have a general struct t_table which have a pointer to t_list struct called cmds.
How can i save different structs for example t_env, t_heredoc, t_cmd in void * content; property of t_list struct. How should I cast the void * content to another type (t_env, t_cmd, t_heredoc, etc)
void lexical_analyze(char *cmdline, t_table **table)
{
cmdline = openquotes(cmdline);
cmdline = find_replace(cmdline, (*table)->env);
(*table)->cmds = malloc(sizeof(t_list));
}
After this point i can’t understand how to cast and how to allocate a memory for the other structs for example t_cmd struct
You can assign a pointer to any struct to your context member. But if you want to use that struct later, you will need to recover the original pointer type. That means you must store extra information about type of your content in your struct:
typedef enum {
CT_Env,
CT_Cmd,
CT_HereDoc
} t_context_type;
typedef struct s_list
{
void *content;
t_context_type type;
struct s_list *next;
} t_list;
t_list *add_Env(t_env *env)
{
t_list *list = malloc(sizeof *list);
... Do the list handling...
list->context = env;
list->type = CT_Env;
return list;
}
Then, when you want to access the nodes of your list you can cast to correct type:
void handle_node(t_list *list)
{
switch (list->type)
{
case CT_Env:
{
t_env *env = list->context;
// Access members of t_enf via env pointer
}
break;
case CT_Cmd: // TODO handle t_cmd type
break;
case CT_HereDoc: // TODO handle t_heredoc type
break;
default: // TODO: Error handling
break;
}
}
Of course that code is not complete. It should show how it is supposed to work.

struct that holds struct, how to dereference

i have couple of linked lists in my larger program which i now want to keep in a struct (t_holder).
typedef struct s_list
{
int val;
struct t_list *next;
} t_list;
typedef struct s_holder
{
t_list *a_starts;
// more lists...
} t_holder;
now i try to figure out how i dereference this in my program.
void try_out(t_holder *list_holder, int num)
{
//assigning something to a_starts
list_holder->a_starts->val = num;
}
int main(int argc, char *argv[])
{
t_holder *list_holder;
int num;
num = 42;
list_holder = NULL;
try_out(list_holder, num);
return (0);
}
in the function "try_out" i simlpy try to assign a value to a_starts->val but my debugger shows me ACCESS_ERROR if i declare it like this
list_holder->a_starts->val = num;
For starters this typedef declarations
typedef struct s_list
{
int val;
struct t_list *next; // <===
} t_list;
is incorrect. It seems you mean
typedef struct s_list
{
int val;
struct s_list *next; // <===
} t_list;
As for your other code then you declared a null pointer
t_holder *list_holder;
//...
list_holder = NULL;
So dereferencing the null pointer results in undefined behavior.
You need to write something like the following
t_holder list_holder = { .a_starts = NULL };
//...
try_out( &list_holder, num);
and then within the function something like
void try_out(t_holder *list_holder, int num)
{
t_list *node = malloc( sizeof( *node ) );
node->val = num;
node->next = list_holder->a_starts;
list_holder->a_starts = node;
}

Expression must have struct or union type

I'm trying to make a stack / linkedlist implementation in C with. I'm struggling on the pop function of a stack.
Here's what my stack/linkedlist implementation looks like :
// a cell
struct cell_s
{
void *elem;
struct cell_s *next;
};
typedef struct cell_s cell_t;
// the list is a pointer to the first cell
struct linkedlist_s
{
struct cell_s *head;
int len;
};
typedef struct linkedlist_s linkedlist_t;
Here's the pop function :
/**
* Pop remove and return the head
*/
cell_t *pop(linkedlist_t *list)
{
if ((*list).len == 0) {
// we cannot pop an empty list
return NULL;
}
else
{
cell_t* tmp = (*list).head;
(*list).head = (*list).head.next; // <-- error occurs here
(*tmp).next = NULL;
return tmp;
}
}
I don't understand what I did wrong. (*list).head is a struct cell_s so I should be able to access the attribute next ? But compiler won't let me do it.
Thanks.
The head field is not a struct cell_s. It is a struct cell_s *, i.e. a pointer to struct cell_s. As such, you need to use the -> operator to dereference and access the member.
list->head = list->head->next;
Note also that ptr->field is easier to read than (*ptr).field.

Initialize a struct in C using {}

In the marked line I get an error Error - expected expression
#include <stdlib.h>
struct list_head {
struct list_head *next, *prev;
};
struct program_struct {
const char *name;
struct list_head node;
};
typedef struct program_struct program_t;
struct task_t {
program_t blocked_list;
};
int main() {
struct task_t *p = malloc(sizeof(*p));
p->blocked_list.name = NULL;
p->blocked_list.node = {&(p->blocked_list.node), &(p->blocked_list.node)}; //error
return 0;
}
I know I can replace this line with
p->blocked_list.node.next = &(p->blocked_list.node);
p->blocked_list.node.prev = &(p->blocked_list.node);
But can I make it work using {} like I tried in the first piece of code?
Initialization is allowed only when you define a variable. So, you can't use initializers in assignment.
You can instead use C99's compound literals:
p->blocked_list.node = (struct list_head) {&(p->blocked_list.node), &(p->blocked_list.node)}; //error

LinkedList Struct Typedef in C

I am try to build a basic linked list in C. I seem to get an error for this code:
typedef struct
{
char letter;
int number;
list_t *next;
}list_t;
char letters[] = {"ABCDEFGH"};
list_t openGame, ruyLopez;
openGame.letter = letters[4];
openGame.number = 4;
openGame.next = &ruyLopez;
ruyLopez.letter = letters[5];
ruyLopez.number = 4;
ruyLopez.next = NULL;
It won't accept my definition in the struct:
list_t *next;
And for the same reason it won't accept:
openGame.next = &ruyLopez;
When you are using list_t *next in your code, the compiler doesn't know what to do with list_t, as you haven't declared it yet. Try this:
typedef struct list {
char letter;
int number;
struct list *next;
} list;
As H2CO3 pointed out in the comments, using _t as an identifier suffix is not a great idea, so don't use list_t.
why did you make it hard on yourself just set openGame and ruzeLopez as pointers and you wont have to use the & (this is the usual way to use linked lists , just don't forget to use -> to access members)
try this code instead :
#include <stdlib.h>
#include <malloc.h>
typedef struct list
{
char letter;
int number;
struct list *next;
}list;
main(void)
{
char letters[] = "ABCDEFGH"; //what were the braces for ?
list *openGame, *ruyLopez;
openGame = ruyLopez = NULL;
openGame = malloc(sizeof(list));
ruyLopez = malloc(sizeof(list));
openGame->letter = letters[4];
openGame->number = 4;
openGame->next = ruyLopez;
ruyLopez->letter = letters[5];
ruyLopez->number = 5;
ruyLopez->next = NULL;
}
Here is a working example without the risk of memory leaks from using malloc to create your structures.
#include <stdlib.h>
typedef struct _list
{
char letter;
int number;
struct _list *next;
} list_type;
int main(void)
{
char letters[] = "ABCDEFGH"; //what were the braces for ?
list_type openGame, ruyLopez;
openGame.letter = letters[4];
openGame.number = 4;
openGame.next = &ruyLopez;
ruyLopez.letter = letters[5];
ruyLopez.number = 5;
ruyLopez.next = NULL;
}

Resources