How can I access the tree in my printpostroder function? - c

This is my tree struct :
typedef struct quad
{
struct quad *child[4];
char *names;
} quad;
and I need to build it then print it in postorder
but I can't access the memory for the tree in my printpostorder function :
void printpostorder(quad * tree)
{
if (tree->names[0] == 'G') {
printpostorder(tree->child[0]);
printpostorder(tree->child[1]);
printpostorder(tree->child[2]);
printpostorder(tree->child[3]);
printf("%s", tree->names);
}
else {
printf("%s", tree->names);
}
}
I can access it before calling this function in the main function.
int main(void){
int n = 0;
int size;
quad * t;
char * str1 = (char *)malloc(MAX * sizeof(char));
printf("Enter name: ");
scanf("%s", str1);
size = strlen(str1);
t = build_preorder_tree(str1,t,&n,size);
printpostorder(t);
}
here is the build tree function, basically we have to build from preorder, then print out the post order.
quad* build_preorder_tree(char *s_r, quad * tree, int * index_ptr,int size){
char c;
int s = 0;
int index = *index_ptr;
c = s_r[index];
char d = ']';
char * ptr = (char *)malloc(MAX * sizeof(char));
char * ptr1;
if(index == size){
return;
}
tree = malloc(sizeof(quad*));
tree -> names = (char *)malloc(MAX * sizeof(char));
if(c == 'G') {
tree->names = "G";
(*index_ptr)++;
tree->child[SW] = build_preorder_tree(s_r, tree->child[SW],index_ptr,size);
tree->child[SE] = build_preorder_tree(s_r, tree->child[SE],index_ptr,size);
tree->child[NW] = build_preorder_tree(s_r, tree->child[NW],index_ptr,size);
tree->child[NE] = build_preorder_tree(s_r, tree->child[NE],index_ptr,size);
}
if(c == 'W') {
tree->names = "W";
(*index_ptr)++;
}
if(c == 'B') {
strcpy(ptr,s_r);
ptr1 = strtok(ptr+index,"]");
strncat(ptr1,&d,1);
s = strlen(ptr1);
(*index_ptr)= (*index_ptr) + s;
tree->names = ptr1;
}
return tree;
}
And when I call the printpostorder(t), a seg fault occurred at first call of
if (tree->names[0] == 'G')
I tried to access the tree before the printpostorder is call, and I was able to access every element of the tree

Related

How can I return list in C?

I am trying to divide the string with *, and return the divided strings, as follows.
abc*d*efg*hijk -> [abc,d,efg,hijk]
This is my code, where *pattern is the given string, and I first count the number of asterisk(cnt), and make a empty list with length cnt. But it keeps getting the error and I don't get it... Can anyone help me?
error message
value computed is not used (*star_cnt++;)
function returns address of local variable(return units;)
Number 2 is my main error. I can't return the list
int Slice(char *pattern) {
int *star_cnt;
int cnt;
*star_cnt = *pattern;
cnt = 0;
while (*star_cnt != '\0') {
if (*star_cnt == '*') {
cnt++;
}
*star_cnt++;
}
int units[cnt];
int *unit;
int unit_cnt;
unit_cnt = 0;
*unit = *pattern;
while (*unit != '\0') {
int *new_unit;
while (*unit != '*'){
*new_unit = *unit;
unit++;
new_unit++;
}
unit++;
units[unit_cnt] = *new_unit;
}
return units;
I felt there were a number of things wrong, and that looking at a working example might actually help a bit more here.
You could try something like this:
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
/**
* #fn Slice()
* #param [IN] pattern - pointer to string to be analysed
* #param
* #return pointer to array for strings, array is terminated by NULL
* */
char** Slice(char *pattern) {
char *star_cnt;
int cnt;
char** resultlist;
star_cnt = pattern;
cnt = 0;
while (*star_cnt != '\0') {
if (*star_cnt == '*') {
cnt++;
}
star_cnt++;
}
printf("%d items\n",cnt+1);
resultlist = malloc(sizeof(char*) * (cnt+2));
memset(resultlist,0,sizeof(char*) * (cnt+2));
star_cnt = pattern;
cnt = 0;
resultlist[cnt] = star_cnt;
//printf("item %d: %s\n",cnt,resultlist[cnt]);
cnt++;
while (*star_cnt != '\0') {
if (*star_cnt == '*') {
*star_cnt = '\0';
resultlist[cnt] = star_cnt+1;
//printf("item %d: %s\n",cnt,resultlist[cnt]);
cnt++;
}
star_cnt++;
}
return resultlist;
}
int main()
{
char working_string[] = "abc*d*efg*hijk";
char* backup_string = strdup(working_string);
char** list = NULL;
list = Slice(working_string);
int i;
i = 0;
if (list != NULL)
{
while(list[i] != NULL)
{
printf("%d : %s\n",i,list[i]);
i++;
}
free(list);
}
printf("original_string = %s\n",backup_string);
free(backup_string);
}
It produces an output like this:
4 items
0 : abc
1 : d
2 : efg
3 : hijk
original_string = abc*d*efg*hijk
The Slice function basically returns a pointer to char* strings, and the array list is terminated with a NULL in the last element. Keep in mind that in this solution the original string is modified so it cannot be used again.
For storing and returning the result you can also define string container like:
struct c_str_container{
char **arr;
size_t size;
};
And then you can define functions like init_c_str_container, add_element_to_c_str_container and free_c_str_container for dealing with the container.
then you can write the substrings function with using strchr function for finding the delimiters and splitting the string in to sub-strings.
Finally you can use this function to create the container and then after displaying the result from the container (and possibly doing other things with the container) you free the allocated memory by the predefined function free_c_str_container:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct c_str_container{
char **arr;
size_t size;
};
void init_c_str_container(struct c_str_container *container){
container->arr = NULL;
container->size = 0;
}
int add_element_to_c_str_container(struct c_str_container *container, const char *txt, size_t length){
char **newarr = (char **) realloc(container->arr, (container->size + 1) * (sizeof(char *)));
if(!newarr){
newarr = (char **) malloc((container->size + 1) * (sizeof(char *)));
if(!newarr){
return -1;
}else{
for(size_t counter = container->size; counter--;){
newarr[counter] = container->arr[counter];
}
if(container->size){
free(container->arr);
}
}
}
newarr[container->size] = malloc((length + 1) * sizeof(char));
memcpy(newarr[container->size], txt, length);
newarr[container->size][length] = '\0';
container->arr = newarr;
++container->size;
return 0;
}
void free_c_str_container(struct c_str_container *container){
for(size_t counter = container->size; counter--;){
free(container->arr[counter]);
}
free(container->arr);
container->size = 0;
}
struct c_str_container substrings(const char *input, const char delimiter){
const char *input_end = input + strlen(input);
struct c_str_container container;
init_c_str_container(&container);
while(strchr(input, delimiter) == input){
++input;
}
const char *end_point;
while((end_point = strchr(input, delimiter))){
add_element_to_c_str_container(&container, input, (end_point - input));
while(strchr(end_point, delimiter) == end_point){
++end_point;
}
input = end_point;
}
if(input < input_end){
add_element_to_c_str_container(&container, input, (input_end - input));
}
return container;
}
int main(void) {
struct c_str_container container = substrings("***as***we*grow*up", '*');
printf("number of elements is : %zu\n", container.size);
for(size_t counter = 0; counter < container.size; ++counter){
printf("element %zu is : %s\n", counter, container.arr[counter]);
}
free_c_str_container(&container);
printf("now elements are : %zu\n", container.size);
return EXIT_SUCCESS;
}
for the test string ="***as***we*grow*up" delimeter = '*' the result of the program is:
number of elements is : 4
element 0 is : as
element 1 is : we
element 2 is : grow
element 3 is : up
now elements are : 0

Segmentation Fault: double free or corruption (fast top)

I've a problem when I run this piece of code: a Segmentation Fault that appears during the free instruction of percorso. I cannot find the problem.
void ricerca(char nome[], struct node *radice, char percorso[], struct stringhe **indice) {
struct node *punt = radice;
int dim = len(percorso);
char *prov = NULL;
if (dim > 0) {
prov = malloc(2 * dim * sizeof(char));
prov[0] = '\0';
strcpy(prov, percorso);
free(percorso); //--------------------->here the SegFault
}
struct stringhe *nuovo = NULL;
int i = 0, fine = 0;
char *perc_orig = NULL;
if (punt != NULL) {
if (punt->array != NULL) {
dim = len(prov) + len(punt->nome) + 2;
percorso = malloc(dim * sizeof(char));
percorso[0] = '\0';
if (prov!=NULL)
strcpy(percorso, prov);
strcat(percorso, "/");
strcat(percorso, punt->nome);
perc_orig = malloc(dim * sizeof(char));
for (i = 0; i < N; i++) {
if (punt->array->vet[i] != NULL) {
perc_orig[0] = '\0';
strcpy(perc_orig, percorso);
ricerca(nome, punt->array->vet[i], perc_orig,indice);
}
}
free(perc_orig);
}
if (strcmp(nome,punt->nome) == 0) {
free(percorso);
dim = len(prov) + len(punt->nome) + 2;
percorso = malloc(dim * sizeof(char));
inizializza(percorso, dim);
if (prov != NULL)
strcpy(percorso, prov);
strcat(percorso, "/");
strcat(percorso, punt->nome);
nuovo = malloc(sizeof(struct stringhe));
nuovo->next = NULL;
nuovo->str = malloc(dim * sizeof(char));
inizializza(nuovo->str, dim);
strcpy(nuovo->str, percorso);
nuovo->next = (*indice);
*indice = nuovo;
}
while (punt->chain != NULL && fine == 0) {
ricerca(nome, punt->chain,prov, indice);
fine = 1;
if (prov!=NULL)
free(prov);
}
}
}
The len function is like strlen, but the difference is that I've made it myself.
the context is:
void find(char nome[], struct node *radice) {
char *perc = NULL;
struct stringhe **inizio = NULL;
inizio = malloc(sizeof(struct stringhe*));
*inizio = NULL;
int i = 0;
for (i = 0; i < N; i++) {
if (radice->array->vet[i] != NULL) {
perc = NULL;
ricerca(nome, radice->array->vet[i], perc, inizio);
}
}
if (*inizio != NULL) {
insertion(inizio);
stampap(*inizio);
} else
printf("no\n");
}
And the data structures:
struct tab {
struct node *vet[64];
};
struct node {
char nome[255];
int num;
int tipo;
char *dati;
struct tab *array;
struct node *chain;
};
This is really weird:
if (some condition)
free(percorso);
Later on we have:
perc_orig = malloc(dim*sizeof(char));
for(something){
if(something){
ricerca(nome,punt->array->vet[i],perc_orig,indice);
}
}
free(perc_orig);
If that if conditions happens, perc_orig will be freed twice. Kaboom.
I think your problem is you think that ricerca(..., char percico[], ...) copies percico. It doesn't; it's really ricerca(..., char *percico, ...) so you ended up freeing the memory twice.
the sizing for the char arrays needs to allow for the trailing NUL ('\0') character.
ALL fields that are referenced by strcpy() and similar functions need to have ALL source character arrays NUL terminated.
The code does not seem to be allocating enough room for those trailing NUL bytes NOR terminating every character array with a NUL char.
Segmentation fault occurs when you initialize a character pointer to NULL and try to point it to a not null value
For example,
char *a=NULL;
a='a';
Will cause segmentation fault. To avoid this you can try to initialize as,
char *a;
a='a';

Memory leak in a recursive function in c

I need some help with memory leak in my C program. The following function searches a radix trie to find a word with a given number. It allocates some memory in every recursive call and I don't know how to sort it out so that the blocks allocated aren't lost. Please help.
char *substring(char *str, int position, int length) {
int c = 0;
char *sub = malloc(length*(sizeof(char))+1);
while (c < length) {
sub[c] = str[position + c];
c++;
}
return sub;
}
void prev(int w, int start, int end) {
char *newWord = "";
bool found = false;
void prevRec(struct tNode *t,
int w, int start, int end, char *soFar, int prevLength) {
if (t != NULL) {
char *updatedWord = malloc(strlen(soFar) + strlen(t->word));
strcpy(updatedWord,soFar);
strcat(updatedWord,t->word);
printf("%s\n", updatedWord);
int length = strlen(t->word);
if (t->count == w) {
found = true;
if ((start > -1) && (end <= strlen(updatedWord))) {
newWord = updatedWord;
} else {
newWord = "";
}
} else {
struct tNode *tmp = t->child;
struct tNode *tmp1 = NULL;
while ((tmp != NULL) && (!found)) {
prevRec(tmp,w,start,end,updatedWord,length);
tmp1 = tmp;
tmp = tmp->brother;
updatedWord = substring(updatedWord, 0, strlen(updatedWord) - prevLength);
}
}
}
}
prevRec(root,w,start,end,newWord,0);
printf("%s\n",newWord);
if (strlen(newWord) == 0) printf("ignored");
else {
char *tmp = substring(newWord,start,end - start + 1);
insert(tmp);
free(tmp);
}
You must free what you've allocated. In your case you could to sth. like that: replace
updatedWord = substring(updatedWord, 0, strlen(updatedWord) - prevLength);
by
char *sub = substring(updatedWord, 0, strlen(updatedWord) - prevLength);
free( updatedWord );
updatedWord = sub;
and add another
free( updatedWord );
as last line of your if( t != NULL ) block.
Besides as #Eregith has already mentioned in his comment, the '+1' for NULL is missing in the length you are allocating. And you should also add some error checking, as malloc() may return NULL

Cutting a substring from a radix tree of strings

my problem is this: I want to search through a radix tree of strings, each having a unique number, until I find the one with the number given as function parameter. While I search the tree recursively I need to update the string (concatenate current string with the new one as I go down and cut off the suffix as I get back from recurrence). Each tree node has a pointer to its child and its brother. The function is as follows and it's not working for some reason.
void prev(struct tree *t, int w, int start, int end) {
char *newWord = "";
bool f = false;
bool *found = &f;
void prevRec(struct tNode *t,
int w, int start, int end, char *soFar) {
if (t != NULL) {
char *updatedWord = malloc(strlen(soFar) + strlen(t->word) + 1);
strcpy(updatedWord,soFar);
strcat(updatedWord,t->word);
int length = strlen(t->word);
if (t->count == w) {
*found = true;
if ((start > -1) && (start <= end)) {
newWord = updatedWord;
} else newWord = "";
} else {
if (!*found) {
prevRec(t->child,w,start,end,updatedWord);
char *sub = substring(updatedWord, 0, strlen(updatedWord) - length);
free(updatedWord);
updatedWord = sub;
prevRec(t->brother,w,start,end,updatedWord);
sub = substring(updatedWord, 0, strlen(updatedWord) - length);
free(updatedWord);
updatedWord = sub;
}
}
}
} //prevRec
prevRec(t->root->child,w,start,end,newWord);
if (strlen(newWord) < 1 || end > strlen(newWord)) {
printf("ignored\n");
globalFound = 1;
} else {
char *tmp = substring(newWord,start,end - start + 1);
insert(t,tmp);
free(tmp);
}
}

having trouble with storing string in linked list

I am having trouble storing a string in a linked list. This is the function that inserts a node to the list:
void insert_rec(rec_ptr *h_ptr, rec_ptr *t_ptr, int a, int b, int c, char* cs)
{
rec_ptr new_ptr;
new_ptr = rec_ptr( malloc( sizeof(REC) ) );
if(new_ptr != NULL)
{
new_ptr->x = a;
new_ptr->y = b;
new_ptr->z = c;
new_ptr->c = cs;
new_ptr->next = NULL;
if(*h_ptr == NULL){
*h_ptr = new_ptr;
}
else{
(*t_ptr)->next = new_ptr;
}
*t_ptr = new_ptr;
}
else
{
printf("%d %d %d not inserted. No memory available.\n",a,b,c);
}
}
This is the function that reads input from an output file. I am inserting a string into the list as a char*. The fscanf() has read the string in correctly.
void read_from_input2(rec_ptr & hptr, rec_ptr & tptr)
{
fp3=fopen("input2.txt","r");
if (fp3 == NULL)
printf("Error: Couldn't open file: input2.txt\n");
else
{
while(!feof(fp3))
{
int x,y,z;
char c1[10];
fscanf(fp3,"%d",&x);
fscanf(fp3,"%d",&y);
fscanf(fp3,"%d",&z);
fscanf(fp3,"%s",c1);
char *c2 = c1;
insert_rec(&hptr,&tptr,x,y,z,c2);
}
}
fclose(fp3);
}
This is the function where I am having problems. When I extract the data from the linked list, the variable c1 outputs garbage.
void write_to_output2(rec_ptr hptr)
{
fp4=fopen("output2.txt","w");
if (fp4 == NULL)
printf("Error: Couldn't open file: output2.txt\n");
else
{
if(hptr == NULL){
printf("List is empty.\n\n");
}
else{
while(hptr != NULL)
{
int x,y,z;
char *c1,*c2;
x = hptr->x;
y = hptr->y;
z = hptr->z;
c1 = hptr->c;
c2 = get_class(x,y,z);
fprintf(fp4,"%d %d %d %s %s\n",x,y,z,c1,c2);
hptr = hptr->next;
}
}
}
fclose(fp4);
}
If anyone can see my error please help me out. Thanks.
char c1[10];
/* ... */
char *c2 = c1;
insert_rec(&hptr,&tptr,x,y,z,c2);
The problem is c1 is on the stack of read_from_input2 and then you store a pointer to its contents. It will go out of scope when the while ends thus access to it will be invalid.
You'll want to strdup it (or equivalent).
char *c2 = strdup(c1);
/* or */
new_ptr->c = strdup(cs);
And don't forget to free it at some point.

Resources