C.4.5 另一个错误 … 最阴险的

我说过“几乎准备好打印”!当然,在print-graph函数中存在一个错误 … 它有一个vertical-step选项,但没有horizontal-step选项。top-of-range刻度从10到300,间隔为十。但print-graph函数只会打印每个单位。

这是某些人认为最阴险类型的错误的典型例子,即遗漏错误。这不是你可以通过研究代码找到的错误,因为它不在代码中;它是一个被遗漏的特性。你最好的行动是尽早而经常地尝试你的程序;并且尽量安排,尽可能写出易于理解和修改的代码。尽量在任何时候都意识到,无论你写了什么,会被重新编写,如果不是很快,那就是迟早的事。这是一个难以遵循的格言。

需要对print-X-axis-numbered-line函数进行修改;然后需要调整print-X-axisprint-graph函数。不需要做太多事情;有一个小技巧:数字应该对齐在刻度标记下方。这需要一点思考。

以下是修正后的print-X-axis-numbered-line

(defun print-X-axis-numbered-line
  (number-of-X-tics X-axis-leading-spaces
   &optional horizontal-step)
  "打印X轴数字线"
  (let ((number X-axis-label-spacing)
        (horizontal-step (or horizontal-step 1)))
    (insert X-axis-leading-spaces)
    ;; 删除多余的前导空格。
    (delete-char
     (- (1-
         (length (number-to-string horizontal-step)))))
    (insert (concat
             (make-string
              ;; 插入空白。
              (-  (* symbol-width
                     X-axis-label-spacing)
                  (1-
                   (length
                    (number-to-string horizontal-step)))
                  2)
              ? )
             (number-to-string
              (* number horizontal-step))))
    ;; 插入剩余的数字。
    (setq number (+ number X-axis-label-spacing))
    (while (> number-of-X-tics 1)
      (insert (X-axis-element
               (* number horizontal-step)))
      (setq number (+ number X-axis-label-spacing))
      (setq number-of-X-tics (1- number-of-X-tics)))))

如果你在Info中阅读此内容,你可以查看print-X-axisprint-graph的新版本,并对其进行评估。如果你在印刷的书中阅读此内容,你可以在这里看到更改的行(完整文本太长,无法打印)。

(defun print-X-axis (numbers-list horizontal-step)
  "打印X轴标签,长度为NUMBERS-LIST。
可选参数HORIZONTAL-STEP,一个正整数,
指定每列的X轴标签增量。"
;; 符号宽度和full-Y-label-width的值由print-graph传递。
  (let* ((leading-spaces
          (make-string full-Y-label-width ? ))
       ;; 符号宽度由graph-body-print提供
       (tic-width (* symbol-width X-axis-label-spacing))
       (X-length (length numbers-list))
       (X-tic
        (concat
         (make-string
          ;; 制作一串空格。
          (-  (* symbol-width X-axis-label-spacing)
              (length X-axis-tic-symbol))
          ? )
         ;; 用空格和刻度符号连接。
         X-axis-tic-symbol))
       (tic-number
        (if (zerop (% X-length tic-width))
            (/ X-length tic-width)
          (1+ (/ X-length tic-width)))))

    (print-X-axis-tic-line
     tic-number leading-spaces X-tic)
    (insert "\n")
    (print-X-axis-numbered-line
     tic-number leading-spaces horizontal-step)))
(defun print-graph
  (numbers-list &optional vertical-step horizontal-step)
  "打印带标签的条形图,NUMBERS-LIST的Y轴值构成。

可选参数VERTICAL-STEP,一个正整数,
指定每行的Y轴标签增量。例如,步长为5表示每行五个单位。

可选参数HORIZONTAL-STEP,一个正整数,
指定每列的X轴标签增量。"
  (let* ((symbol-width (length graph-blank))
         ;; height既是最大的数字,也是具有最多数字的数字。
         (height (apply 'max numbers-list))
         (height-of-top-line
          (if (zerop (% height Y-axis-label-spacing))
              height
            ;; 否则
            (* (1+ (/ height Y-axis-label-spacing))
               Y-axis-label-spacing)))
         (vertical-step (or vertical-step 1))
         (full-Y-label-width
          (length
           (concat
            (number-to-string
             (* height-of-top-line vertical-step))
            Y-axis-tic))))
    (print-Y-axis
     height-of-top-line full-Y-label-width vertical-step)
    (graph-body-print
        numbers-list height-of-top-line symbol-width)
    (print-X-axis numbers-list horizontal-step)))