2013-01-08 14 views
10

Molte delle costanti associate alla programmazione di sessioni audio sono in realtà stringhe di quattro caratteri (Audio Session Services Reference). Lo stesso vale per OSStatus code restituito da funzioni come AudioSessionGetProperty.iOS/C: conversione "intero" in stringa di quattro caratteri

Il problema è che quando provo a stampare queste cose, fuori dalla scatola, sembrano 1919902568. posso inserire che in Calcolatrice e accendere uscita ASCII e mi dirò "roch", ma ci deve essere un modo programmatico per farlo.

ho avuto un successo limitato in una delle mie funzioni C con il seguente blocco:

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

Quello che voglio fare è quello di astrarre questa caratteristica fuori della sua funzione attuale, al fine di utilizzare altrove . Ho provato a fare

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

ma che mi dà "à * €/3IT: ê * €/+ € /", non "roch". Il mio C fu non è molto forte, ma la mia impressione è che il codice sopra tenta di interpretare l'indirizzo di memoria come una stringa. O forse c'è un problema di codifica? Qualche idea?

risposta

14

Il tipo si sta parlando è un FourCharCode, definito in CFBase.h. È equivalente a OSType. Il modo più semplice per convertire tra OSType e NSString utilizza NSFileTypeForHFSTypeCode() e NSHFSTypeCodeFromFileType(). Queste funzioni, purtroppo, non sono disponibili su iOS.

per iOS e codice di cacao-portatile, mi piace Joachim Bengtsson'sFourCC2Str() dal suo NCCommon.h (più un po 'di pulizia casting per un utilizzo più facile):

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

Si potrebbe naturalmente gettare la @() nella macro per ancora più facile uso.

+0

Ooh, sembra davvero utile. Mi dà comunque un errore "Expected Expected" fuori dagli schemi, quindi dovrò tornare a questo. –

+0

Pulito per renderlo un po 'più facile da usare. Restituisce un char [] piuttosto che un char *, e questo sembra confondere le cose ora. –

+0

eccellente, grazie! –

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

Dopo capire una funzione reverseStr, questo funziona. Mi piacerebbe davvero avere una soluzione DRYer (come per racchiudere questo in un metodo), ma serve per ora. –

5

Numero intero = 4 byte = 4 caratteri. Quindi, per la conversione da numero intero a char * si può semplicemente scrivere:

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

Per riconvertirlo:

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

non sarebbe opportuno aggiungere 'st [4] = '\ 0';' nel caso qualcuno voglia stampare la stringa? –

2

Ho scritto questa funzione C per il mio codice audio ... potrebbe essere un po 'ingenuo , ma lo fa il lavoro per abbastanza bene per me:

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

io suggerisco di usare una funzione come questa:

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]]; 
} 

Ciò garantisce che non si ottengano risultati casuali per alcuni FourCharCode che sono numeri reali come kCMPixelFormat_32ARGB = 32.

4

In Swift si può usare questa funzione:

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

Questo func farà lo stesso come sopra in un terzo del tempo:

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

Il modo inverso saranno:

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

solo per semplificare una delle tue funzioni [code] FUNC stringValue (unicodeValue: Int) -> String {var stringValue = "" valore var = unicodeValue per _ a 0 .. <4 { stringValue = Stringa (UnicodeScalar (valore di & 255)) + stringValue value = valore/256 } ritorno stringValue } [\ code] – TheCodingArt

+0

Un altro modo: l'estensione Int { var unicodeStringValue: String { get { var stringValue = "" var value = self per _ a 0 .. <4 { stringValue = String (UnicodeScalar (valore e 255)) + stringValue value = Valore/256 } ritorno stringValue }} } – TheCodingArt

0

Se si sta sviluppando per macOS anziché iOS, è già disponibile una funzione integrata in Launch Servi ces. Per ottenere il 4cc come NSString:

(__bridge_transfer NSString *)UTCreateStringForOSType(fourccInt) 
+0

Stessa risposta esistente Charlesism. – matt

+0

Non c'è risposta da parte di nessuno con quel nome e nessuna risposta che menzioni UTCreateStringForOSType /() – svth

+0

L'ha cancellata 10 ore fa. Tuttavia, è giusto per macOS, ed è stato di grande aiuto per me nello scrivere un'applicazione macOS. Come la sua risposta ha giustamente detto, tuttavia, la domanda iniziale riguarda iOS, dove UTCreateStringForOSType - quindi anche la tua risposta soffre di questo problema. – matt

0

lavoro Swift 2.2 versione a due estensioni:

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

Ecco la versione Swift 3 del codice di jscom, ripulito per eliminare la ripetizione:

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

Un'implementazione più Swifty, che funziona per 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) 
    } 
} 

che può essere usato come segue:

String(fourCharCode: CMFormatDescriptionGetMediaSubType(charCode)) 
Problemi correlati