Terminal: MacBook Air OS: macOS High Sierra Swift: 4.0.3 (swiftlang-900.0.74.1 clang-900.0.39.2) Clang: Apple LLVM version 9.0.0 (clang-900.0.39.2)
Ich denke, jeder verwendet beiläufig die folgende Methode, wenn er eine C-Zeichenfolge (char \ *) in eine Swift- oder Objective-C-Zeichenfolge (Zeichenfolge, NSString) konvertiert.
String.swift
init?(cString: UnsafePointer<CChar>) //typealias CChar = Int8
Zunächst möchte ich den cString vorstellen, der an diese Methode übergeben wird, dh den C-String. Als nächstes wurde das obige Verfahren auf der NSString-Seite abgeschafft, und ein Verfahren zum gleichzeitigen Festlegen der Codierung wird wie unten gezeigt vorbereitet. Ich möchte über den zu diesem Zeitpunkt übergebenen Codierungswert nachdenken.
String.swift
init?(cString: UnsafePointer<CChar>, encoding enc: String.Encoding)
Char
wird als Typ bereitgestellt, der ein Zeichen in C-Sprache darstellt. In dieser Variablen vom Typ char kann ein 1-Byte-Wert gespeichert werden.
Der Buchstabe C schließt den Buchstaben in einfache Anführungszeichen ein. Der in einfache Anführungszeichen eingeschlossene Wert wird als Zeichenliteral bezeichnet.
C Brief.c
int main(void) {
char c = '*'; //「'Es wird in einen 1-Byte-ASCII-Wert konvertiert, indem das Zeichen mit einer "Markierung" versehen wird.
printf("%c\n", c); // *
printf("%ld\n", sizeof(c)); // 1
}
Wie in den Kommentaren erwähnt, ist das Obige tatsächlich die folgende Zuckerbeschichtungssyntax.
Buchstabe c.c
int main(void) {
char c = 42;
printf("%c\n", c); // *
printf("%ld\n", sizeof(c)); // 1
}
Mit anderen Worten, die Substanz des Zeichenliteral ist "nur eine Zahl".
Wenn Sie Multi-Byte-Zeichen wie unten gezeigt in einfache Anführungszeichen setzen, überschreitet die generierte Zahl (* 1) die Größe von "char" (1 Byte), was zu einem Kompilierungsfehler führt.
(\ * 1: Den generierten Wert finden Sie im folgenden Abschnitt "[Wenn Mehrbytezeichen in der C-Zeichenfolge gespeichert sind](https://qiita.com/ysn551/items/446074b22103233edd95#c%E3%81] % AE% E6% 96% 87% E5% AD% 97% E5% 88% 97% E3% 81% AB% E3% 83% 9E% E3% 83% AB% E3% 83% 81% E3% 83% 90 % E3% 82% A4% E3% 83% 88% E6% 96% 87% E5% AD% 97% E3% 82% 92% E6% A0% BC% E7% B4% 8D% E3% 81% 97% E3 % 81% 9F% E5% A0% B4% E5% 90% 88) ”)
C Brief.c
//Diese Quellcodedatei wird in UTF8 gespeichert
int main(void) {
char c = 'Ah'; // error: character too large for enclosing character
}
Mit anderen Worten, Multi-Byte-Zeichen können nicht wie in Variablen vom Typ char gespeichert werden.
Darüber hinaus kann die Überprüfung, dass das tatsächliche Zeichenliteral eine 1-Byte-Zahl ist, durch die Tatsache bewiesen werden, dass der Wert direkt im int-Typ (4 Byte) gespeichert werden kann, wie unten gezeigt.
Die Substanz des Zeichenliteral ist eine 1-Byte-Zahl.c
int main(void) {
int num = 'abcd';
printf("%0x\n", num); // 64656667
}
Das Ergebnis der Ausgabe des Werts von num in Hexadezimalzahl ist "64656667". Wenn Sie den Wert in Byteeinheiten lesen, können Sie sehen, dass er in "64,65,66,67" zerlegt werden kann.
Eine C-Sprachzeichenfolge ist ein Array vom Typ "char". Mit anderen Worten wird es durch ein Array zum Speichern von 1-Byte-Daten dargestellt. Außerdem schließt die C-Zeichenfolge das Zeichen in doppelte Anführungszeichen ein. Der in doppelte Anführungszeichen eingeschlossene Wert wird auch als Zeichenfolgenliteral bezeichnet.
C-Saite.c
int main(void) {
char str[] = "Hello"; //Die Anzahl der Elemente kann durch gleichzeitiges Initialisieren weggelassen werden.
printf("sizeof(str)/sizeof(char) = %ld\n", sizeof(str)/sizeof(char)); // 6
}
Die oben für die Initialisierung verwendete Zeichenfolge * Hallo * besteht aus 5 Zeichen, die Anzahl der Elemente beträgt jedoch 6. Tatsächlich hat es die folgende Syntax für die Zuckerbeschichtung.
Über die Zeichenkette von C..c
int main(void) {
char str[] = {'H','e','l','l','o','\0'};
printf("sizeof(str)/sizeof(char) = %ld\n", sizeof(str)/sizeof(char)); //6
}
Mit anderen Worten, das Zeichenfolgenliteral "Hallo" gibt ein Zeichenarray mit 6 Elementen zurück, in dem das Nullzeichen am Ende gespeichert ist.
Obwohl im obigen Abschnitt nicht erwähnt, werden die Ergebnisse, wenn der Quellcode wie unten gezeigt mit Multibyte-Zeichen initialisiert wurde, in einer Datei mit UTF8 gespeichert und wenn er in einer Datei mit Shift-JIS gespeichert wird, unten angezeigt. Ich würde es gerne sehen.
Über die Zeichenkette von C..c
int main(void) {
char str[] = "Ah"; //Wenn Sie ein Array gleichzeitig mit der Initialisierung deklarieren, können Sie die Anzahl der Elemente weglassen
int size = sizeof(str);
for (int i = 0; i < size; i++) {
printf("%hhx ", str[i]); //Überprüfen Sie diese Ausgabe bei jeder Codierung
}
}
Überprüfungsmethode:
Ausgabe beim Speichern in UTF8:
case_utf8_result.txt
e3 81 82 0
Ausgabe beim Speichern als Shift-JIS:
case_shift_jis_result.txt
82 a0 0
Geben Sie für jeden der oben genannten Werte auf dieser Site "A" ein und zeigen Sie das Ergebnis an.
Ergebnis
Mit anderen Worten, Sie können sehen, dass das Ergebnis des Zeichenfolgenliterals des Mehrbytezeichens in der Sprache C mit der Codierung des Texteditors übereinstimmt.
Dies ist ein sehr natürliches Ergebnis, da wir die "Datei", in der der Quellcode geschrieben ist, an den Compiler übergeben, nicht den "Quellcode".
Mit anderen Worten, im Fall von UTF8 kann gesagt werden, dass "char str [] =" a "" die folgende Syntax für die Zuckerbeschichtung ist.
Über die Zeichenkette von C..c
int main(void) {
//e3 81 82 0
char str[] = {0xe3, 0x81, 0x82, 0x0};
printf("%s \n", str); //Wenn die Terminalcodierungseinstellung UTF8 ist, wird "A" angezeigt.
}
Wenn das oben auszuführende Terminal in UTF-8 codiert und ausgeführt wird, wird "A" angezeigt.
Wenn Sie Shift-JIS verwenden, werden die Zeichen verstümmelt.
(Einstellungen → Profile → Erweitertag)
Infolgedessen ist oben das Ergebnis, wenn Shift-JIS festgelegt ist, und unten das Ergebnis, wenn UTF8 festgelegt ist.
Ich möchte die unten stehende Swift-API verwenden, um die von der C-API übergebenen Zeichen in eine Swift-Zeichenfolge zu konvertieren. Wie sollte der zu diesem Zeitpunkt angegebene Codierungswert sein?
String.swift
init?(cString: UnsafePointer<CChar>, encoding enc: String.Encoding) //CChar = Int8
Der zu überprüfende C-Programmcode lautet wie folgt.
libc.c
char* file_name() {
return "hello.txt";
}
char* new_file_header_str() {
FILE *f = fopen(file_name(), "r");
if (f == NULL) return NULL;
char *str = calloc(256, sizeof(char));
fgets(str, 256, f); //Nur eine Zeile
fclose(f);
return str;
}
Wenn Sie das Obige von Swift aus aufrufen, wird der Typ C char *
als Typ UnsafeMutablePointer <Int8>
übergeben.
Zunächst möchte ich überprüfen, ob das von der Funktion file_name
erhaltene C-Zeichen in das Swift-Zeichen konvertiert wurde.
Dieses Zeichenkettenliteral wird unverändert zurückgegeben.
Mit anderen Worten, Sie können sehen, dass der Codierungswert beim Konvertieren in eine Swift-Zeichenfolge mit der Codierung in der libc.c-Datei übereinstimmen muss.
Was ist als nächstes mit dem Codierungswert, der zum Konvertieren des von der Funktion new_file_header_str
erhaltenen C-Zeichens in eine Swift-Zeichenfolge verwendet wird?
Hier wird die Zeichenfolge der Datei "hello.txt" zurückgegeben.
Sie können also sehen, dass der Codierungswert, den Sie hier angeben müssen, mit dem Codierungswert übereinstimmen muss, in dem die Datei "hello.txt" gespeichert ist.
Unten finden Sie einen Beispielquellcode, der die Datei lib.c in UTF-8 und die Datei hello.txt in Shift-JIS speichert und jede Funktion von Swift aus aufruft.
get_str_from_c.swift
let name = file_name() //Optional<UnsafeMutablePointer<Int8>>
if let name = name,
let converted = String(cString: name, encoding: .utf8) {
print(converted)
}
let header = new_file_header_str() //Optional<UnsafeMutablePointer<Int8>>
if let header = header,
let converted = String(cString: header, encoding: .shiftJIS) {
print(converted)
}
Informationen zum Aufrufen der C-Bibliothek finden Sie im Folgenden. https://qiita.com/ysn551/items/83e06cf74ae628cb573c
Auf diese Weise speichert das C-String-Literal den Codierungswert direkt, sodass er von der Entwicklungsumgebung abhängt. Im Falle des Swift-Compilers können übrigens nur UTF8-Dateien kompiliert werden.
In Python3 ist der vom Zeichenfolgenliteral generierte Wert eine Zahl, dies ist jedoch ein Unicode-Wert. Daher muss beim Austausch von Zeichenfolgenliteralen zwischen Dateien keine Codierung berücksichtigt werden.
Das Überprüfungsergebnis mit python3 lautet wie folgt. Python2 verwendet übrigens Codierungswerte, daher ist es nutzlos, wenn die Codierung zwischen den Quellcodes unterschiedlich ist.
Speichern Sie die folgende Datei shift_jis.py in Shift-JIS-Codierung
shift_jis.py
#! coding=shift-jis
word = "Freut mich, dich kennenzulernen"
Speichern Sie die folgende Datei utf8.py als UTF8 und führen Sie sie aus.
utf8.py
#! coding=utf-8
import shift_jis as sh
if sh.word == "Freut mich, dich kennenzulernen":
print("true")
else:
print("false")
Wenn ich das oben genannte auf python3 ausführe, wird true angezeigt, aber auf python2 wird false angezeigt.
Ich freue mich darauf, 2018 mit Ihnen zusammenzuarbeiten. m (__) m
Recommended Posts