web-dev-qa-db-fra.com

Comment puis-je obtenir le (s) code (s) Unicode d'un personnage?

Comment extraire le ou les points de code Unicode d'une Character donnée sans d'abord la convertir en String? Je sais que je peux utiliser les éléments suivants:

let ch: Character = "A"
let s = String(ch).unicodeScalars
s[s.startIndex].value // returns 65

mais il semble qu'il devrait exister un moyen plus direct d'accomplir cela en utilisant uniquement la bibliothèque standard de Swift. Les sections du guide linguistique "Utilisation des caractères" et "Unicode" ne traitent que de l'itération des caractères d'une String, ne travaillant pas directement avec Characters.

42
nathan

D'après ce que je peux rassembler dans la documentation, ils veulent que vous obteniez les valeurs Character à partir d'un String car cela donne un contexte. Est-ce que cette Character est codée avec des points de code (scalaires) UTF8, UTF16 ou 21 bits?

Si vous regardez comment une Character est définie dans le framework Swift, c'est en fait une valeur enum. Ceci est probablement dû aux différentes représentations de String.utf8, String.utf16 et String.unicodeScalars.

Il semble qu'ils ne s'attendent pas à ce que vous travailliez avec les valeurs Character mais plutôt Strings et vous, en tant que programmeur, décidez comment les obtenir à partir de String lui-même, ce qui permet de conserver le codage.

Cela dit, si vous devez obtenir les points de code de manière concise, je recommanderais une extension comme celle-ci:

extension Character
{
    func unicodeScalarCodePoint() -> UInt32
    {
        let characterString = String(self)
        let scalars = characterString.unicodeScalars

        return scalars[scalars.startIndex].value
    }
}

Ensuite, vous pouvez l'utiliser comme ceci:

let char : Character = "A"
char.unicodeScalarCodePoint()

En résumé, l'encodage de chaînes et de caractères est une tâche délicate lorsque vous prenez en compte toutes les possibilités. Afin de permettre à chaque possibilité d'être représentée, ils ont opté pour ce schéma.

Rappelez-vous également qu'il s'agit d'une version 1.0, je suis sûr qu'ils développeront bientôt le sucre syntaxique de Swift.

31
Erik

Je pense qu'il y a des malentendus à propos de l'Unicode. Unicode lui-même est PAS un codage, il ne fait pas transformer n'importe quel grappe de graphèmes (ou "Caractères" du respect de la lecture humaine) en n'importe quelle séquence binaire. L'Unicode n'est qu'un grand tableau qui regroupe tous les grappes de graphèmes utilisés par toutes les langues de la Terre (de manière non officielle, inclut également le klingon). Ces grappes de graphèmes sont organisées et indexées par les points de code (nombre de 21 bits dans Swift et ressemblant à U + D800). Vous pouvez trouver où se trouve le personnage que vous recherchez dans la grande table Unicode en utilisant les points de code 

Pendant ce temps, le protocole appelé UTF8, UTF16, UTF32 est en fait un encodage. Oui, il existe plusieurs façons de coder les caractères Unicode en séquences binaires. L'utilisation de ce protocole dépend du projet sur lequel vous travaillez, mais la plus grande partie de la page Web est codée par UTF-8 (vous pouvez en fait le vérifier maintenant). 

Concept 1: Le point Unicode s'appelle le Unicode Scalar dans Swift.

Un scalaire Unicode est un point de code Unicode compris dans la plage U + 0000 à U + D7FF inclus ou U + E000 à U + 10FFFF inclus. Les scalaires Unicode n'incluent pas les points de code de paire de substitution Unicode, qui sont les points de code compris dans la plage U + D800 à U + DFFF.

Concept 2: Le Unité de code est la représentation abstraite du codage. 

Considérez l'extrait de code suivant 

let theCat = "Cat!????"

for char in theCat.utf8 {
    print("\(char) ", terminator: "") //Code Unit of each grapheme cluster for the UFT8 encoding
}
print("")
for char in theCat.utf8 {
    print("\(String(char, radix: 2)) ", terminator: "") //Encoding of each grapheme cluster for the UTF8 encoding
}
print("")


for char in theCat.utf16 {
    print("\(char) ", terminator: "") //Code Unit of each grapheme cluster for the UFT-16 encoding
}
print("")
for char in theCat.utf16 {
    print("\(String(char, radix: 2)) ", terminator: "") //Encoding of each grapheme cluster for the UTF-16 encoding
}
print("")

for char in theCat.unicodeScalars {
    print("\(char.value) ", terminator: "") //Code Unit of each grapheme cluster for the UFT-32 encoding
}
print("")
for char in theCat.unicodeScalars {
    print("\(String(char.value, radix: 2)) ", terminator: "") //Encoding of each grapheme cluster for the UTF-32 encoding
}

Représentation abstraite} _: L'unité de code est écrite par le nombre en base 10 (nombre décimal), il est égal au codage en base 2 (séquence binaire). Le codage est fait pour les machines, Code Unit est plus pour les humains, il est facile à lire que les séquences binaires.

Concept 3: Un personnage peut avoir un ou plusieurs points Unicode différents. Cela dépend de la façon dont le personnage est contracté par quels grappes de graphèmes (c’est pourquoi j’ai dit "Caractères" de la part du respect en lecture au début) 

considérez l'extrait de code suivant

let precomposed: String = "\u{D55C}"
let decomposed: String = "\u{1112}\u{1161}\u{11AB}" 
print(precomposed.characters.count) // print "1"
print(decomposed.characters.count) // print "1" => Character != grapheme cluster
print(precomposed) //print "한"
print(decomposed) //print "한"

Les caractères precomposed et decomposed sont visuellement et linguistiquement identiques, mais ils ont un point Unicode différent et une unité de code différente s'ils sont codés par le même protocole de codage (voir l'exemple suivant).

for preCha in precomposed.utf16 {
    print("\(preCha) ", terminator: "") //print 55357 56374 128054 54620
}

print("")

for deCha in decomposed.utf16 {
    print("\(deCha) ", terminator: "") //print 4370 4449 4523
}

Exemple supplémentaire 

var Word = "cafe"
print("the number of characters in \(Word) is \(Word.characters.count)")

Word += "\u{301}"

print("the number of characters in \(Word) is \(Word.characters.count)")

Résumé: Points de code, A.k.a, l'index de position des caractères dans Unicode, n'a rien à voir avec les schémas de codage UTF-8, UTF-16 et UTF-32.

_ {Lectures supplémentaires} _:

http://www.joelonsoftware.com/articles/Unicode.html

http://kunststube.net/encoding/

https://www.mikeash.com/pyblog/friday-qa-2015-11-06-why-is-swifts-string-api-so-hard.html

17
SLN

Je suis d'accord avec vous, il devrait y avoir un moyen d'obtenir le code directement du personnage. Mais tout ce que je peux offrir, c'est un raccourci:

let ch: Character = "A"
for code in String(ch).utf8 { println(code) }
6
evpozdniakov

Je pense que le problème est que Character ne représente pas un point de code Unicode. Il représente un "cluster de graphèmes Unicode", qui peut être constitué de plusieurs points de code.

UnicodeScalar représente plutôt un point de code Unicode.

6
newacct

As-tu essayé:

import Foundation

let characterString: String = "abc"
var numbers: [Int] = Array<Int>()
for character in characterString.utf8 {
    let stringSegment: String = "\(character)"
    let anInt: Int = stringSegment.toInt()!
    numbers.append(anInt)
}

numbers

Sortie:

[97, 98, 99]

Il peut également s'agir d'un seul personnage dans la chaîne.

0
Binarian

#1. Utilisation de la propriété value de Unicode.Scalar

Avec Swift 5, Unicode.Scalar a une propriété value qui a la déclaration suivante:

Une représentation numérique du scalaire Unicode.

var value: UInt32 { get }

L'exemple de code suivant Playground montre comment effectuer une itération sur la propriété unicodeScalars d'un Character et imprimer la valeur de chaque scalaire Unicode qui le compose:

let character: Character = "A"
for scalar in character.unicodeScalars {
    print(scalar.value)
}

/*
 prints: 65
 */

En guise d'alternative, vous pouvez utiliser l'exemple de code ci-dessous si vous souhaitez uniquement imprimer la valeur du premier scalaire unicode d'un Character:

let character: Character = "A"
let scalars = character.unicodeScalars
let firstScalar = scalars[scalars.startIndex]
print(firstScalar.value)

/*
 prints: 65
 */

# 2. Utilisation de la propriété Character's asciiValue

Si vous voulez vraiment obtenir la valeur de codage ASCII d'un caractère, vous pouvez utiliser Character's asciiValue . asciiValue a la déclaration suivante:

Renvoie la valeur de codage ASCII de ce caractère, si ASCII.

var asciiValue: UInt8? { get }

L'exemple de code Playground ci-dessous montre comment utiliser asciiValue:

let character: Character = "A"
print(String(describing: character.asciiValue))

/*
 prints: Optional(65)
 */
let character: Character = "П"
print(String(describing: character.asciiValue))

/*
 prints: nil
 */
0
Imanou Petit