【问题标题】:Class and methods to trim string not even starting修剪字符串的类和方法甚至没有开始
【发布时间】:2019-10-01 00:32:33
【问题描述】:

我正在尝试创建一个具有字符串修剪功能的类:

Object subclass: Trimmer [
    trimleading: str [ |ch ret|
        ch := (str first: 1).           "get first character"
        ret := str.                     "make a copy of sent string"
        [ch = ' '] whileTrue: [         "while first char is space"
            ret := (ret copyFrom: 2).   "copy from 2nd char"
            ch := ret first: 1.         "again test first char"
            ].
        ^ret                            "return value is modified string"
        ].
    trim: str [ |ret|
        ret := str. 
        ret := (trimleading value: ret).           "trim leading spaces"
        ret := (trimleading value: (ret reverse)). "reverse string and repeat trim leading"
        ^(ret reverse)                             "return reverse string"
        ]
].

oristr := '        this is a test  '
('ORI..>>',oristr,'<<') displayNl.
('FINAL>>',((Trimmer new) trim: oristr),'<<') displayNl.

但是,它没有运行并给出以下错误:

$ gst trimstring_class.st

trimstring_class.st:10: invalid class body element
trimstring_class.st:17: expected expression

问题出在哪里,如何解决?

如果我在 trimleading 方法块之后删除 .,如下代码所示:

Object subclass: Trimmer [
    trimleading: str [ |ch ret flag|
        ret := str.                     "make a copy of sent string"
        flag := true.
        [flag] whileTrue: [         "while first char is space"
            ch := ret first: 1.         "again test first char"
            ch = ' '
            ifTrue: [ ret := (ret copyFrom: 2 to: ret size)]    "copy from 2nd char"
            ifFalse: [flag := false] 
            ].
        ^ret                                "value is modified string"
        ]     "<<<<<<< PERIOD/DOT REMOVED FROM HERE."
    trim: str [ |ret|
        ret := str. 
        ret := (trimleading value: ret).           "trim leading spaces"
        ret := (trimleading value: (ret reverse)). "reverse string and repeat trim leading"
        ^(ret reverse)                      "return reverse string"
        ]
].

然后代码开始运行但停止并出现以下错误:

$ gst trimstring_class.st 
trimstring_class.st:15: undefined variable trimleading referenced
ORI..>>        this is a test  <<
Object: Trimmer new "<0x7f1c787b4750>" error: did not understand #trim:
MessageNotUnderstood(Exception)>>signal (ExcHandling.st:254)
Trimmer(Object)>>doesNotUnderstand: #trim: (SysExcept.st:1448)
UndefinedObject>>executeStatements (trimstring_class.st:23)

为什么 trimleading 方法现在未定义以及为什么 gnu-smalltalk did not understand #trim:

【问题讨论】:

  • 试试(ret := str copyFrom: 2 to: str size)
  • 它不起作用。同样的错误仍然存​​在。

标签: class oop smalltalk gnu-smalltalk


【解决方案1】:

通常,对于此类常见用例,检查此类功能是否已实现是明智之举。您可以从中获得灵感来编写您的代码(作为 Smalltalk 程序员,您也会有所进步)。从sports.sttrimBlanksFrom:

 SpStringUtilities class >> trimBlanksFrom: aString [
    "^a String
     I return a copy of aString with all leading and trailing blanks removed."

    <category: 'services'>
    | first last |
    first := 1.
    last := aString size.
    [last > 0 and: [(aString at: last) isSeparator]] 
        whileTrue: [last := last - 1].
    ^last == 0 
        ifTrue: [String new]
        ifFalse: [
            [first < last and: [(aString at: first) isSeparator]] 
                whileTrue: [first := first + 1].
            aString copyFrom: first to: last
       ]
]

如果您只想修剪前导空格,您可以只使用第二部分,即修剪前导空格。

编辑 OP 自己的代码应用了修复:

Object subclass: Trimmer [
    trimleading: str [ |ch ret flag|
        ret := str.                     "make a copy of sent string"
        flag := true.
        [flag] whileTrue: [         "while first char is space"
            ch := ret first: 1.         "again test first char"
            ch = ' '
            ifTrue: [ ret := (ret copyFrom: 2 to: ret size) ]    "copy from 2nd char"
            ifFalse:  [flag := false ] 
            ].
        ^ret                                "value is modified string"
        ]     "<<<<<<< PERIOD/DOT REMOVED FROM HERE."
    trim: str [ |ret|
        ret := str. 
        ret := self trimleading: (ret copy).           "trim leading spaces"
        ret := self trimleading: (ret copy reverse). "reverse string and repeat trim leading"
        ^ (ret reverse)                      "return reverse string"
        ]
].

oristr := '        this is a test  '
('ORI..>>',oristr,'<<') displayNl.
('FINAL>>',((Trimmer new) trim: oristr),'<<') displayNl.

有一些错误需要修正。如果要寻址选择器#trimleading:,则必须使用self 关键字来搜索本地类(对于自己的类或继承的类)。接下来,您不应更改分配给您的变量,应使用 #copy 否则可能会出现奇怪的结果。

【讨论】:

  • 我有兴趣在我的代码中发现错误。我的代码有什么错误,如何纠正?
  • 是的,它有效。需要使用self trimleading。我已经将str 复制到ret。代码无需每次都使用(ret copy) 即可工作。这里真的需要吗?
  • @rnso 对于您的特定代码,您自己复制它时不需要它,但您应该熟悉,这就是我使用它的原因,copy(通常是浅拷贝)和deepCopy。使用时更容易阅读和理解。
猜你喜欢
  • 1970-01-01
  • 2017-10-08
  • 2023-04-10
  • 2021-06-18
  • 1970-01-01
  • 1970-01-01
  • 2022-01-21
  • 1970-01-01
  • 2016-01-25
相关资源
最近更新 更多