3

请考虑以下代码:

NSString *string = @"ä";
const char *str1 = [string cStringUsingEncoding:NSUTF8StringEncoding];
const char *str2 = "ä";
NSLog(@"C string comparison: %d",strcmp(str1,str2));
NSLog(@"str1: \"%s\"", str1);
NSLog(@"str2: \"%s\"", str2);

如果从一个全新的 Foundation 项目运行,该程序会输出:

C string comparison: 0
str1: "ä"
str2: "ä"

这确实是我期望发生的,因为字符串应该是相同的。

但是,如果我在另一个代码库的某个深处运行完全相同的代码,我会得到以下输出:

C string comparison: 31
str1: "ä"
str2: "ä"

什么可以解释这种差异?我很确定这两个文件都采用 UTF-8 编码。那——不同的文件编码——是这种行为的唯一可能解释,对吧?

任何想法在第二种情况下可能出了什么问题?我该如何解决?

(我可能应该提一下,在第二种情况下,代码在.mm文件中运行,即在 Objective-C++ 下。这可以解释吗?)

4

3 回答 3

2

您可以尝试使用字符的 unicode 版本吗?

IE

NSString * string1 = @"\u00e4" ;

参看。http://blog.ablepear.com/2010/07/objective-c-tuesdays-unicode-string.html

于 2012-05-21T22:20:21.413 回答
0

源文件如何在磁盘上编码是一回事。编译器如何认为它被编码是另一回事。默认情况下,GCC 假定为 UTF-8,但可以从语言环境或-finput-charset=<charset>选项中告知它是另一种编码。我希望 Clang 支持同样的事情。

Xcode 有自己的源文件编码概念。我不知道它是否会调整编译命令以使用上述选项传递它,但我不会感到惊讶。

GCC 也有执行字符集的概念。这就是它将字符串写入二进制文件的方式。查看-fexec-charset=<charset>选项。

因此,编译器根据输入字符集解释文件的字节,并将它们写到执行字符集中的二进制文件中。如果这两者不同,那么这涉及转换。这是每个翻译单元的事情,因此对于不同的源文件可能会发生不同的情况。

另一个问题是“ä”在 Unicode 中有两种可能的表示形式。它可以是带分音符号的拉丁文小写字母 A (U+00E4),也可以是拉丁文小写字母 A (U+0061) 后跟分音符号组合 (U+0308)。在 UTF-8 中,这将是 0xC3 0xA4 与 0x61 0xCC 0x88。您的两个源文件可能会以不同的方式表达相同的字符,这意味着它们确实包含不同的字符串(在所有级别:C 字符串NSString,等等,尽管如果未指定,NSString将忽略方法的差异;尽管方法会进行文字比较)。当然,如果这两个字节序列以不同的方式在编码之间进行转换,这种情况会更加严重。-compare:...NSLiteralSearch-isEqual...

因此,您需要追踪包含相关字符串的特定源文件。使用十六进制转储准确检查它们包含哪些字节。检查用于编译它们的命令(如果语言环境可能起作用,可能还有环境)以查看编译器对输入和可执行字符集的看法。

于 2012-05-21T23:01:33.063 回答
0

文档

保证返回的 C 字符串仅在接收器被释放或当前自动释放池被清空之前有效,以先发生者为准。

我认为在你的情况下,要么接收器被释放,要么当前的自动释放池被清空。
例如

NSString *string = @"ä";
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
const char *str3 = [string cStringUsingEncoding:NSUTF8StringEncoding];
[pool release];
NSLog(@"str1: \"%s\"", str3);
const char *str2 = "ä";
NSLog(@"C string comparison: %d",strcmp(str3,str2));
NSLog(@"str2: \"%s\"", str2);  

输出是

2012-05-22 17:14:50.069 test[32895:a0f] str1: "ä"
2012-05-22 17:14:50.071 test[32895:a0f] C string comparison: -195
2012-05-22 17:14:50.074 test[32895:a0f] str2: "ä" 



NSString *string = @"ä";
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
const char *str3 = [string cStringUsingEncoding:NSUTF8StringEncoding];
[pool release];
const char *str2 = "ä";
NSLog(@"C string comparison: %d",strcmp(str3,str2));
NSLog(@"str1: \"%s\"", str3);
NSLog(@"str2: \"%s\"", str2);

输出是

2012-05-22 17:19:13.226 test[33153:a0f] C string comparison: 0
2012-05-22 17:19:13.228 test[33153:a0f] str1: ""
2012-05-22 17:19:13.229 test[33153:a0f] str2: "ä"
于 2012-05-22T11:50:35.530 回答