开发者

Remove the last new line in C

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==N开发者_如何学CULL)
    {
        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?


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.


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.


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);


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.


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.


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);
  }
}


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?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜