【问题标题】:Smalltalk Input/OutputSmalltalk 输入/输出
【发布时间】:2015-04-12 00:37:43
【问题描述】:

我在 Smalltalk 方面遇到了麻烦。我试图用从文件中读取的数字填充一个数组,但它似乎不起作用。我尝试了很多选择,我希望有人能向我解释我做错了什么。

 Object subclass: #MyStack
        instanceVariableNames:'anArray aStack'
        classVariableNames:''
        poolDictionaries:''

!
MyStack class comment: 'Creates a Stack Class.'
!

!
MyStack methodsFor: 'initialize Stack'
!

new "instance creation"
        ^ super new.
!
init "initialization"
        anArray := Array new: 32.
        aStack := 0.
! !

!MyStack methodsFor: 'methods for stacks' !


pop "Removes the top entry from the stack"
    | item |
    item := anArray at: aStack.
    aStack := aStack - 1.
!

push: x "Pushes a new entry onto the stack"
    aStack := aStack + 1.
    anArray at:aStack put:x.
!

top "Returns the current top of the stack"
        ^anArray at: aStack.
!

empty "True if the stack is empty"
        ^aStack = 0.
!

full "True if the stack is full"
        ^aStack = 32.
!

printOn: aStream "Prints entire stack one entry per line, starting the top entry"
    aStream show: 'Stack:'.
    aStack to:1 by:-1 do:[:i |(anArray at:i) printOn:aStream. ].
    aStream show: ''
! !
"----------------------------------------------------------------------------------"
Object subclass: #IOExample
  instanceVariableNames: 'input output'
  classVariableNames: ''
  poolDictionaries: ''
!
IOExample class comment: '
 basic I/O.
'
!

!
IOExample methodsFor: 'initialize'
!
new
  ^ super new.

!
init
  [ input := FileSelectionBrowser open asFilename readStream. ]
    on: Error
    do: [ :exception |
      Dialog warn: 'Unable to open file'.
      exception retry.
    ].
  [ output := FileSelectionBrowser open asFilename writeStream. ]
    on: Error
    do: [ :exception |
      Dialog warn: 'Unable to open file'.
      exception retry.
    ].

! !

!
IOExample methodsFor: 'copy input to output turning :: into :'
!
copy
  | data lookAhead theStack myStack|
  [ input atEnd ] whileFalse: [

    data := input next.
    (data isKindOf: Integer)
      ifTrue: [
        (input atEnd) ifFalse: [
        "myStack push: data."
        lookAhead = input peek.
        (lookAhead asCharacter isDigit)
            ifTrue: [
            ]              
        ].
      ].  
    output show: myStack.



  ].
  input close.
  output close.
! !

【问题讨论】:

  • 一些事情:1)请指定您使用的是哪种 Smalltalk 方言(我试图将您的代码归档到Pharo,它没有#subclass:instanceVariableNames:classVariableNames:poolDictionaries: 2)这不是常见的做法以块格式共享代码。它很难阅读,需要有人复制/粘贴到文本文件中才能加载 3)您没有提供有关输入文件的详细信息

标签: smalltalk


【解决方案1】:

您是否尝试运行此代码?如果您这样做了,我很惊讶您没有收到以下 #2 的编译警告。

#copy 有很多问题(除了我不明白它到底想做什么)...

  1. 首先,您似乎希望数据是数字:data isKindOf: Integer。但后来您将其视为字符流:lookAhead asCharacter isDigit。如果第一个条件为真以使您超过该点,则第二个条件永远不可能,因为您将匹配 [0-9],这不是数字的 ASCII 值。
  2. lookAhead = input peek。在这里,您将未初始化的 lookAhead (nil) 与偷看的值进行比较,然后丢弃结果。我猜你的意思是lookAhead := input peek
  3. 然后是空的内部条件ifTrue: [ ]。你想在那里做什么?
  4. 然后是奇怪的协议名称,“将输入复制到输出,将 :: 变为 :”。这是什么意思,这与在流之间复制数字有什么关系?

【讨论】:

  • 谢谢。我知道我提供的信息不是很丰富,但我已经解决了我提出的问题。
【解决方案2】:

贾斯汀,让我尝试在 MyStack 的课程上帮助您,并根据您的示例中的任何 cmets 推迟另一个答案。

我已将您的代码分成片段并附加了我的 cmets。


片段 A:

Object subclass: #MyStack
    instanceVariableNames:'anArray aStack'
    classVariableNames:''
    poolDictionaries:''

A 的评论:

Smalltalker 会使用实例变量名称而没有不确定的文章 aan

Object subclass: #MyStack
    instanceVariableNames:'array stack'
    classVariableNames:''
    poolDictionaries:''

片段 B:

MyStack class comment: 'Creates a Stack Class.'

对 B 的评论:

这很奇怪。我本来会期待这个(没有class):

MyStack comment: 'Creates a Stack Class.'

片段 C:

MyStack methodsFor: 'initialize Stack'

new "instance creation"
    ^ super new.

对 C:* 的评论

这段代码将new 放在类的实例端,这没有任何意义,因为您通常将new 发送到类而不是它的实例。正确的形式需要加class

MyStack class methodsFor: 'initialize Stack'

new
    ^super new.

您忘记发送初始化方法(但是,请参阅下面的片段 D)

new
    ^super new init.

片段 D:

init "initialization"
    anArray := Array new: 32.
    aStack := 0.

D 的评论:

在 Smalltalk 中人们使用选择器 initialize 以便它可以先发送 super

initialize
    super initialize.
    array := Array new: 32.
    stack := 0.

请注意,此更改还需要将 new 写为

new
    ^super new initialize.

但是,如果您的方言已经默认发送initialize 方法,您应该从您的类中删除new 的实现。


片段 E:

pop "Removes the top entry from the stack"
    | item |
    item := anArray at: aStack.
    aStack := aStack - 1.

对 E 的评论:

你忘了回答刚刚弹出的item

pop
    | item |
    item := array at: stack.
    stack := stack - 1.
    ^item

片段 F:

push: x "Pushes a new entry onto the stack"
    aStack := aStack + 1.
    anArray at:aStack put:x.

对 F 的评论:

没关系。但是请注意,堆栈将拒绝推送任何超过 32 限制的项目。

push: x
    stack := stack + 1.
    array at: stack put: x.

片段 G:

top "Returns the current top of the stack"
    ^anArray at: aStack.

empty "True if the stack is empty"
    ^aStack = 0.

full "True if the stack is full"
    ^aStack = 32.

对 G 的评论:

这些也可以。但是,empty 更合适的名称应该是 isEmpty,因为所有集合都理解这个多态消息。同样,full 的推荐选择器将是 isFull

top
    ^array at: aStack.

isEmpty
    ^stack = 0.

isFull
    ^stack = 32.

另请注意,isFull 重复了您在初始化代码中使用的魔法常数 32。这不是一个好主意,因为如果您将来改变主意并决定将 32 更改为 64,您将不得不修改两种方法,而不仅仅是一种。您可以通过这种方式消除这种重复

isFull
    ^stack = array size.

片段 H:

printOn: aStream
    "Prints entire stack one entry per line, starting the top entry"
    aStream show: 'Stack:'.
    aStack to:1 by:-1 do:[:i |(anArray at:i) printOn:aStream. ].
    aStream show: ''

对 H 的评论:

这段代码的最后一行是多余的,我会去掉它。但是,您可能希望用空格将每个项目与下一个项目分开

printOn: aStream
    stream show: 'Stack:'.
    stack to: 1 by: -1 do:[:i |
        aStream space.
        (array at: i) printOn: aStream].

【讨论】:

  • 非常感谢,内容非常丰富。但是,由于给我的指导方针,我选择的名称是强制性的。
  • @JustinB123 没问题。你可以使用给你的名字。请记住,这些名称不是 Smalltalker 会使用的名称。实际上,ivar stack 也具有误导性,因为该变量会跟踪堆栈顶部的位置,并且应该命名为 top
  • 我遇到了一个问题,但我之前已经解决了。我害怕将整个代码发布在互联网上,因为它最终会成为一个等级。有什么办法可以私下向您展示我的代码吗?问题与添加有理数有关,Smalltalk 的方言是 SmallTalk/X。当我试图找到两个数字的余数(两者的分母都是 1)时,它说它不理解余数运算。我不确定为什么会出现问题,而我的同事也没有。 @Leandro Caniglia
  • @JustinB123 尝试隔离不适合您的代码段并将其粘贴到 StackOverflow 的新问题中。请记住将其标记为 Smalltalk 并提及您正在使用 Smalltalk/X(顺便说一句,它是带有小写 t 的 Smalltalk)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-25
  • 1970-01-01
  • 2016-05-28
  • 1970-01-01
  • 2017-05-12
相关资源
最近更新 更多