注意:这个问题是由这个话语线索引起的。
考虑以下示例字符串:
str = "This is some text that initially consists of normal ASCII characters—but oh wait, the em-dash is only part of the extended ASCII character set!"
Run Code Online (Sandbox Code Playgroud)
尝试使用其长度遍历此字符串:
for i in 1:length(str)
println(i, str[i])
end
Run Code Online (Sandbox Code Playgroud)
失败StringIndexError,返回循环中途返回以下消息:
ERROR: StringIndexError("This is some text that initially consists of normal ASCII characters—but oh wait, the em-dash is only part of the extended ASCII character set!", 70)
Stacktrace:
[1] string_index_err(::String, ::Int64) at ./strings/string.jl:12
[2] getindex_continued(::String, ::Int64, ::UInt32) at ./strings/string.jl:217
[3] getindex(::String, ::Int64) at ./strings/string.jl:210
[4] top-level scope at ./REPL[4]:2
Run Code Online (Sandbox Code Playgroud)
这种行为的确切原因是什么?
Julia中的字符串完全支持Unicode字符的UTF-8编码标准。但是,这取决于字符,使单个字符的编码大小可变。
标准ASCII字符(代码点少于128个)使用一个字节,并在迭代过程中产生预期的行为。但是,由于破折号—是扩展ASCII字符集的一部分,因此在尝试使用统一步长进行索引时会产生错误。有关字符串及其行为的更多信息,请参见文档(特别是“ Unicode和UTF-8”部分)。
编辑:正如Stefan在评论中提到的那样,请注意length(str)以预期的方式运行并返回字符串中的实际字符数。最后一个索引位置可以通过检索lastindex(str)。
可以通过多种方式来避免此错误,具体取决于所需的行为:
选项1:直接迭代字符串元素
如果索引不相关,这是最简单的方法:
for c in str
println(c)
end
Run Code Online (Sandbox Code Playgroud)
选项2:使用eachindex提取正确的字符串指数
如果字符串中的实际索引位置是相关的,一个可以这样做:
for bi in eachindex(str)
println(bi, str[bi])
end
Run Code Online (Sandbox Code Playgroud)
方案3:使用enumerate获得线性索引位置和角色
如果“字符”指数(即指数/当前字符数,不是它的字节索引)到字符串和相应的字符是相关的:
for (ci, c) in enumerate(str)
println(ci, c)
end
Run Code Online (Sandbox Code Playgroud)
编辑2:添加了一个小示例来澄清。以字符串str = "a ? x ? y"为例。
选项1返回:
julia> for c in str; print(c, " | "); end
a | | ? | | x | | ? | | y |
Run Code Online (Sandbox Code Playgroud)
选项2返回:
julia> for bi in eachindex(str); print(bi, " ", str[bi], " | "); end
1 a | 2 | 3 ? | 6 | 7 x | 8 | 9 ? | 12 | 13 y |
Run Code Online (Sandbox Code Playgroud)
注意,例如从3-> 6的跳跃
选项3返回:
julia> for (ci, c) in enumerate(str); print(ci, " ", c, " | "); end
1 a | 2 | 3 ? | 4 | 5 x | 6 | 7 ? | 8 | 9 y |
Run Code Online (Sandbox Code Playgroud)