Kotlin 中 DynamicArray 的自定义 print() 打印意外结果
Custom print() of DynamicArray in Kotlin prints unexpected result
我有一个简单的场景,我有 Kotlin class 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 class 只有:
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, 2, 3, 40, 0, ]
更新
如果我将打印方法更改为:
fun print(): String {
return numArray.contentToString() // using built-in method
}
它仍然打印:
[1, 2, 3, 4, 0, 0]
无法找出导致此问题的原因。
当插入不适合的新项目时,数组的大小会加倍。这意味着内部数组的大小可能比 DynamicArray 的虚拟大小大。
要仅显示 添加的 元素,您应该从 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 = "]")
}
首先,让我们看看如何找出问题所在。
调试技术有很多,但目前为止最有用的一般就是简单地打印内容。为了缩小问题所在的范围,能够在每个点查看程序的 state(在本例中为 DynamicArray 的内容)真的非常有用。
您希望能够添加一行,例如:
println("Point A: $array")
…每次调用 insert()
前后。问题是它只会打印出类似的东西:
Point A: DynamicArray@63947c6b
…这是因为 DynamicArray 没有覆盖 toString()
。您可以改为调用 print()
方法 — 但您不知道错误是否存在。
如果 DynamicArray 是 data class
,您会自动得到一个闪亮的 toString()
实现。但是这个 class 并不真正适合作为数据 class (并且需要很多其他更改)。但是没有什么能阻止你自己写,例如:
override fun toString() = "DynamicArray(count=$count, numArray=[${numArray.joinToString()}])"
有了它,您可以添加大量调试输出。例如:
Start: DynamicArray(count=0, numArray=[0, 0, 0])
Inserted 1: DynamicArray(count=1, numArray=[1, 0, 0])
Inserted 2: DynamicArray(count=2, numArray=[1, 2, 0])
Inserted 3: DynamicArray(count=3, numArray=[1, 2, 3])
Inserted 4: DynamicArray(count=4, numArray=[1, 2, 3, 4, 0, 0])
Inserted 5: DynamicArray(count=5, numArray=[1, 2, 3, 4, 5, 0])
[1, 2, 3, 4, 50, ]
这样一来,问题出在哪里就清楚多了!您可以看到 count
和 numArray
都设置正确。所以问题一定出在你的print()
方法上。
我不打算在这里给出最终的解决方案,因为我认为这对您自己解决剩下的问题会更有帮助;我希望这已经给了你足够的开始去做那件事。 (如果您需要提示,请考虑它打印了多少数字,以及逗号放在哪里。)
即使计数较少,您的打印方法也会遍历所有元素,因此零会附加到打印的字符串。如果索引大于 count
,对代码进行最小更改的简单解决方案是打破循环
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 的更简单代码
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(", ", "[", "]")
}
我有一个简单的场景,我有 Kotlin class 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 class 只有:
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, 2, 3, 40, 0, ]
更新
如果我将打印方法更改为:
fun print(): String {
return numArray.contentToString() // using built-in method
}
它仍然打印:
[1, 2, 3, 4, 0, 0]
无法找出导致此问题的原因。
当插入不适合的新项目时,数组的大小会加倍。这意味着内部数组的大小可能比 DynamicArray 的虚拟大小大。
要仅显示 添加的 元素,您应该从 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 = "]")
}
首先,让我们看看如何找出问题所在。
调试技术有很多,但目前为止最有用的一般就是简单地打印内容。为了缩小问题所在的范围,能够在每个点查看程序的 state(在本例中为 DynamicArray 的内容)真的非常有用。
您希望能够添加一行,例如:
println("Point A: $array")
…每次调用 insert()
前后。问题是它只会打印出类似的东西:
Point A: DynamicArray@63947c6b
…这是因为 DynamicArray 没有覆盖 toString()
。您可以改为调用 print()
方法 — 但您不知道错误是否存在。
如果 DynamicArray 是 data class
,您会自动得到一个闪亮的 toString()
实现。但是这个 class 并不真正适合作为数据 class (并且需要很多其他更改)。但是没有什么能阻止你自己写,例如:
override fun toString() = "DynamicArray(count=$count, numArray=[${numArray.joinToString()}])"
有了它,您可以添加大量调试输出。例如:
Start: DynamicArray(count=0, numArray=[0, 0, 0])
Inserted 1: DynamicArray(count=1, numArray=[1, 0, 0])
Inserted 2: DynamicArray(count=2, numArray=[1, 2, 0])
Inserted 3: DynamicArray(count=3, numArray=[1, 2, 3])
Inserted 4: DynamicArray(count=4, numArray=[1, 2, 3, 4, 0, 0])
Inserted 5: DynamicArray(count=5, numArray=[1, 2, 3, 4, 5, 0])
[1, 2, 3, 4, 50, ]
这样一来,问题出在哪里就清楚多了!您可以看到 count
和 numArray
都设置正确。所以问题一定出在你的print()
方法上。
我不打算在这里给出最终的解决方案,因为我认为这对您自己解决剩下的问题会更有帮助;我希望这已经给了你足够的开始去做那件事。 (如果您需要提示,请考虑它打印了多少数字,以及逗号放在哪里。)
即使计数较少,您的打印方法也会遍历所有元素,因此零会附加到打印的字符串。如果索引大于 count
,对代码进行最小更改的简单解决方案是打破循环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 的更简单代码
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(", ", "[", "]")
}