First element in a double pointer to struct is jiberrish - c

I am creating a simple array of structures in C, but the first structure is always jibberish. How do i fix this?
I have tried to set the first element of the double pointer to struct in many ways but it always fails.
This is my graph.h file:
#ifndef GRAPH_H
#define GRAPH_H
#include "set.h"
typedef struct urlNode * URLList;
typedef struct GraphRep * Graph;
struct urlNode {
int id;
char* URL_NAME;
URLList next; // link to next node
};
struct GraphRep {
int nV;
URLList * collections;
};
Graph newGraph(Set s);
int nameToId(Graph g, char *name);
void showGraph(Graph g);
#endif
And my newGraph(Set s) function looks like this:
Graph newGraph(Set s){
int size = nElems(s);
Graph new_graph = malloc(sizeof(struct GraphRep));
if (new_graph == NULL) {
printf("ERROR: COULDNT ALLOCATE GRAPH\n");
}
new_graph->nV = size;
char *name = getNextVal(s);
// THIS IS THE NODE TO BE ADDED TO THE GRAPH
URLList list_to_add = malloc(sizeof(struct urlNode));
list_to_add->URL_NAME = strdup(name);
list_to_add->id = 0;
list_to_add->next = NULL;
// HERE I ADD THE NODE TO THE GRAPH.
new_graph->collections[0] = list_to_add;
// PRINT OUT THE VALUES OF THE NEWLY ADDED NODE TO MAKE SURE IT WORKS
// THE URL_NAME IS PRINTED OUT FINE
// BUT THE ID IS JIBBERISH.
printf("%s\n", new_graph->collections[0]->URL_NAME);
printf("%d\n", new_graph->collections[0]->id);
if(new_graph->collections[0]->next != NULL) {
printf("%s\n", new_graph->collections[0]->next->URL_NAME);
printf("%d\n", new_graph->collections[0]->next->id);
}
printf("\n");
return new_graph;
}
I expect new_graph->collections[0]->id to be 0 but it keeps on giving me random ints.
Also even if the next for the newly declared pointer to struct is NULL, it still gives me a jibberish next value too.
Any help would be appreciated, thanks!

The data member collections of the object *new_graph is not initialized.
There is initialized only this data member
new_graph->nV = size;
So this statement
new_graph->collections[0] = list_to_add;
results in undefined behavior.
If you need an array of pointers of the type URLList you have to allocate the memory and its address assign to the pointer collections.
For example
new_graph->collections = malloc( new_graph->nV * sizeof( URLList ) );
And after that this statement
new_graph->collections[0] = list_to_add;
could be valid.
(I suppose that the data member nV corresponds to the number of elements in the dynamically allocated array though it may not be truth)
Pay attention to that as the string pointed to by the pointer name is not changed in the function then it is better to declare it like
const char *name = getNextVal(s);

Related

Cannot allocate dynamic array on C

Im trying to create a graph structure on C but I got some issues. First, Im getting 2 compilation errors:
main.c:18:19: error: member reference type 'node' is not a
pointer; did you mean to use '.'?
graph[index]->start = NULL;
~~~~~~~~~~~~^~
.
main.c:18:27: error: expression is not assignable
graph[index]->start = NULL;
~~~~~~~~~~~~~~~~~~~ ^
2 errors generated.
compiler exit status 1
I cannot figure out what Im doing wrong. I tried to create an array of nodes* but the compiler doesn't recognize it as a pointer for some reason. It's like malloc doesn't work. Also, I can't manage to acess edge* fields because it's like the array of nodes* is non-existent.
#include <stdio.h>
#include <stdlib.h>
#define maxNodes 4
typedef struct edge {
int target;
struct edge* next;
} edge;
typedef struct {
edge* start;
} node;
void initializeGraph(node* graph) {
graph = (node *) malloc(maxNodes * sizeof(node));
for(int index = 0; index < maxNodes; index++) {
graph[index]->start = NULL;
}
}
int main(void) {
node test;
initializeGraph(&test);
}
Im trying to initialize my structure. Any help is appreciated.
You have a large number of problems in your short example code. As to your error, that is covered by #dbush's answer and [...] serves as a dereference on your pointer making the '.' (dot) operator proper instead of the -> arrow operator.
Next, you cannot declare a node with static storage duration in main() and pass its address for allocation in your function. When you declare node test; all storage is already provided on the stack. You can't then pass that address to your function and allocate additional memory for that struct.
If you intend to have more than one node, then you can either declare an array with static storage duration in main(), or you must declare a pointer in main() and allocate in your function. To make that allocation visible in main(), as noted in my comment, you can either (1) make the return type node * and return a pointer to the allocated block for assignment in the caller, or (2) make the parameter node** and pass the address of your pointer as the parameter.
Putting that altogether and choosing option (1) above, you could do:
#include <stdio.h>
#include <stdlib.h>
#define maxNodes 4
typedef struct edge {
int target;
struct edge* next;
} edge;
typedef struct {
edge* start;
} node;
node *initializeGraph (void) {
node *graph = malloc(maxNodes * sizeof *graph);
if (!graph)
return NULL;
for (int index = 0; index < maxNodes; index++) {
graph[index].start = NULL;
}
return graph;
}
int main (void) {
node *test = initializeGraph();
if (!test)
fputs ("error: initialization failed.\n", stderr);
else
puts ("initialization succeeded");
}
Example Use/Output
$ ./bin/graphinit
initialization succeeded
Allocating For Each test[i].start
Before you can make use of any of the start pointers, you must allocate storage for a struct edge and assign the beginning address for that block of memory to each of your test[i].start pointers. You can do that in your same initializeGraph() function by allocating where you currently set the pointers NULL, e.g.
node *initializeGraph (void)
{
node *graph = malloc(maxNodes * sizeof *graph);
if (!graph)
return NULL;
for (int index = 0; index < maxNodes; index++) {
graph[index].start = malloc (sizeof *graph[index].start);
if (!graph[index].start)
return NULL;
}
return graph;
}
You can then assign a value to the target in each. Extending the earlier example, you could do:
int main (void) {
node *test = initializeGraph();
if (!test)
fputs ("error: initialization failed.\n", stderr);
else
puts ("initialization succeeded");
for (int i = 0; i < maxNodes; i++)
test[i].start->target = i;
puts ("targets filled");
}
Example Use/Output
$ ./bin/graphinit
initialization succeeded
targets filled
(don't forget to free the memory you allocate when it is no longer needed)
Look things over and let me know if you have further questions.
The array index operator [] implicitly dereferences a pointer. The syntax a[b] is exactly the same as *(a + b).
This means that graph[index] has type node, not node *. So use . instead of -> as the error message suggests.
graph[index].start = NULL;

Operations with pointers in linked lists

Generally, I know that a pointer stores the memory address of another value located in computer memory, for example:
int firstvalue= 5
int * p1;
p1 = &firstvalue; // p1 = address of firstvalue
What happens if we define an operation like the following in a linked list? Does *current=*list means that the value pointed to by current equals to the value pointed to by list? And what does it mean if we define ecur=current?
int function(struct list_t **list){
struct list_t *ecur=NULL;
struct list_t *current=*list;
ecur=current;
}
Update:
What does it do *list=remove(*list, param1, param2)? And why is that?
remove is a function that returns a modified list of list.
Update 2:
Why do we need to define a pointer to pointer in order to modify the list? Is *list a pointer to pointer?
The variable list is a pointer to a pointer to a struct list_t. If we (just as an example) assume that the struct is placed at address 2000 and that the unnamed pointer is at address 1000 it will look like this:
Then you have the initialization that adds two new variables. Both as pointer to a struct list_t.
struct list_t *ecur=NULL;
struct list_t *current=*list;
So the picture now becomes:
Notice that current got the same value as the "some-pointer" in the middle because it is *list that was assigned to current.
Then you have the assignment:
ecur=current;
which means that ecur gets the same value as current and gives the picture:
Update: What does it do *list=remove(*list, param1, param2) ?
It changes the value of the "some-pointer" in the middle of the picture. This is for instance needed if the remove function removes the first element in a linked list.
Why do we need to define a pointer to pointer in order to modify the list? Is *list a pointer to pointer?
Remember that C passes all function arguments by value - the formal argument in the function definition is a different object in memory from the actual argument in the function call. For example:
void swap( int a, int b )
{
int tmp = a;
a = b;
b = tmp;
}
void foo( void )
{
int x = 1;
int y = 2;
swap( x, y );
}
a is a different object in memory than x, and b is a different object in memory than y, so swapping a and b has no effect on x and y. In order to swap the values of x and y, you must pass pointers to them:
void swap( int *a, int *b )
{
int tmp = *a;
*a = *b;
*b = tmp;
}
void foo( void )
{
int x = 1;
int y = 2;
swap( &x, &y );
}
The expression *a is the same as x, so writing to *a is the same as writing to x. Same for *b and y.
So, in order for a function to write to a parameter, you must pass a pointer to that parameter:
void foo ( T *arg )
{
*arg = new_value(); // writes a new value to the thing arg points to
}
void bar( void )
{
T var;
foo( &var ); // write a new value to var
}
This is true for any non-array type T. Let's replace T with a pointer type P *:
void foo( P **arg )
{
*arg = new_value(); // write a new *pointer* value to the thing arg points to
}
void bar( void )
{
P *var;
foo( &var ); // write a new pointer value to var
}
The semantics are exactly the same - all that's changed is the type.
If a function has the potential to modify a list * object (say pointing it at a new list head), then you must pass a pointer to that list * object:
void add_node( struct list_t **list, struct list_t *node )
{
if ( !*list || (node->value < (*list)->value) ) // make node new head of list
*list = node;
else
// add node somewhere else in the list
}
int main( void )
{
struct list_t *list = NULL;
...
struct list_t *node = newNode( value );
add_node( &list, node );
...
}
TYPE *p = ptype /*variable of type: TYPE * */;
is not an assignment. It's an initialization, which for an auto-matic (=on-the-stack) p can be rewritten as:
TYPE *p;
p = ptype;
(not TYPE *p; *p=ptype; /*would be a type error*/)
In terms of your example:
struct list_t *current=*list;
sets where current will point to (the same place as what *list points to (*list is also a pointer because list is a doubly-indirect pointer)) without doing anything whatsoever with what current will point at (*current) after the initialization.
All of this is just conceptual, though. Your function doesn't have any externally visible effects so an optimizing compiler should completely delete its body.
I had a similar knot in my head with this post. I'd like to rearrange your function a bit, so it's easier to understand what's going on:
int function(struct list_t **list)
{
struct list_t *current = *list;
struct list_t *ecur = current;
}
If we call this function with an element foo we essentially get this:
struct list_t foo = { .data = "foo" };
struct list_t *bar = &foo;
struct list_t **list = &bar;
struct list_t *current = *list;
struct list_t *ecur = current;
We have five declarations and five assignments. For better readability, I'll write everything down without declarations:
foo = { .data = "foo" };
bar = &foo;
list = &bar;
current = *list;
ecur = current;
Now, let's walk through it:
foo is a struct. It contains the above data-field.
bar is a pointer to struct. It contains the address of foo
list is a pointer to a pointer to struct. It contains the address of bar
current is a pointer to struct. It contains the contents of the contents of list, which is the address of foo
ecur is a pointer to struct. It's identical to current and contains the address bar
In the end we can simplify the whole example to this:
struct list_t foo = { .data = "foo" };
struct list_t *ecur = &foo;
What does it all mean?
list: Because list is a pointer to a pointer you are able to modify bar to point to something completely different, by de-referencing it (*list = ...)
current/ecur: that's what bar originally pointed too. By de-referencing you could change the data-field itself ((*ecur).data = "banana" or better ecur->data)
I hope I could clarify things and didn't make it worse ;)
Why do we need to define a pointer to pointer in order to modify the
list?
Let me add a complete program, albeit short, to illustrate it better. It defines a simply linked list and builds it while keeping it ordered. Yes, I know it would be easier to simply call qsort(), but I want to demonstrate how adding one level of indirection —the pointer to pointer— allows to insert elements smoothly, without testing for special cases.
// C pointer exercise: sort arguments
#include <stdio.h>
#include <strings.h>
#include <stdlib.h>
struct list
{
char *arg;
struct list *next;
};
int main(int argc, char *argv[])
{
// pointer to base, running pointer and pointer to pointer
struct list *base = NULL, *p, **pp;
for (int i = 1; i < argc; ++i)
{
struct list *new_entry = malloc(sizeof(struct list));
if (new_entry)
{
new_entry->arg = argv[i];
// find where to insert new entry
for (pp = &base; *pp; pp = &(*pp)->next)
if (strcasecmp(new_entry->arg, (*pp)->arg) < 0)
break;
// insertion in a simply linked list
new_entry->next = *pp;
*pp = new_entry;
}
}
// display and cleanup
for (p = base; p;)
{
struct list * tmp = p->next;
puts(p->arg);
free(p);
p = tmp;
}
return 0;
}

Error: variable (struct) has initializer but incomplete type (C)

Okay, I'm very new to C and need an explanation as to why I'm getting this error:
"variable 'newFilm' has initializer but incomplete type"
The task is to create a struct called film. Then pass the data from a .txt file into that struct and create a linked list of structs representing all of the data in the .txt
The problem seems to be that the compiler is missing the point where I allocate memory for the struct newFilm which I believe is being done correctly
Code in main file:
char* t = (char*)malloc(sizeof(char*));
int y;
char* r = (char*)malloc(sizeof(char*));
char* g = (char*)malloc(sizeof(char*));
int rt;
double s;
List* list = newList();
//read pReadFile
char input[256];
//read characters from file being pointed at, and store into input
while( fgets( input, 256, pReadFile )) {
//scan each line with each variable separated by a comma
fscanf(pReadFile,"%s %d %s %s %d %d\n", t,y,r,g,rt,s);
struct Film newFilm = createFilm(t,y,r,g,rt,s); //ERROR OCCURS HERE
addToList(list, newFilm);
}
printList(list, pWriteFile);
Here is the createFilm function from film.c source file:
Film *createFilm(char *title, int year, char *rating,
char *genre, int runtime, double score){
Film *newFilm = (Film*)malloc(sizeof(Film));
// n.b. error checking to be added - to be added
title = (char*)malloc(sizeof(title));
newFilm->title = title;
newFilm->year = year;
rating = (char*)malloc(sizeof(rating));
newFilm->rating = rating;
genre = (char*)malloc(sizeof(genre));
newFilm->genre = genre;
newFilm->runtime = runtime;
newFilm->score = score;
return newFilm;
}
While I don't think there is anything wrong with the addToList function I thought I'd keep it so you have better context (in database.h file):
void addToList(List* list, struct Film* film){
Node *node = (Node*)malloc(sizeof(Node));
//Generates an error message and the program terminates if
//insufficient memory is available.
if (node == NULL){
fprintf(stderr, "Error: Unable to allocate memory in list_add()\n");
exit(EXIT_FAILURE);
}
//appends film to tail of linked list
node->film = film;
node->next = NULL;
if (list->last == NULL){
list->first = list->last = node;
}
else{
list->last = list->last->next = node;
}
}
Thanks in advance :)
You are missing the declaration of the struct. With struct Film; you can create as many struct Film * pointers as you would like, because the compiler can figure out how big a pointer to a film will have to be (big enough to point to a struct).
However, since all you have is that Film is a struct (not what the struct is, or how big it is) you can't actually create a struct Film variable, since the compiler can't know how much space to allocate for that. There are two fixes for this:
Make the entire struct visible.
This likely involves moving the struct definition (not just declaration) to the header file. IE:
// old film.h
struct Film;
// new film.h
struct Film {
int with;
int all;
int of;
int the;
int things;
int it;
int needs;
};
Make the entire struct opaque, and use opaque accesses.
This means that you never actually create struct Film anywhere in the code that uses it. Instead you write functions to create/destroy a film pointer and to access/modify each element.
Typically option 2 is more extensible (since changing the struct doesn't affect the code) but option 1 is easier.

Initialization of a structure that contains a pointer to an array

I have the following structure:
typedef struct TRIE_NODE
{
char* word;
struct TRIE_NODE* node[26];
}TRIE_NODE;
I create a node called head, TRIE_NODE *head = NULL;, and then i try to initialize this node using the following function:
void initialize_node(TRIE_NODE *current_node)
{
int MAX = 25;
current_node = malloc(sizeof(TRIE_NODE));
for(int i = 0; i < MAX; i++)
{
current_node->node[i] = NULL;
if(current_node->node[i] == NULL)
printf("\n -- \n");
}
}
However, i get a segmentation fault whenever i try to even read current_node->node[i]. Does anyone have any idea of what's going on? Considering current_node->node is a pointer, that points to another pointer of type TRIE_NODE, shouldn't i be able to access it's values through bracket notation? (I've tried dereferencing it too, it doesn't compile)
You do everything correctly, except this line
current_node = malloc(sizeof(TRIE_NODE));
which modifies the local copy of current_node. The pointer in the caller remains unchanged.
To fix this problem, pass a pointer to pointer, and assign with an indirection operator:
void initialize_node(TRIE_NODE **current_node_ptr) {
...
*current_node_ptr = malloc(sizeof(TRIE_NODE));
...
}

Using malloc with structures in a function

HERE IS MY INSTRUCTIONS FOR THIS FUNCTION: Here an unsigned integer listsize is passed to this function you are to create a link list of size listsize. This will be performed by repeated use of malloc and calling setData to initialize the data into the struct plane fields. Each time you place the process in the list you need to place it so the list is sorted by the field distance (in ascending order). you return the head of the list
struct plane* list_intialize(unsigned int num)
{
struct plane *ptr,*head;
int i=0;
ptr = (struct plane*) malloc(num * sizeof(struct plane));
for (i = 0; i < num; ++i)
setData(ptr+i);
return ptr;
}
This started as a function skeleton inside an already completed program....I'm to complete the function so that it creates a link list. The setData is given function that inserts data to the structure elements.....MY problem is that after I run the current function it only returns one plane with information instead of num amount....am I using setData wrong or should my current setup work
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#ifndef _MY_DEF_
#define _MY_DEF_
enum dir {NE=0, EN, NW, WN, SE, ES, SW, WS};
enum loc {LNE=0, LNW,LSE,LSW};
struct plane{
short flightCode;
long xCord;
long yCord;
double distance;
char direction;
enum dir flightPattern;
enum loc location;
struct plane *nextPlane;
};
#endif
struct plane* sortByDist(struct plane*);
struct plane * radarPrint(struct plane*head);
int checkPlane(struct plane *);
int checkForCollision(struct plane*);
void setData(struct plane *pLane);
You need to allocate your list by allocating each node. One way of doing that while chaining the list forward is the code below:
struct plane* list_intialize(unsigned int num)
{
struct plane *head, **pp = &head;
int i=0;
for (i=0; i<num; ++i)
{
*pp = malloc(sizeof(**pp));
setData(*pp);
pp = &(*pp)->nextPlane;
}
*pp = NULL;
return head;
}
How It Works
This uses a pointer-to-pointer to always hold the address of the location where the nextPlane dynamo node address is stored. It starts with the address of the head pointer. With each new node, pp is filled the address of that node's nextPlane member. Once finished, it holds the address of the last node's nextPlane pointer, which it sets to NULL. The first node, pointed to by head, is returned. (and yes, this works even if you passed num = 0 for the requested size, in which case you would get back zero nodes: i.e. NULL).
Note: Don't forget, you need to free each node when releasing the list, extracting a single node out, etc. For example, to delete an entire list:
void list_delete(struct plane **lst)
{
while (*lst)
{
struct node *victim = *lst;
*lst = victim->nextPlane;
free(victim);
}
}
Invoked like this:
struct plane *lst = list_initialize(N);
// use list.., maybe adding nodes, removing them, changing, etc...
list_delete(&lst);
How to print your list:
void list_print(const struct plane *lst)
{
while (lst)
{
// TODO: print list node pointed to by lst.
// Ex: (x,y) coords
printf("(%d,%d) ",lst->xCord, lst->yCord);
lst = lst->nextPlane;
}
printf("\n");
}
You are not setting the links between the objects. In the for loop, you need:
ptr[i]->nextPlane = ptr[i+1];
At the end of the loop, make sure the last object points to NULL.
ptr[i-1] = NULL;

Resources