I have to do this project on Flex/Yacc, where I must calculate the Abstract Syntax Tree of an Insiemistic expression. But the real problem is within the C code.
I've made this function, that creates a node:
node_t * createNode(node_content_t nodecontent, int nodetype){
node_t *newNode = (node_t *) malloc(sizeof(node_t * ));
if(nodetype == 0){
newNode->content = (node_content_t)strdup(nodecontent.string);
}
else
newNode->content = nodecontent;
newNode->type = nodetype;
newNode->leftChild = NULL;
newNode->rightChild = NULL;
printf("Right Child in createNode: %p\n", newNode->rightChild);
return newNode;
}
As you can see, left and right child are both initialized to null. But when i try to print the pointer value of the right child out of the function, it changes value(tipically to 0x23 or 0x53), leading to a segmentation fault.
node_t and node_content_t are defined as follows
typedef union{
char* string;
char singleletter;
}node_content_t;
typedef struct node node_t;
struct node{
node_content_t content;
int type; //0 for string, 1 for char
node_t *leftChild;
node_t *rightChild;
};
When i tried to print the pointer in createNode
, it resulted 0x0, i printed it in this function printNode, that should print the entire tree:
void printNode(node_t *n, size_t indent) {
char *indentation = malloc(sizeof(char) * indent);
for (size_t i = 0; i < indent; ++i) {
indentation[i] = ' ';
}
printf("LeftChild: %p\n", n->leftChild);
printf("RightChild: %p\n", n->rightChild);
switch (n->type) {
case 0: printf("%s%s\n", indentation, n->content); break;
case 1: printf("%s%c\n", indentation, n->content); break;
}
if (n->leftChild != NULL){
printNode(n->leftChild, indent+2);
}
if (n->rightChild != NULL){
printf("RightChild: %p\n", n->rightChild); //there
printNode(n->rightChild, indent+2);
}
printf("Non ci sono figli\n");
}
And as i said, the value change, so the function doesn't work, any ideas? I don't modify the value of rightChild if not in the function addChild:
void addChild(node_t *parent, node_t *child) {
printf("Addchild\n");
printf("Right Child in createNode: %p\n", parent->rightChild);
if(parent->leftChild == NULL)
parent->leftChild = child;
else if(parent->rightChild == NULL && strcmp(parent->content.string, "co") != 0 ){
parent-> rightChild = child;
printf("Aggiunto figlio destro\nContent: %c\nType: %d\n", child->content, child->type);
}
else
printf("Error during child adding\n");
}
Problem 1:
node_t *newNode = (node_t *) malloc(sizeof(node_t * ));
node_t *
; not the node_t
struct you intend.malloc()
can fail. Get used to checking return values. Make it a habit!node_t *newNode = malloc( sizeof *newNode ); // cleaner
if( newNode == NULL ) { /* handle error condition */ }
Problem 2:
void printNode(node_t *n, size_t indent) {
char *indentation = malloc(sizeof(char) * indent); // <== never free'd
for (size_t i = 0; i < indent; ++i) { // unnecessary...
indentation[i] = ' ';
}
printf("LeftChild: %p\n", n->leftChild);
printf("RightChild: %p\n", n->rightChild);
switch (n->type) {
case 0: printf("%s%s\n", indentation, n->content); break;
case 1: printf("%s%c\n", indentation, n->content); break;
}
indentation
is allocated each time this function is called, and it is never free()
'd.indentation
is NOT null terminated and must not be treated as a C string.Get rid of the lines performing the allocation and utilise the capabilities of printf()
. Eg:
printf( "%*s%s\n", indent, "", n->content ); break;
%*s
gets the field width specifier from the next parameter, in this case indent
. It then gets the string to be printed in a field that wide, in this case ""
. The result is a prefix of the desired number of spaces on each line.