So, here's the story. I'm trying to create a recursive descent parser that tokenizes a string and then creates a tree of nodes out of those tokens.
All of the pointers for my major classes are working... if you're worked with an RDP before then you know what I'm talking about with program -> statement -> assignStmt... etc. The idea being that the program node has a child that points to the statement node, etc.
Here's the problem. When I get to the end of the treenode I'm pointing to the actual tokens that the tokenizer created from the string.
So, let's say the string is:
firstvar = 1;
In this case there are 4 tokens [{id} firstvar], [{assignment} =], [{number} 1], [{scolon}]
And I want my assignStmt node to point to the non-decorator portions of that statement.. namely, child1 of assignStmt would be [{id} firstvar] and child2 would be [{number} 1]...
HOWEVER. When I assign child1 to [{id} firstvar], and then move onward to the next tokens, the value of child1 changes as I move forward. So, if I change my global token to the next token ( in this case [{assignment} =] ) then child1 of the assignStmt changes with it.
Why is this? What can I do?! Thank you!
TOKEN* getNextToken(void);
//only shown here to you know the return... it's working properly elsewhere
typedef struct node {
TOKEN *data;
struct node *child1, *child2, *child3, *child4, *parent;
} node;
TOKEN *token;
Symbol sym;
struct node *root;
void getsym()
{
token = getNextToken();
sym = token->sym;
}
int main()
{
getsym();
//So, right now, from getsym() the global token has the value {identifier; firstvar}
struct node* tempNode;
tempNode = (struct node*) calloc(1, sizeof(struct node));
tempNode->child1 = tempNode->child2 = tempNode->child3 = tempNode->child4 = NULL;
tempNode->data = token;
getsym();
//BUT NOW from getsym() the global token has the value {assignment; =}, and
//subsequently the tempNode->data has changed from what it should be
//{identifier; firstvar} to what the global token's new value is: {assignment; =}
}
Since i can't comment on this due to my low reputation i will add this answer and if have understood your problem you are probably passing a pointer to a function, and the problem is that you probably need a pointer to pointer instead of just a pointer.
in C when you pass values to a function you are passing them by value, not by reference, meaning that the function makes a local copy of that argument and it will work only with that local copy, the problem is that all the changes will affect only the local copy and when the function terminates all the changes will be lost if you will not handle this correctly.
You are returning a pointer to a global variable, and that pointer will always be the same even if you modify the global variable.
The solution is to either allocate a new object each time, or to not use pointers at all and return the structure directly and let the compiler handle copying of the structures internal values.
Related
I want the value of a pointer variable to be initialized to NULL at the start of the execution. This variable is used in a function and its value may also get changed within the function. But I do not want the value of this variable to reset to NULL whenever a function call is made. Instead, its value should be equal to the updated value from its previous function call. Cannot use global variables.
void function(struct node *variable) {
// changes value of pointer variable to something else
variable = something;
}
void another_function(void) {
// have to be initialised before passing in as argument or else will raise error
struct node *variable = NULL;
function(variable);
}
// then calling this function multiple times in main
another_function();
another_function();
help would be much appreciated.
Firstly, the pointer variable variable is local to another_function. It does not live outside of this scope.
Secondly, when you pass it to function, the variable parameter of that function is also local to that function. You immediately assign a value to that local variable, but that doesn't change the variable you passed in.
You can use the static keyword when declaring your initial pointer variable.
It will only be initialized when first encountered during the execution.
But as for now, your code will probably not do what you intend it to do.
The pointer variable in function is local and will have no effect on the value of variable in another_function.
You should use a pointer of pointer (also called a double-pointer or a nested pointer) for this effect.
Here is an example of how to use a double-pointer :
struct node {
int value;
};
void function(struct node** variable) {
if(*variable == NULL) {
*variable = (struct node*)malloc(sizeof(struct node));
(*variable)->value = 1;
}
printf("Value of variable is %d\n", (*variable)->value);
// Creating another struct node just for the demonstration
struct node* newnode = (struct node*)malloc(sizeof(struct node));
newnode->value = (*variable)->value + 1;
*variable = newnode;
}
void another_function() {
static struct node* variable = NULL;
function(&variable);
}
Basically, you pass the address of a pointer (located on the stack, which will always have a memory address) which let you modify the content of this pointer (a memory address on the heap) in the receiving function.
When you are dereferencing variable in function, what you get is not a value but another pointer.
Also parenthesis are important in this case.
Nested pointers can really be confusing, I hope that my explanation is somewhat clear.
To really understand how it works you need to understand what it's on the stack and what it's on the heap. But maybe this is an explanation for another time.
Of course, there is no memory management in this example and what I wrote contains memory leaks from all struct node that never are deallocated.
You should figure out how to do it depending on your program architecture.
I am learning data structure, and here is a thing that I am unable to understand...
int end(struct node** p, int data){
/*
This is another layer of indirection.
Why is the second construct necessary?
Well, if I want to modify something allocated outside of my function scope,
I need a pointer to its memory location.
*/
struct node* new = (struct node*)malloc(sizeof(struct node));
struct node* last = *p;
new->data = data;
new->next = NULL;
while(last->next !=NULL){
last = last ->next ;
}
last->next = new;
}
why we are using struct node **p?
can we use struct node *p in place of struct node **p?
the comment which I wrote here is the answer I found here, but still, I am unclear about this here is the full code...
please help me
thank you
Short answer: There is no need for a double-pointer in the posted code.
The normal reason for passing a double-pointer is that you want to be able to change the value of a variable in the callers scope.
Example:
struct node* head = NULL;
end(&head, 42);
// Here the value of head is not NULL any more
// It's value was change by the function end
// Now it points to the first (and only) element of the list
and your function should include a line like:
if (*p == NULL) {*p = new; return 0;}
However, your code doesn't !! Maybe that's really a bug in your code?
Since your code doesn't update *p there is no reason for passing a double-pointer.
BTW: Your function says it will return int but the code has no return statement. That's a bug for sure.
The shown function (according to its name) should create a new node and apend it at the end of the list represented by the pointer to a pointer to a node of that list. (I doubt however, that it actually does, agreeing with comments...)
Since the list might be empty and that pointer to node hence not be pointing to an existing node, it is ncessary to be able to potentially change the pointer to the first elemet of that list away from NULL to then point to the newly created node.
That is only possible if the parameter is not only a copy of the pointer to the first node but instead is a pointer to the pointer to the first node. Because in the second case you can dereference the pointer to pointer and actually modify the pointer to node.
Otherwise the list (if NULL) would always still point to NULL after the function call.
Lets say I have the following code,
typedef struct WordNode WordNode;
struct WordNode {
int freq; // The frequency of the the word.
char *word; // The word itself.
WordNode *next; // The next word node in the list.
};
struct WordSet {
int size; // The number of elements in the set.
WordNode *head; // The starting node in the set.
};
After this, I've got some functions that initialize these structs. To prevent too much code in this post, I'm going to avoid posting those functions here.
Now, lets say I have the following,
WordNode **p = wset->head; // can't change this line
Here, p is basically a pointer pointing to a pointer, correct?
And then, if I do this:
(*p) == NULL
This would return true if p is pointing to NULL, right?
Now, how would I get the word stored in wset->head?
Can I do this?
(*(*p))->word
And if I want p to point to the next WordNode, can I do this?
p = (*(*p))->next
I just want to know if all this is valid syntax so that I know I'm using pointers correctly.
Not really. (*(*p))->word is a total dereferenciation. So it would either be (*(*p)).word or (*p)->word.
You can imagine it that way, that the ->-Operator takes away one reference for you.
obj->field is the same as (*obj).field
Just for the sake of simplicity, whenever I have to deal with double pointer and I need the value I all the time go via an intermediate variable
e.g.
WordNode **ptr2ptr = wset->head;
WordNode *ptr = *ptr2Ptr;
WordNode value = *ptr;
or to get the head:
WordNode head = ptr->head;
Now I'm just answering the question which is, how to access the value of a pointer to pointer. You must be careful that your wset->head contains actually a pointer to pointer which is normally not the case in a linked list the way I understand you are trying to do. This is also not the way you have defined your head member...
Hi I am making a Queue abstact data type and I ran into a problem which I will try to explain as clearly as possible.
Basically I have a two structs one for an element and one for a queue (so you can initialize multiple queues).
struct element
{
TYPE value;
struct element* next;
};
struct queue
{
struct element* head;
struct element* tail;
int element_counter;
};
And I have a function which initializes my queue struct.
int make_new_queue(struct queue* name)
{
name = malloc(sizeof(struct queue));
name->head = NULL;
name->tail = NULL;
name->element_counter = 0;
}
The problem I ran into is foolproofing this code. For example I initialised my first queue in my main function.
struct queue* first = make_new_queue(first);
But if somebody tries to do the same thing again somewhere in the middle of the code write:
first = make_new_queue(first);
it overrides it and makes the head and tail pointers NULL. The thing I can't figure out is how to make my make_new_queue function better and check if there is something in the queue that I provide it, but still let me initialise empty queues.
Sorry for my english. I hope you get the idea of what I want to do. Thanks.
Initialize it to NULL and pass a pointer to pointer:
void make_new_queue(struct queue **name)
{
if (*name != NULL) return; /* Yet initialized ? */
*name = malloc(sizeof(struct queue));
if (*name == NULL) {
perror("malloc");
exit(EXIT_FAILURE);
}
*name->head = NULL;
*name->tail = NULL;
*name->element_counter = 0;
}
struct queue *first = NULL;
make_new_queue(&first);
You can simply check if you variable name is NULL.
If your variable is non-null, you can alloc and initialize your queue else just do what you want to do.
There is really no good way to enforce what you want without discipline from the user. In my opinion, the best approach is to stick to known patterns.
You can use Alter Mann's approach to pass a pointer to a pointer to update the struct. The drawback is that is that you have to separate variable declaration and initialisation. It also relies on the user to initialise the pointer to the struct to NULL. If you forget it, the queue pointer will not be initialised and you don't even know, because you can't check against NULL.
struct stuff *stuff = NULL;
stuff_initialise(&stuff);
You can use your original approach to pass in the struct and return the same struct when it was initialised or a new one. It has the same problems as the first approach plus the possibility that you forget to assign the return value. You can, however, combine allocation and initialisation:
struct stuff *stuff = stuff_new(NULL);
The simplest way is not to pass the old pointer and rely on the user not to change the pointer after allocation. After all, the functions of the standard library suffer from the same problem:
char *buf = malloc(BUFSIZE);
buf = malloc(2 * BUFSIZE); // Memory leak
buf++; // Allowed, but a bad idea
free(buf); // Ouch!
FILE *f = fopen("palomino.txt", "r");
f = stdin; // Switch horses midstream?
You should design your API so that you have matching pairs of functions that define the scope of your struct:
struct stuff *stuff = stuff_create(...);
// use stuff ...
stuff_destroy(stuff);
Good naming should make clear that stuff acts as a handle and should not be changed and that after closing or destroying the handle, it is invalid. You should see these calls as first and last statements in functions. (This method is similar to the malloc/free or fopen/fclose pairngs of the standard library.)
Finally, if you as the user of a handle want to avoid accidential changes, you can define the pointer (not what it points to) as const:
struct stuff *const handle = stuff_create("X");
handle = stuff_create("Y"); // Compiler error
But I rarely see this. C programmers usually just use an unadorned pointer and remember to keep their fingers off the hotplate.
So, here's the story. I'm trying to create a recursive descent parser that tokenizes a string and then creates a tree of nodes out of those tokens.
All of the pointers for my major classes are working... if you're worked with an RDP before then you know what I'm talking about with program -> statement -> assignStmt... etc. The idea being that the program node has a child that points to the statement node, etc.
Here's the problem. When I get to the end of the treenode I'm pointing to the actual tokens that the tokenizer created from the string.
So, let's say the string is:
firstvar = 1;
In this case there are 4 tokens [{id} firstvar], [{assignment} =], [{number} 1], [{scolon}]
And I want my assignStmt node to point to the non-decorator portions of that statement.. namely, child1 of assignStmt would be [{id} firstvar] and child2 would be [{number} 1]...
HOWEVER. When I assign child1 to [{id} firstvar], and then move onward to the next tokens, the value of child1 changes as I move forward. So, if I change my global token to the next token ( in this case [{assignment} =] ) then child1 of the assignStmt changes with it.
Why is this? What can I do?! Thank you!
TOKEN* getNextToken(void);
//only shown here to you know the return... it's working properly elsewhere
typedef struct node {
TOKEN *data;
struct node *child1, *child2, *child3, *child4, *parent;
} node;
TOKEN *token;
Symbol sym;
struct node *root;
void getsym()
{
token = getNextToken();
sym = token->sym;
}
int main()
{
getsym();
//So, right now, from getsym() the global token has the value {identifier; firstvar}
struct node* tempNode;
tempNode = (struct node*) calloc(1, sizeof(struct node));
tempNode->child1 = tempNode->child2 = tempNode->child3 = tempNode->child4 = NULL;
tempNode->data = token;
getsym();
//BUT NOW from getsym() the global token has the value {assignment; =}, and
//subsequently the tempNode->data has changed from what it should be
//{identifier; firstvar} to what the global token's new value is: {assignment; =}
}
Since i can't comment on this due to my low reputation i will add this answer and if have understood your problem you are probably passing a pointer to a function, and the problem is that you probably need a pointer to pointer instead of just a pointer.
in C when you pass values to a function you are passing them by value, not by reference, meaning that the function makes a local copy of that argument and it will work only with that local copy, the problem is that all the changes will affect only the local copy and when the function terminates all the changes will be lost if you will not handle this correctly.
You are returning a pointer to a global variable, and that pointer will always be the same even if you modify the global variable.
The solution is to either allocate a new object each time, or to not use pointers at all and return the structure directly and let the compiler handle copying of the structures internal values.