字符串子无法正常工作

String sub not working correctly

我还有一个关于 lua 的问题。我创建了一种方法来计算某些价格的总额。价格采用​​这种格式:500 英镑。因此,为了将它们转换为数字,我使用了 string:sub() 和 tonumber(),但我得到了一些奇怪的结果。这是我的代码:`

function functions.calculateTotalAmount()
print("calculating total amount")
saveData.totalAmount = 0
print("There are " .. #saveData.amounts .. " in the amount file")
for i=1, #saveData.names do
    print("SaveData.amounts[" .. i .. "] original = " .. saveData.amounts[i])
    print("SaveData.amounts[" .. i .. "]  after sub= " .. saveData.amounts[i]:sub(2))
    print("totalAmount: " .. saveData.totalAmount)
    if saveData.income[i] then
        saveData.totalAmount = saveData.totalAmount + tonumber(saveData.amounts[i]:sub(2))
    else
        saveData.totalAmount = saveData.totalAmount - tonumber(saveData.amounts[i]:sub(2))
    end
end
totalAmountStr.text = saveData.totalAmount .. " " .. currencyFull
loadsave.saveTable(saveData, "payMeBackTable.json")

结束

我在 for 循环中打印了一些信息以确定问题,这是 for 循环中前 2 个打印语句打印的内容:

16:03:51.452 SaveData.amounts1原=¥201

16:03:51.452 SaveData.amounts1 在 sub= 201

之后

它在 Whosebug 中看起来不错,但 ¥ 实际上并没有在我的日志中消失,而是被一个奇怪的矩形符号代替。此 post 将附有打印文本的图片。 有人看到这里发生了什么吗?

string.sub() 作用于字符串的 字节 ,而不作用于它的 个字符 。当字符串包含 Unicode 文本时会有所不同。

如果数字在字符串的末尾,用

提取它
amount = tonumber(saveData.amounts[i]:match("%d+$"))

在这种情况下不要使用 sub,因为 ¥ 符号可能是一个多字节序列(取决于编码),因此使用 sub(2) 就是在切割它在中间而不是删除它。

改为使用 gsub("[^%d%.]+","") 删除所有非数字部分。

Lua 字符串是 字节 的字符串,而不是 字符 的字符串。 ASCII 字符长度为 1 个字节,但大多数其他字符占用多个字节,因此使用 string.sub() 是行不通的。

字节字符(或代码点)之间的转换有多种标准,但到目前为止,网络上最常见的是 UTF-8。如果您使用的是 Lua 5.3 或更高版本,则可以使用新的 built-in functions 来执行 UTF-8 操作。例如,要获取 UTF-8 字符串的子字符串,您可以这样做:

-- Simple version without bounds-checking.
function utf8_sub1(s, start_char_idx, end_char_idx)
  start_byte_idx = utf8.offset(s, start_char_idx)
  end_byte_idx = utf8.offset(s, end_char_idx + 1) - 1
  return string.sub(s, start_byte_idx, end_byte_idx)
end

-- More robust version with bounds-checking.
function utf8_sub2(s, start_char_idx, end_char_idx)
  start_byte_idx = utf8.offset(s, start_char_idx)
  end_byte_idx = utf8.offset(s, end_char_idx + 1)
  if start_byte_idx == nil then
    start_byte_idx = 1
  end
  if end_byte_idx == nil then
    end_byte_idx = -1
  else
    end_byte_idx = end_byte_idx - 1
  end
  return string.sub(s, start_byte_idx, end_byte_idx)
end

s = "¥201"

print(string.sub(s, 2, 4)) -- an invalid byte sequence
print(utf8_sub1(s, 2, 4)) -- "201"
print(utf8_sub2(s, 2, 4)) -- "201"
print(utf8_sub1(s, 2, 5)) -- throws an error

如果您没有 Lua 5.3,您可以使用像 this one 这样的 UTF-8 库来实现相同的功能。