删除C中的最后一个新行

时间:2011-08-07 10:39:36

标签: c file

我想从以下函数中删除最后一个新行:

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

我正在使用此函数将文本文件写入BST的内容,我不希望它写下最后一行,我该如何删除它?

7 个答案:

答案 0 :(得分:5)

在像你这样的递归例程中,你不能轻易知道哪个是最后一个电话,但你可以知道第一个电话是什么。

不是编写数据和可选的换行符,而是考虑编写一个可选的换行符后跟数据:

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

但是,考虑文本模式文件中最常用的行定义是:包含新行的0个或更多字符的序列。根据这个定义所有行都有换行符;并且文件中的最后一段数据不是一行。

至少有一个写得不好的程序因为这个而无法处理整个输入。我的猜测是它有点像

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

如果最后一条数据包含换行符,那么编写得很糟糕的程序就会有效。

答案 1 :(得分:3)

按如下方式修改您的功能:

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

isFarRight变量会跟踪您当前是否位于树的最右侧。如果当前节点有子节点,或者如果您不在最右侧,则只打印'\n'

答案 2 :(得分:3)

一旦你已经写入文件,就可以使用ftruncate将文件截断为大小 - 1

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

在Windows上,使用_chsize而不是ftruncate

_chsize(fd, size - 1);

答案 3 :(得分:1)

在写完整个树之后,您可以将文件截断1个字节。 How to truncate a file in C可能会帮助您。

通常,您可以尝试不写最后一个\ n,因为您知道自己位于最后一个节点,但考虑到树的这种实现,您将不得不对代码进行一些更改,所以通常,第一种方法对你来说可能更快。 - 示例如何做到这一点已由Oli Charlesworth给出,我认为这种方法更好然后截断(不做坏事,而不是修复它),两者都可以。 / p>

答案 4 :(得分:1)

你可以这样做:

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

在你的主要电话中拨打Write(tree, 1);。不漂亮,但应该工作。

答案 5 :(得分:0)

这是按顺序打印树,即从左到右?

我认为递归写树应该定义如下:

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

您确定您的功能是按顺序打印树吗?

答案 6 :(得分:0)

请注意,在您的代码中,您为树的根文本两次写入NULL。所以不用改变你的函数定义:

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