2013-01-08 45 views
10

許多與音頻會話編程相關的常量實際上都是四字符字符串(Audio Session Services Reference)。從AudioSessionGetProperty等函數返回的OSStatus code同樣適用。iOS/C:將「整數」轉換爲四個字符串

問題是,當我試圖打印這些東西時,他們看起來像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); 
} 

我想要做的是抽象的這項功能擺脫目前的功能,以便在其他地方使用它。我試着做

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

但是這給了我 「A *€/3íT:E *€/ +€/」,而不是 「蓉城」。我的C語言功能不是很強大,但我的預感是上面的代碼試圖將內存地址解釋爲一個字符串。或者也許有一個編碼問題?有任何想法嗎?

回答

14

你在談論的類型是FourCharCode,在CFBase.h定義。這相當於一個OSType。在OSTypeNSString之間轉換的最簡單方法是使用NSFileTypeForHFSTypeCode()NSHFSTypeCodeFromFileType()。不幸的是,這些功能在iOS上不可用。

對於iOS和Cocoa移植的代碼,我喜歡Joachim Bengtsson'sFourCC2Str()從他NCCommon.h(加上易於使用的小鑄件清理):

#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)); 

你當然可以扔@()到宏更容易使用。

+0

哦,這聽起來很有用。雖然它給了我一個錯誤「預期的表達」,但我必須回到這個問題。 –

+0

清理起來使它更容易使用。它返回一個char []而不是char *,這似乎混淆了現在的事情。 –

+0

非常好,謝謝! –

3
char str[5]; 
str[4] = '\0'; 
long *code = (long *)str; 
*code = 1919902568; 
printf("%s\n", str); 
+0

搞清楚一個reverseStr功能後,這個工程。我真的很想得到一個DRYer解決方案(就像將它包裝在一個方法中一樣),但它現在就可以使用。 –

5

整數= 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); 
+0

加上'st [4] ='\ 0'是不是很好;'如果有人想要打印字符串呢? –

2

我寫這個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; } 
1

我建議使用這樣的函數:

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的隨機結果。

4

在斯威夫特你可以使用此功能:

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) 
} 
+0

只是爲了簡化的你的函數[代碼] FUNC stringValue的一個(unicodeValue的:int) - >字符串{ VAR stringValue的= 「」 VAR值= unicodeValue 爲_在0 .. <4 { stringValue的=字符串(UnicodeScalar (值255))+ stringValue的 值=值/ 256 } 返回stringValue的 } [\代碼] – TheCodingArt

+0

的另一種方法:擴展詮釋{ VAR unicodeStringValue:字符串{ 獲得{ VAR stringValue的= 「」 var value = self 爲_在0 .. <4 { stringValue的=字符串(UnicodeScalar(值255))+ stringValue的 值=值/ 256 } 返回stringValue的 } } } – TheCodingArt

0

如果您正在爲macOS而不是iOS開發,那麼在Launch Servi中已經有了一個內置函數CES。爲了得到4毫升爲的NSString:

(__bridge_transfer NSString *)UTCreateStringForOSType(fourccInt) 
+0

與由現有Charlesism答案。 – matt

+0

沒有任何人回答這個名字,沒有回答提及UTCreateStringForOSType /() – svth

+0

他在10個小時前刪除了它。儘管如此,對於macOS來說,這是正確的,對我編寫macOS應用程序非常有幫助。正如他的回答正確地說,但是,最初的問題是關於iOS,其中UTCreateStringForOSType - 所以你的答案也遭受了這個問題。 – matt

0

工作雨燕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 
    } 
} 
0

這裏的雨燕3.0版本的jscom的代碼,清理,消除重複:

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)") 
} 
0

更適用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))