问题描述
我有一个简单的场景,我有 Kotlin 类 DynamicArray.kt:
class DynamicArray(size: Int) {
private var numArray: IntArray
private var count: Int = 0
init {
if (size <= 0)
throw IllegalArgumentException("Invalid value for array size")
numArray = IntArray(size)
}
fun insert(item: Int) {
if (numArray.size == count){
// Create newArray with double size
val newArray = IntArray(count * 2)
// copy old to new
for ((index,i) in numArray.withIndex()){
newArray[index] = i
}
// assign newArray to old
numArray = newArray
}
numArray[count++] = item
}
fun print(): String {
val arrayAsstring = StringBuilder()
arrayAsstring.append("[")
for ((index,i) in numArray.withIndex()){
arrayAsstring.append(i)
if (index != (count - 1)){
arrayAsstring.append(",")
}
}
arrayAsstring.append("]")
return arrayAsstring.toString()
}
}
还有一个简单的 Main.kt 类,它只有:
fun main(args: Array<String>) {
val array = DynamicArray(3)
array.insert(1)
array.insert(2)
array.insert(3)
println(array.print())
}
当 DynamicArray 的 size
和 items
相等时,上面的代码完美运行
[1,2,3]
但是当我们插入更多项目时,初始大小例如:
fun main(args: Array<String>) {
val array = DynamicArray(3)
array.insert(1)
array.insert(2)
array.insert(3)
array.insert(4)
println(array.print())
}
它打印出奇怪的值,例如:
[1,3,40,]
更新
如果我将打印方法更改为:
fun print(): String {
return numArray.contentToString() // using built-in method
}
它仍然打印:
[1,4,0]
无法找出导致此问题的原因。
解决方法
首先,让我们看看如何找出问题所在。
调试的技术有很多,但到目前为止最有用的就是简单地打印出来。为了缩小问题的范围,能够在每个点查看程序的状态(在本例中为 DynamicArray 的内容)真的非常有用。
您希望能够做的是添加一行,例如:
println("Point A: $array")
...在每次调用 insert()
之前和之后。麻烦的是,它只是打印如下内容:
Point A: DynamicArray@63947c6b
...这是因为 DynamicArray 不会覆盖 toString()
。您可以改为调用您的 print()
方法 - 但您不知道错误是否在那里。
如果 DynamicArray 是 data class
,您将自动获得闪亮的 toString()
实现。但是这个类并不适合作为数据类(并且需要很多其他更改)。但是没有什么能阻止你自己写,例如:
override fun toString() = "DynamicArray(count=$count,numArray=[${numArray.joinToString()}])"
有了它,您就可以添加大量调试输出。例如:
Start: DynamicArray(count=0,numArray=[0,0])
Inserted 1: DynamicArray(count=1,numArray=[1,0])
Inserted 2: DynamicArray(count=2,2,0])
Inserted 3: DynamicArray(count=3,3])
Inserted 4: DynamicArray(count=4,3,4,0])
Inserted 5: DynamicArray(count=5,5,0])
[1,50,]
由此,问题出在哪里变得更加清晰了!您可以看到 count
和 numArray
都设置正确。所以问题一定出在您的 print()
方法中。
我不会在这里给出最终的解决方案,因为我认为它会帮助你更多地自己解决其余的问题;我希望这已经给了你足够的开始来做到这一点。 (如果你想要一个提示,请考虑它打印了多少个数字,以及它把逗号放在哪里。)
,当插入不适合的新项目时,数组的大小加倍。这意味着内部数组的大小可能大于动态数组的虚拟大小。
要仅显示添加的元素,您应该从 0 到 count
迭代,而不是迭代整个数组。
手动追加的示例:
fun print(): String {
val builder = StringBuilder()
// Iterate over *inserted* indices only
for (i in 0 until count) {
if (builder.isNotEmpty()) {
builder.append(",")
}
builder.append(numArray[i])
}
builder.insert(0,"[")
builder.append("]")
return builder.toString()
}
使用内置函数的替代方法:(这会创建一个中间列表)
fun print(): String {
// get a List of added elements
val content = numArray.take(count)
// convert the list to a string
return content.joinToString(prefix = "[",postfix = "]")
}
,
即使计数较少,您的打印方法也会迭代所有元素,因此在打印字符串后附加零。对代码进行最少更改的简单解决方案是,如果索引大于计数,则中断循环
fun print(): String {
val arrayAsString = StringBuilder()
arrayAsString.append("[")
for ((index,i) in numArray.withIndex()){
if(index>=count) break; // NEW condition
arrayAsString.append(i)
if (index != (count - 1)){
arrayAsString.append(",")
}
}
arrayAsString.append("]")
return arrayAsString.toString()
}
这是使用 Kotlin 内置功能的 DynamicArray
类的更简单代码
class DynamicArray(size: Int) {
private var numArray: IntArray
private var count: Int = 0
init {
require(size>0) { "Invalid value for array size" }
numArray = IntArray(size)
}
fun insert(item: Int) {
if (numArray.size == count) {
numArray = numArray.copyInto(IntArray(count * 2))
}
numArray[count++] = item
}
fun print() = numArray.take(count).joinToString(",","[","]")
}