我想从以下函数中删除最后一个新行:
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的内容,我不希望它写下最后一行,我该如何删除它?
答案 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);
}
}