iOS / C:将“整数”转换为四个string

与audio会话编程相关的许多常量实际上是四个字符的string( audio会话服务参考 )。 从AudioSessionGetProperty函数返回的OSStatus代码 AudioSessionGetProperty

问题是,当我试图打印出这些东西,他们看起来像1919902568.我可以插入到计算器,打开ASCII输出,它会告诉我“roch”,但必须有一个编程方式做这个。

我的一个C函数在下面的块中取得了有限的成功:

 char str[20]; // see if it appears to be a four-character code *(UInt32 *) (str + 1) = CFSwapInt32HostToBig(error); if (isprint(str[1]) && isprint(str[2]) && isprint(str[3]) && isprint(str[4])) { str[0] = str[5] = '\''; str[6] = '\0'; } else { // no, format as integer sprintf(str, "%d", (int)error); } 

我想要做的就是将这个function从当前的function中抽象出来,以便在其他地方使用它。 我试过了

 char * fourCharCode(UInt32 code) { // block } void someOtherFunction(UInt32 foo){ printf("%s\n",fourCharCode(foo)); } 

但是那给了我“à€€/3íT:€€/€€/”,而不是“roch”。 我的C语言function不是很强大,但是我的直觉是上面的代码试图将内存地址解释为一个string。 或者也许有一个编码问题? 有任何想法吗?

你所说的types是在FourCharCode中定义的CFBase.h 。 这相当于一个OSType 。 在OSTypeNSString之间转换最简单的方法是使用NSFileTypeForHFSTypeCode()NSHFSTypeCodeFromFileType() 。 不幸的是,这些function在iOS上不可用。

对于iOS和Cocoa可移植的代码,我喜欢从他的NCCommon.h Joachim Bengtsson的 FourCC2Str() (加上一些简单的清理以方便使用):

 #include <TargetConditionals.h> #if TARGET_RT_BIG_ENDIAN # define FourCC2Str(fourcc) (const char[]){*((char*)&fourcc), *(((char*)&fourcc)+1), *(((char*)&fourcc)+2), *(((char*)&fourcc)+3),0} #else # define FourCC2Str(fourcc) (const char[]){*(((char*)&fourcc)+3), *(((char*)&fourcc)+2), *(((char*)&fourcc)+1), *(((char*)&fourcc)+0),0} #endif FourCharCode code = 'APPL'; NSLog(@"%s", FourCC2Str(code)); NSLog(@"%@", @(FourCC2Str(code)); 

你当然可以将@()放入macros中,以便使用。

整数= 4个字节= 4个字符。 所以要从整数转换为char *,你可以简单地写:

 char st[5]; st[0] = yourInt & 0xff; st[1] = (yourInt >> 8) & 0xff; st[2] = (yourInt >> 16) & 0xff; st[3] = (yourInt >> 24) & 0xff; 

将其转换回来:

 yourInt = st[0] | (st[1] << 8) | (st[2] << 16) | (st[3] << 24); 

在Swift中你可以使用这个函数:

 func str4 (n: Int) -> String { var s: String = "" var i: Int = n for var j: Int = 0; j < 4; ++j { s = String(UnicodeScalar(i & 255)) + s i = i / 256 } return (s) } 

这个函数在三分之一的时间内会像上面那样做:

 func str4 (n: Int) -> String { var s: String = String (UnicodeScalar((n >> 24) & 255)) s.append(UnicodeScalar((n >> 16) & 255)) s.append(UnicodeScalar((n >> 8) & 255)) s.append(UnicodeScalar(n & 255)) return (s) } 

相反的方式将是:

 func val4 (s: String) -> Int { var n: Int = 0 var r: String = "" if (countElements(s) > 4) { r = s.substringToIndex(advance(s.startIndex, 4)) } else { r = s + " " r = r.substringToIndex(advance(r.startIndex, 4)) } for UniCodeChar in r.unicodeScalars { n = (n << 8) + (Int(UniCodeChar.value) & 255) } return (n) } 
 char str[5]; str[4] = '\0'; long *code = (long *)str; *code = 1919902568; printf("%s\n", str); 

我为我的audio代码编写了这个C函数…它可能是一个天真的,但它为我做足够的工作:

 NSString* fourCharNSStringForFourCharCode(FourCharCode aCode){ char fourChar[5] = {(aCode >> 24) & 0xFF, (aCode >> 16) & 0xFF, (aCode >> 8) & 0xFF, aCode & 0xFF, 0}; NSString *fourCharString = [NSString stringWithCString:fourChar encoding:NSUTF8StringEncoding]; return fourCharString; } 

我build议使用这样的function:

 static NSString * NSStringFromCode(UInt32 code) { UInt8 chars[4]; *(UInt32 *)chars = code; for(UInt32 i = 0; i < 4; ++i) { if(!isprint(chars[i])) { return [NSString stringWithFormat:@"%u", code]; } } return [NSString stringWithFormat:@"%c%c%c%c", chars[3], chars[2], chars[1], chars[0]]; } 

这将确保您不会以一些随机结果为实际的数字,如kCMPixelFormat_32ARGB = 32一些FourCharCodes。

工作Swift 2.2版本作为两个扩展:

 extension String { public var fourCharCode:FourCharCode { var string = self if unicodeScalars.count < 4 { string = self + " " } string = string.substringToIndex(string.startIndex.advancedBy(4)) var res:FourCharCode = 0 for unicodeScalar in string.unicodeScalars { res = (res << 8) + (FourCharCode(unicodeScalar) & 255) } return res } } extension FourCharCode { public var string:String { var res = String (UnicodeScalar((self >> 24) & 255)) res.append(UnicodeScalar((self >> 16) & 255)) res.append(UnicodeScalar((self >> 8) & 255)) res.append(UnicodeScalar(self & 255)) return res } } 

如果你正在开发macOS而不是iOS,在启动服务中已经有了一个内置的函数。 要获得4cc作为NSString:

 (__bridge_transfer NSString *)UTCreateStringForOSType(fourccInt) 

更Swifty的实现,为Swift 4工作:

 extension String { init(fourCharCode: FourCharCode) { let n = Int(fourCharCode) var s: String = "" let unicodes = [UnicodeScalar((n >> 24) & 255), UnicodeScalar((n >> 16) & 255), UnicodeScalar((n >> 8) & 255), UnicodeScalar(n & 255)] unicodes.flatMap { (unicode) -> String? in guard let unicode = unicode else { return nil } return String(unicode) }.forEach { (unicode) in s.append(unicode) } self = s.trimmingCharacters(in: CharacterSet.whitespaces) } } 

其中可以使用如下:

 String(fourCharCode: CMFormatDescriptionGetMediaSubType(charCode)) 

这里是jscom代码的Swift 3版本,清理以消除重复:

 func debugPrintFourCcCode(_ value: Int) { var res = "" if value <= 0x28 { res = "\(value)" } else { func add(_ pos: Int) { res.append(String(UnicodeScalar((value >> pos) & 255)!)) } add(24) add(16) add(8) add(0) } NSLog("Code: \(res)") }