【问题标题】:Use of fseek with stdout将 fseek 与标准输出一起使用
【发布时间】:2014-08-15 15:49:42
【问题描述】:

文件指针arg为stdout时是否可以使用fseek?

我在尝试用“)”覆盖逗号分隔列表中的最后一个“,”时尝试过

例如

fprintf(stdout, "1,2,3,4,");

fseek(stdout, -1, SEEK_CUR);

fprintf(stdout, ")");

实现:

1,2,3,4)

相对于

1,2,3,4,)

不幸的是我输出了后者

【问题讨论】:

  • printf(...) 等同于fprintf(stdout, ...),并且比fprintf(stdout, ...) 更清晰。
  • 不管什么可行或不可行,我认为完全不产生尾随逗号而不是乱搞输出流会很多干净。跨度>
  • 我自己也得出了同样的结论——乱搞文件指针位置显然是一堆虫子
  • 我已经用另一种解决方案来解决打印逗号分隔列表的问题。

标签: c


【解决方案1】:

您可以在stdout 上成功使用fseek 当且仅当 stdout 指的是可搜索的流。

如果您的程序的标准输出将发送到终端或类似的东西(通常是默认设置)或管道,那么fseek 将失败。如果因为您执行程序并重定向了输出而导致它进入一个文件,那么fseek 可以像处理任何其他文件一样工作。

任何时候你调用fseek,你都应该检查它的返回值,看看它是成功还是失败。

假设 stdout 是可搜索的可能是不好的做法,因为它通常是一个不好的假设。

您的目标是在项目之间打印带有", " 的项目序列,但不是在第一个之前或最后一个之后。 fseek 和打印 '\b' 都不是您想要做的事情的好方法。如果您还没有打印列表中的最后一项,则应该打印逗号only,而不是打印最后一个逗号然后尝试删除它。检测到这一点并非易事。

但更简单的方法是在每个项目前加上逗号除非它是第一个。您不能总是判断您是否正在打印序列的最后一个值。您可以始终判断您是否在打印第一个。

伪代码:

bool is_first_item = true
for each item
    if is_first_item
        is_first_item = false
    else
        print ", "
    end if
    print item
end for 

【讨论】:

  • stdout 被重定向到管道时,搜索不会必然失败。大概它可以工作(在我的简短测试中),因为输出仍在缓冲区中。
【解决方案2】:

stdout 上使用fseek 是不可能的。相反,您可以使用退格符 '\b' 将光标向后移动一个空格:

fprintf(stdout, "1,2,3,4,");

fprintf(stdout, "\b)");

注意:这stdout 指向终端并且被重定向到文件或管道时才起作用。此外,如果光标当前位于行首,则不能保证这能正常工作。一般来说,只有少数情况下会起作用。

【讨论】:

  • 没有理由假设stdout 指的是终端,或者将'\b' 打印到stdout 将移动光标。如果您的程序的输出被重定向到一个文件,那么您只需将"1,2,3,4,\b" 写入该文件。
  • @KeithThompson 我添加了一个说明。
  • 您还忽略了其他一些情况。如果stdout 要去管道怎么办?
  • @KeithThompson 我可以争辩说我松散地使用了“文件”这个词:P 但无论如何我都修复了它
  • 我已经撤回了我的反对票,但目前尚不清楚打印 '\b' 是否可以合理替代 fseek 调用(或者问题中的 fseek 是否合理方法,即使它有效)。
猜你喜欢
  • 2011-06-22
  • 2012-04-16
  • 2011-02-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多