在为计算器应用程序设计输入和输出时遇到问题

时间:2010-04-15 14:56:47

标签: model-view-controller calculator

我正在写一个按钮计算器。我将代码拆分为模型,视图和控制器。该模型对格式化一无所知,只关注数字。所有格式都在视图中完成。该模型将其输入作为按键,每个按键都是枚举的一部分:

typedef enum {

    kButtonUnknown        =   0,
    kButtonMemoryClear    = 100,
    kButtonMemoryPlus     = 112,
    kButtonMemoryMinus    = 109,
    kButtonMemoryRecall   = 114,
    kButtonClear          =  99,
    …
};

当用户按下按钮(比如 1 )时,模型会收到一个按钮代码(kButtonNum1),并将相应的数字添加到字符串输入缓冲区("1" )并更新数字输出值(1.0)。然后,控制器将数字输出值传递给格式化它的视图(1)。

这一切都很简单,干净,但并不真正有效。问题是,当用户输入数字的一部分(比如0.00,然后输入0.001)时,输入无法通过模型查看,显示屏显示0而不是0.00。我知道为什么会发生这种情况("0.00"::string解析为0::double并且格式化为0)。我不知道的是如何设计计算器,以便代码保持干净简洁,数字将在用户输入时完全显示在屏幕上。

我已经提供了某种解决方案,但这实际上是一种破解,打破了从计算器模型到显示器的美丽而简单的流程。

想法?


当前解决方案跟踪计算器状态。如果计算器正在构建一个数字,我会使用计算器输入缓冲区(一个字符串)并直接设置显示内容(也是一个字符串)。否则我采取正确的道路,即。取数字计算器输出,将其作为double传递给视图,视图使用其内部格式化程序为显示创建字符串。示例输入:

input | display | mode
------+---------+------------
0     | 0       | from string
0.    | 0.      | from string
0.0   | 0.0     | from string
0.0+  | 0       | from number

这太丑了。 (1)计算器必须暴露其输入缓冲区和状态。 (2)视图必须公开其显示并允许使用字符串直接设置其内容。 (3)我必须复制一些格式化代码来格式化我从计算器输入缓冲区得到的字符串。如果用户输入12345.000,我必须显示12,345.000,因此我必须有字符串的通信代码。呸。

2 个答案:

答案 0 :(得分:1)

在我的计算器(HP48SX)上,显示屏中的数字将根据显示数字的设置进行格式化。现在,如果我输入0.00(或其任何变体),它将显示为0.0000。也许您可以将显示(即格式化)与内部数字表示分开?就MVC而言,我猜这将在C中实现为状态。

编辑回应OP的评论。我不完全理解你所谓的按钮计算器的局限性,所以你自己就在那里。至于分离,我会设计计算器:

  • 模型总是使用你用于表示数字的任何东西:浮点数,双精度数,小数数,你有什么。
  • View始终使用字符串,它可以很好地显示数字,并允许用户按照自己的意愿输入。
  • Controller将字符串转换为数字,从数字转换为字符串。在我最初的建议中,我设想控制器本身是有状态的(例如存储当前数字格式)并且可以从按钮寻址。但你似乎已经排除了这一点。

你的问题,就像我看到的那样,如果你不在某个地方存储这个状态,那么你无法告诉计算器使用除固定*格式之外的任何东西来显示输入的任何数字。固定*我指的是一种非常有限的灵活性,例如始终显示最近输入的数字中的小数位数,而不是绝对固定的数字,例如12位数,不多也不少。

答案 1 :(得分:0)

最后我发现了一个更好的解决方案。我在formatter对象中添加了一个inputHint属性,用于处理视图中的输出格式。此输入提示接收计算器输入缓冲区的值并影响格式。如果输入提示中有一个小数点,则格式化程序必须始终在输出中保留小数点,因此解决了"0."格式为"0"的情况。如果输入包含一些小数位,则格式化程序被强制在输出中保持相同数量的小数位(解决"0.00"格式为"0"的情况)。

我仍然需要公开计算器输入缓冲区和状态,但是我不必将视图的显示作为字符串公开,也不必为字符串维护重复的格式化代码路径。