2

I want to remove the last new line from the following function:

void WriteToFile(node *tree)
{
    void Write(node*);
    fp = fopen("dictionary.txt","w");
    if(fp==NULL)
    {
        printf("Cannot open file for writing data...");
    }
    else //if(tree==NULL)
    {
        if(tree!=NULL)
        {
            Write(tree);
        }
        fclose(fp);  
    }
}
void Write(node *tree)
{
    if(tree!=NULL)
    {
        fprintf(fp,"%s:%s\n",tree->word,tree->meaning);
        Write(tree->left);
        Write(tree->right);
    }
}

I am using this function to write to a text file the contents of a BST, and I dont want it to write the last new line, how can I remove it?

beatgammit
  • 19,817
  • 19
  • 86
  • 129
Caffeinatedwolf
  • 1,217
  • 3
  • 20
  • 26
  • 1
    I am curious. Why don't you want to write a newline for the last line? Conventionally, all lines of a text file should be terminate with a newline, including the last one. – CB Bailey Aug 07 '11 at 10:49

7 Answers7

5

In a recursive routine like yours, you cannot easily know which is the last call, but you can know what is the first call.

Rather than writing data and, optionally, a newline, consider writing an optional newline followed by data:

void FirstWrite(node *tree, FILE *fp)
{
    if (tree)
    {
        fprintf(fp, "%s%s", tree->word, tree->meaning);
        Write(tree->left, fp);
        Write(tree->right, fp);
    }
}
void Write(node *tree, FILE *fp)
{
    if (tree)
    {
        fprintf(fp, "\n%s%s", tree->word, tree->meaning);
        Write(tree->left, fp);
        Write(tree->right, fp);
    }
}

But consider the most used definition of a line for text mode files is: a sequence of 0 or more characters folllowed by and including a newline. According to this definitilon all lines have a newline; and the last piece of data in your file is not a line.

At least one badly written program I've used fails to process the whole input because of that. My guess is that it does something like

fgets(buf, sizeof buf, inf);
inlen = strlen(buf);
if (buf[inlen - 1] == '\n') processline(buf);

This badly written program would work if the last piece of data included a newline.

pmg
  • 106,608
  • 13
  • 126
  • 198
3

Modify your function as follows:

void Write(node *tree, int isFarRight)
{
    if(tree!=NULL)
    {
        fprintf(fp,"%s:%s",tree->word,tree->meaning);
        if (!isFarRight || tree->left || tree->right)
        {
            fprintf(fp, "\n");
        }
        Write(tree->left, 0);
        Write(tree->right, isFarRight);
    }
}

...

Write(tree, 1);

The isFarRight variable keeps track of whether you're currently on the far right-hand side of the tree. You only print the '\n' if the current node has children, or if you're not on the far right-hand side.

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
3

Once you've already written to the file, you can use ftruncate to truncate the file to size - 1

size_t size = ftell(fp);
ftruncate(fp, size - 1);

On windows, use _chsize instead of ftruncate

_chsize(fd, size - 1);
Charles Ma
  • 47,141
  • 22
  • 87
  • 101
1

You can truncate the file by 1 byte, after writing whole tree. How to truncate a file in C might help you with that.

Normally, you could try to not write the last \n by knowing that you are in the last node, but considering this implementation of tree, you would have to make few changes to the code, so generally, the 1st approach might be quicker for you. - sample how to do that has been given by Oli Charlesworth, this approach I think is nicer then truncating (not doing harm, instead of fixing it), both will work though.

Community
  • 1
  • 1
Marcin Deptuła
  • 11,789
  • 2
  • 33
  • 41
1

You could do it this way:

void Write(node *tree, int first) {
  if (tree!=NULL) {
    if (!first)
      fprintf(fp, "\n");
    fprintf(fp,"%s:%s",tree->word,tree->meaning);
    Write(tree->left, 0);
    Write(tree->right, 0);
  }
}

And call Write(tree, 1); in your main. Not pretty, but should work.

Mat
  • 202,337
  • 40
  • 393
  • 406
  • I'd suggest to have a default value for first ( = 1) to make it prettier. The caller shouldn't care about implementation details of Write – Armen Tsirunyan Aug 07 '11 at 10:52
  • That would be nice, but would require a second function - I don't think you can have default values in C like you can in C++. [pmg](http://stackoverflow.com/users/25324/pmg) posted something like that. – Mat Aug 07 '11 at 10:55
0

Does this print the tree in order, i.e. from left to right?

I think that the recursive write tree should be defined as follows:

write(tree *node)
{
    write(node->left);
    printf(.....);
    write(node->right);
}

Are you sure that your function prints the tree in order?

Louis Marascio
  • 2,629
  • 24
  • 28
0

Note that in your code, you text twice for the root of the tree to be NULL. So without changing your function definition:

void WriteToFile(node *tree)
{
  void Write(node*);
  fp = fopen("dictionary.txt","w");
  if(fp==NULL)
  {
    printf("Cannot open file for writing data...");
  }
  else //if(tree==NULL)
  {
    if(tree!=NULL)
    {
      fprintf(fp,"%s:%s",tree->word,tree->meaning);
      Write(tree);
    }
    fclose(fp);  
  }
}
void Write(node *tree)
{
  if (tree->left)
  {
    fprintf(fp,"\n%s:%s",tree->left->word,tree->left->meaning);
    Write(tree->left);
  }

  if (tree->right)
  {
    fprintf(fp,"\n%s:%s",tree->right->word,tree->right->meaning);
    Write(tree->right);
  }
}
jfg956
  • 16,077
  • 4
  • 26
  • 34