【问题标题】:Is there a "File IO in Postscript for Dummies"?是否有“傻瓜后记中的文件 IO”?
【发布时间】:2011-02-27 21:37:35
【问题描述】:

在 Stack Overflow 上播放的大部分 都涉及 ASCII 数字,codegolf.SE 的形成方式相同。

这一切都很好,但我想在输出中注入一点变化,并明确写下我最近的问题Output a playable crossword grid 以鼓励图形格式输入。

为了表示愿意,我开始尝试在 postscript 中编写一个参考实现。唉,我对这门语言完全陌生,在做基本的文件 IO 时遇到了麻烦。有谁知道涵盖该主题的基本资源?

我知道

  • file
  • (%stdin)
  • token
  • readstring
  • readline

但我很不清楚最后三个返回的确切内容以及在你得到它之后如何操纵它。

已经发现有几个返回 <value> <boolean> 对,我可以使用 if 来测试布尔值。然后呢?

【问题讨论】:

    标签: code-golf file io postscript


    【解决方案1】:

    一本关于后记的好书是格伦·里德(Gleen Reid)的《在后记中思考》。你以前可以从他的网站上免费获得这本书供个人使用,但它已经关闭了。您仍然可以从 http://replay.waybackmachine.org/20090621100720/http://www.rightbrain.com/pages/books.html

    第 14 章介绍了文件 io 并提供了示例代码。

    【讨论】:

    • 如果我可以花时间找到一个waybackmachine链接,我会加2。谢谢。
    • 嗯,我现在才写这篇后记 2 天,但我认为任何“在后记中思考”的人都必须是......疯了?不过很好的参考。
    【解决方案2】:

    在 postscript 中的 File IO 有一些技巧和快捷方式,这些技巧和快捷方式通常不会在 postscript 书籍的介绍部分中提及。其中最保守的秘密是“令牌”运算符。它允许您借用解释器自己的扫描仪来读取裸词(生成名称类型对象)、数字(生成 integertype 或 realtype 对象)或这些数组(但前提是您使用可执行数组表示法,即花括号,否则您只会得到一个表示左方括号的 marktype 对象)。

    作为一个简单的例子,我经常使用这个单行代码在后记程序中嵌入一个扩展的评论部分:

    %!
    { currentfile token pop /END-COMMENT eq {exit} if } loop
    Each word here is read from the current file and converted
    into a name object and compared to "/END-COMMENT".
    It can have but does not need a preceeding slash.
    
    This program produces an image of a snowman in a blizzard,
    suitable for use as stationary.
    END-COMMENT
    
    showpage
    

    编辑:我现在意识到这是一个非常糟糕的答案......到目前为止。

    我上面的例子只是:

    (Some
    multi-line
    text)
    pop
    

    所以,这次是真的。

    首先,您需要loop

    {
    } loop
    

    在这个循环中,你读取了一些数据。

    /src (datafile) (r) file def
    {
        src readline
    } loop
    

    正如您所观察到的,文件读取运算符都在堆栈顶部返回一个布尔值。完美!

    /src (datafile) (r) file def
    {
        src readline {
        }{
            exit
        } ifelse
    } loop
    

    所以布尔值 true 会做一些事情并继续循环,但布尔值 false(no-more-data)会导致循环终止。但是readline 需要一个字符串来将其数据放入其中。即使在错误的情况下它也会返回字符串。

    /src (datafile) (r) file def
    /str 80 string def
    {
        src str readline {
            processline
        }{
            pop exit
        } ifelse
    } loop
    

    现在我们有一个字符串,其中包含文件中的一行(最多 80 个字符)数据。如果它完全类似于 Postscript 语法,您可以在循环中使用token(就像我的第一个示例一样;它从文件中读取每个单词,将其转换为可执行名称,然后将其与文字名称进行比较;如果名称匹配,退出循环)。或者您可以在循环中使用get(或forall 循环)将每个字节提取为整数。但最酷的做法是search

    此过程扫描字符串以查找以空格分隔的单词并将每个单词打印到 stdout 的单独行。

    /processline { % (line)
         ( ) { % (line) ( )
             search { % (post) ( ) (pre)
                 =
             }{ % (no-match)
                 =
                 exit
             } ifelse
         } loop
    } def
    

    当您想对最后一个单词做同样的事情时,在这里复制案例通常更容易。你可以做一些棘手的事情来处理最上面的字符串,然后然后测试布尔值;但这并不值得麻烦。 search 最酷的地方在于它返回结果的便捷顺序。它将字符串的开头放在顶部,以便您可以使用它。然后它为您提供“匹配”(与您最初提供的“搜索”相同(尽管现在它引用了工作字符串))和其余部分;并且它们已经按照正确的顺序进行下一次循环。

    那么,您想如何处理从外部文件中读取的提取的、以空格分隔的单词?

    如果它们代表数字,您可以cvicvr 对它们进行算术运算。如果它们是字母数字,您可以printshow 他们;或cvn 它们并将它们用作原子符号。

    【讨论】:

    • 我发布了一个wrapper function for readline,它将增加字符串缓冲区以容纳不定长度的行。
    • 我有一个“棘手的东西来处理最顶层的字符串并然后测试布尔值”here的例子。
    【解决方案3】:

    听起来您想将一个简单的文本文件(表示填字游戏布局)转换为在页面上绘制该填字游戏的 PostScript 代码。虽然 PostScript 确实是图灵完备的,因此可以通过编程来做到这一点,但我认为在 PostScript 中对整个事物进行编程并不是一个好方法。

    PostScript 是一种很难编程的语言,尤其是当您想处理任意数据时。当我想要 PostScript 输出时,我首先将一些示例 PostScript 拼凑在一起,这些示例 PostScript 绘制了我想要的内容,所有参数都硬编码。然后我用其他语言编写代码,输出 PostScript 代码,根据输入的需要改变适当的部分。

    我发现它读起来不太好,所以这里有一个例子。如果我有一个包含圆半径的输入文件,那么我将用 Python 编写一个程序来读取该半径,然后编写 PostScript 代码来绘制圆,并将半径硬编码在 PostScript 中。

    几年前,我开始从事填字游戏项目。没有走得太远,但附加的 PostScript 代码会画一个小填字游戏。请注意,“正确”的 PostScript 遵循一些我不关心的文档约定;我有一些关于它们的粗略笔记可以发布。

    这个 PostScript 代码确实做了一些计算。一般来说,我会在 PostScript 中为我期望做的事情编写函数,或者为需要只有 PostScript 解释器才能拥有的数据的事情编写函数,例如当前字体中字符串的宽度,用于居中。

    我还没有清理过这个。随时要求澄清。 HTH。

    %!
    
    % "Example"
    % by (author)
    % Generated 16 Apr 2005 22:19 by (program name)
    
    % should really be eps
    
    % unit conversions
    
    /inch {72 mul} bind def
    /cm {inch 2.54 div} bind def
    
    
    
    %%%%%% start of adjustable parameters
    
    % these may be fiddled with, within reason
    % be careful not to change the syntax
    
    % paper size
    /page_width 8.5 inch def
    /page_height 11 inch def
    
    % page margins
    /top_margin 1 inch def
    /left_margin 1 inch def
    
    % how many "cells" wide and high
    /puzzle_width 9 def
    /puzzle_height 9 def
    
    % cell_size: height and width of a one-letter square, in points
    /cell_size .25 inch def
    
    % line width, in points. 1 is about maximum.
    /line_width .375 def
    
    % font and size for the numbers
    /cell_font {/Helvetica 5} bind def
    
    % top/left margin for numbers within a cell
    /num_margin 1.5 def
    
    %%%%%% end of adjustable parameters
    
    
    
    << /PageSize [page_width page_height] >> setpagedevice
    
    
    /w_pts puzzle_width cell_size mul def
    /h_pts puzzle_height cell_size mul def
    
    /ulx left_margin def
    /uly page_height top_margin sub def
    /lrx ulx w_pts add def
    /lry uly h_pts sub def
    
    
    % draw grid
    
    line_width setlinewidth
    0 setgray
    
    newpath ulx uly w_pts h_pts neg rectstroke
    
    lry cell_size uly {
      newpath ulx exch moveto w_pts 0 rlineto stroke
    } for
    
    ulx cell_size lrx {
      newpath lry moveto 0 h_pts rlineto stroke
    } for
    
    
    % fill in black spaces
    
    % ulx uly width height blackrect
    % all in terms of cells; upper-left-most is 0,0
    /blackrect
    {
      << >> begin
      /h exch def /w exch def /y exch def /x exch def
      newpath
      ulx x cell_size mul add
      uly y cell_size mul sub
      w cell_size mul
      h cell_size mul neg
      rectfill
      end
    } bind def
    
    0 setgray
    0 0 1 1 blackrect
    3 0 2 1 blackrect
    8 0 1 1 blackrect
    4 1 1 1 blackrect
    2 2 1 1 blackrect
    6 2 1 1 blackrect
    8 3 1 1 blackrect
    0 4 2 1 blackrect
    7 4 2 1 blackrect
    0 5 1 1 blackrect
    2 6 1 1 blackrect
    6 6 1 1 blackrect
    4 7 1 1 blackrect
    0 8 1 1 blackrect
    4 8 2 1 blackrect
    8 8 1 1 blackrect
    
    
    % draw numbers
    
    % x y h s drawnum
    % x and y in terms of cells; upper-left-most is 0,0. s is string.
    % h is height of numbers. should never change, so compute once before any calls.
    /drawnum
    {
      << >> begin
      /s exch def /h exch def /y exch def /x exch def
      newpath
      ulx x cell_size mul add num_margin add
      uly y cell_size mul sub num_margin sub h sub
      moveto s show
      end
    } bind def
    
    0 setgray
    cell_font selectfont
    
    % compute font height
    mark
    newpath 0 0 moveto
    (0) false charpath flattenpath pathbbox
    /fh exch def
    cleartomark newpath
    
    1 0 fh (1) drawnum
    2 0 fh (2) drawnum
    5 0 fh (3) drawnum
    6 0 fh (4) drawnum
    7 0 fh (5) drawnum
    0 1 fh (6) drawnum
    3 1 fh (7) drawnum
    5 1 fh (8) drawnum
    8 1 fh (9) drawnum
    0 2 fh (10) drawnum
    3 2 fh (11) drawnum
    4 2 fh (12) drawnum
    7 2 fh (13) drawnum
    0 3 fh (14) drawnum
    2 3 fh (15) drawnum
    6 3 fh (16) drawnum
    2 4 fh (17) drawnum
    1 5 fh (18) drawnum
    7 5 fh (19) drawnum
    8 5 fh (20) drawnum
    0 6 fh (21) drawnum
    3 6 fh (22) drawnum
    7 6 fh (23) drawnum
    0 7 fh (24) drawnum
    2 7 fh (25) drawnum
    5 7 fh (26) drawnum
    6 7 fh (27) drawnum
    1 8 fh (28) drawnum
    6 8 fh (29) drawnum
    
    
    showpage
    

    【讨论】:

    • 所以用 c 编写来生成 postscript 是一种替代方法,但我认为在 postscript 中简单地编写它会很可爱。我认为这很难。我已经掌握了参考手册和蓝色和绿色书籍,所以除了 IO 之外的所有东西我都应该没问题,因为 IO 一直在我的大脑中抛出一个未实现的陷阱。 ::sigh::
    • 嗯,这对我来说很难。真正的 PS 黑客可能会觉得这很容易。我只有参考手册。我自己会使用 Python;我看到你用过它,但也许不是很多。效率更高了,我的 C 技能现在已经生疏了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-12
    • 2010-09-23
    • 1970-01-01
    • 1970-01-01
    • 2012-06-22
    • 2014-03-07
    相关资源
    最近更新 更多