背景。我正在使用netlists,一般来说,人们使用/
指定不同的层次结构。但是,实际使用/
作为实例名称的一部分并不违法。
例如,X1/X2/X3/X4
可能在另一个名为X4
的实例中引用实例X1/X2/X3
。或者它可能在名为X3/X4
的实例中的名为X2
的实例中引用名为X1
的实例。知道了吗?
实际上没有“常规”字符不能用作实例名称的一部分,因此您使用不可打印的字符,或者......可能是标准0之外的字符.127 ASCII字符。
我以为我会尝试(十进制)166,因为对我来说它显示为管道:¦
。
所以......我有一些C ++代码使用¦
构建路径名作为分层分隔符,因此上面的路径看起来像X1¦X2/X3¦X4
。
现在GUI是用Tcl / Tk编写的,为了正确地将其翻译成人类可读的术语,我需要做以下的事情:
set path [getPathFromC++] ;# returns X1¦X2/X3¦X4
set humanreadable [join [split $path ¦] /]
基本上,将¦
替换为/
(我也可以使用[string map]
完成此操作。)
现在问题是,我从C ++获得的字符串中的¦
与我在Tcl中创建的¦
不匹配。即失败:
set path [getPathFromC++] ;# returns X1¦X2/X3¦X4
string match $path [format X1%cX2/X3%cX4 166 166]
在视觉上,两个字符串看起来相同,但字符串匹配失败。我甚至尝试使用scan来查看我是否混淆了比特值。但
set path [getPathFromC++] ;# returns X1¦X2/X3¦X4
set path2 [format X1%cX2/X3%cX4 166 166]
for {set i 0} {$i < [string length $path]} {incr i} {
set p [string range $path $i $i]
set p2 [string range $path2 $i $i]
scan %c $p c
scan %c $p2 c2
puts [list $p $c :::: $p2 $c2 equal? [string equal $c $c2]]
}
生成看起来的输出,就像所有内容都应该匹配一样,除了[string equal]
对于带打印行的¦
个字符失败:
¦ 166 :::: ¦ 166 equal? 0
对于它的价值,C ++中的字符定义为:
const char SEPARATOR = 166;
为什么常规ASCII范围之外的字符会像这样失败?当我将分隔符更改为(十进制)28(^\
)时,一切正常。我只是不想在不同的平台上遇到类似的问题。 (我目前正在使用Redhat Linux。)
答案 0 :(得分:6)
答案 1 :(得分:4)
在我的系统上,tcl脚本puts [format %c 166]
以UTF-8(“\ xC2 \ xA6”)输出,而C ++语句cout << "\xA6";
输出Latin-1。确保编码差异不会让你失望。
答案 2 :(得分:4)
据我了解,现代版本的TCL在内部使用UTF-8进行字符串表示。在UTF-8中,十进制166是一个字符的一半,所以毫无疑问,所有的地狱都在破碎。 ; - )
我的猜测是你的C ++代码正在使用Latin-1字符串(即char *
)并且你将它传递给TCL,TCL将其解释为UTF-8字符串。在将C ++字符串传递给任何TCL C函数之前,需要将其转换为UTF-8。 TCL提供some functions for this purpose。
您可以阅读有关TCL and UTF-8的更多信息。