Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

jamesapp

macrumors 6502a
Original poster
Mar 7, 2008
544
0
Code:
#include <stdio.h>
#include <ctype.h>
#include <string.h>

struct tnode {  /* the tree nod: */
   char *word;  /* points to the text */
   int count;  /* number of occurences */
   struct tnode *left;  /* left child */
   struct tnode *right;  /* right child */
};

#define MAXWORD 100
struct tnode *addtree(struct tnode *, char *);
void treeprint(struct tnode *);
int getword(char *, int);

/*word frequency count */
main()
{
  struct tnode *root;
  char word[MAXWORD];
  
  root = NULL;
  while (getword(word, MAXWORD) != EOF)
      if (isalpha(word[0]))
          root = addtree(root, word);
  treeprint(root);
  return 0;
}

struct tnode *talloc(void);


/* addtree: add a node with w, at or below p */
struct tnode *addtree(struct tnode *p, char *w)
{
  int cond;
  
  if (p == NULL) {  /* a new word has arrived */
      p = talloc();  /* make a new node */
      p->word = strdup(w);
      p->count = 1;
      p->left = p->right = NULL;
  } else if ((cond = strcmp(w, p->word)) == 0)
      p->count++;  /* repeated word */
  else if (cond < 0)  /* less than into left subtree */
      p->left = addtree(p->left, w);
  else     /* greater than into right subtree */
      p->right = addtree(p->right, w);
  return p;
}

/* treeprint: in-order print of tree p */
void treeprint(struct tnode *p)
{
  if (p != NULL) {
      treeprint(p->left);
      printf("%4d %s\n", p->count, p->word);
      treeprint(p->right);
  }
}

/* getword: get next word or characters from input */
int getword(char *word, int lim)
{
  int c, getch(void);
  void ungetch(int);
  char *w = word;
  
  while (isspace(c = getch()))
      ;
  if (c != EOF)
      *w++ = c;
  if (!isalpha(c)) {
      *w = '\0';
      return c;
  }
  for ( ; --lim > 0; w++)
      if (!isalnum(*w = getch())) {
          ungetch(*w);
          break;
      }
   *w = '\0';
   return word[0];
}

#define BUFSIZE 100

char buf[BUFSIZE];  /* buffer for ungetch */
int bufp = 0;  /* next free position in buf */

int getch(void)  /* get a (possibly pushed back) character */
{
  return (bufp > 0) ? buf[--bufp] : getchar();
}

void ungetch(int c)  /* push character back on input */
{  
  if (bufp >= BUFSIZE)
      printf("ungetch: too many characters\n");
  else
      buf[bufp++] = c;
}

#include <stdlib.h>

/* talloc: make a tnode */
struct tnode *talloc(void)
{
  return (struct tnode *) malloc(sizeof(struct tnode));
}

the following program is from a book on the c programming language.
from the book: "Storage obtained by calling malloc may be freed for re-use by calling free" just wondering exactly how to free malloc? Any information on the process of using free, would be appreciated.
 

admanimal

macrumors 68040
Apr 22, 2005
3,531
2
To make a long story short, any memory that you allocate using any of the alloc functions (malloc, calloc, etc.) should also be free'd by you or your program could have a memory leak. This means that you need to make sure to always have at least one pointer available to any memory that you have malloc'ed so that you can free that memory when you're done with it.
 

jamesapp

macrumors 6502a
Original poster
Mar 7, 2008
544
0
. This means that you need to make sure to always have at least one pointer available to any memory that you have malloc'ed so that you can free that memory when you're done with it.

i see in the code from the book:
Code:
struct tnode *talloc(void);
i also see:
Code:
/* talloc: make a tnode */
struct tnode *talloc(void)
{
  return (struct tnode *) malloc(sizeof(struct tnode));
}
from the above code snippets, does *talloc(void)
mean that talloc(void) is a pointer to tnode?
and so i would use like:
Code:
free(talloc);
}
 

lee1210

macrumors 68040
Jan 10, 2005
3,182
3
Dallas, TX
i see in the code from the book:
Code:
struct tnode *talloc(void);
i also see:
Code:
/* talloc: make a tnode */
struct tnode *talloc(void)
{
  return (struct tnode *) malloc(sizeof(struct tnode));
}
from the above code snippets, does *talloc(void)
mean that talloc(void) is a pointer to tnode?
and so i would use like:
Code:
free(talloc);
}

I'm not sure what level of knowledge you have yet, so I'll try to cover this as briefly as possible and can expand if needed.

talloc is a function. Its return type is a pointer to a tnode structure. Every time you call talloc, a malloc is performed, and the pointer returned will need to have free called on it.

Example:

Code:
void myfunction(int numToGrab) {
  int counter=0;
  tnode *list = null;
  list = (tnode *)malloc(sizeof(tnode *)*numToGrab);
  for(counter = 0; counter < numToGrab; counter++){
    list[counter] = talloc();
  }

  //Do some work with all of those tnodes

  for(counter = 0; counter < numToGrab; counter++){
    free((void *)list[counter]);
  }
  free((void *)list);
}

In the example i malloc'd my own list to use to store tnode pointers. I then called talloc the number of times specified (note, i didn't make sure numToGrab was positive, etc. so this could cause an overflow situation). I put a comment where you could do some work with all of those tnodes you allocated with talloc. I then free'd EACH of those tnodes first, THEN free'd the list i had allocated.

If I free'd my list first, I wouldn't have assured access to the tnode *s that I needed to free, so sometimes the order of freeing, not just that you do it, is important too.

-Lee
 

kalimba

macrumors regular
Jun 10, 2008
102
0
i see in the code from the book:
Code:
struct tnode *talloc(void);
i also see:
Code:
/* talloc: make a tnode */
struct tnode *talloc(void)
{
  return (struct tnode *) malloc(sizeof(struct tnode));
}
Just to be clear, the first block is the declaration of the function 'talloc'. It tells the compiler that you are promising to define the function at some later time. The second block is where you fulfill your promise to the compiler by defining the 'talloc' function.
 

pjrobertson

macrumors 6502a
Nov 14, 2007
533
4
Not sure how much I know, but it the C / Objective - C book I'm reading it just says to add the

[objectName free];

command to the end of the program.

Also, if you turn on garbage collection, doesn't this do it for you in Leopard?

Project -> Project Settings -> 'Build' tab -> search for 'garbage'
 

admanimal

macrumors 68040
Apr 22, 2005
3,531
2
Not sure how much I know, but it the C / Objective - C book I'm reading it just says to add the

[objectName free];

command to the end of the program.

Also, if you turn on garbage collection, doesn't this do it for you in Leopard?

Project -> Project Settings -> 'Build' tab -> search for 'garbage'

The OP appears to be using straight up C, so the Objective-C stuff doesn't apply.
 

kalimba

macrumors regular
Jun 10, 2008
102
0
If the OP is still struggling with this, the solution lies in the fact that your 'alloc'ated blocks of memory are being added to a binary tree, which (theoretically) gives you a complete data structure containing pointers to all of the memory blocks you've allocated. When it's time to release all of those blocks, you'll want to traverse your binary tree (much in the same way you traverse the tree when adding new elements to it) and free each block. I'll not reveal the complete solution and leave the implementation details as an exercise.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.