SORU
10 HAZİRAN 2011, Cuma


WChars, Kodlamalar, Standartlar ve Taşınabilirlik

Aşağıdaki ÖYLESİNE bir soru olarak hak olabilir; eğer sınırların dışında ise, lütfen git buradan çekinmeyin. Soru şu: temelde, C standart doğru mu anlıyorum "ve bu şeyler hakkında gitmek için doğru yol mu?"

C karakter kullanma anlayışım açıklama, onay ve düzeltmeleri için sormak (ve bu nedenle C ve C 0 x) istiyorum. Öncelikle, önemli bir gözlem:

Taşınabilirlik ve seri hale getirme dikey kavramlardır.

Taşınabilir şeyler C gibi şeyler, unsigned int, wchar_t. Seri hale getirilebilir şeyler uint32_t gibi şeyler vardır ya da UTF-8. "Taşınabilir" anlamına geliyor olabilir yeniden aynı kaynak ve çalışma sonucu her desteklenen bir platform, ama ikili gösterimi olabilir tamamen farklı (ya da bile var, örneğin TCP-over-posta güvercini). Öte yandan seri hale getirilebilir şeyler her zaman varaynıtemsil, örneğin PNG diş fırçamı telefonumla ya benim Windows masaüstü üzerinde okuyabilirim, dosya. Taşınabilir şeyler iç, seri hale getirilebilir işlerim Taşınabilir şeyler typesafe/O. ile anlaşma, seri hale getirilebilir tür şeyler punning gerekiyor. &;/lt Önsöz>

C karakter kullanma söz konusu olduğunda, işler sırasıyla taşınabilirlik ve seri hale getirme ile ilgili iki grup vardır:

  • *, , /**setlocale()mbsrtowcs()7 10*:C standardı hakkında hiçbir şey diyor"" . kodlamalar aslında, herhangi bir metin ya da kodlama özellikleri ile, tamamen agnostik. Sadece diyor ki "giriş noktası main(int, char**); Bir tür wchar_t tutabileceğini tüm sisteminizin karakter; olsun işlevleri okumak için giriş char dizileri ve onları içine uygulanabilir wstrings ve tersi.

  • iconv() ve UTF-8,16,32: işlev/arasında çapraz kitaplık iyi tanımlanmış, kesin, sabit kodlamalar. Tüm kodlamalar iconv tarafından ele evrensel olarak anlaşılır ve bir istisna ile mutabık.

wchar_t taşınabilir karakter türünü ve dünya dışında deterministik C taşınabilir, kodlama-agnostik dünya arasında bir köprüdürWCHAR-T ve UTF arasında dönüştürme iconv.

Her zaman benim dizeleri DAHİLİ olarak wcsrtombs() üzerinden CRT ile kodlama-agnostik bir wstring, arayüz deposu ve seri hale getirme iconv() kullan? Kavramsal olarak:

                        my program
    <-- wcstombs ---  /==============\   --- iconv(UTF8, WCHAR_T) -->
CRT                   |   wchar_t[]  |                                <Disk>
    --- mbstowcs -->  \==============/   <-- iconv(WCHAR_T, UTF8) ---
                            |
                             -- iconv(WCHAR_T, UCS-4) -- 
                                                        |
       ... <--- (adv. Unicode malarkey) ----- libicu --- 

İki yazacağımı anlamına gelir bu da pratikte, kazan levhaları program girişi demek istediğim, örneğin için sarma C :

// Portable wmain()-wrapper
#include <clocale>
#include <cwchar>
#include <string>
#include <vector>

std::vector<std::wstring> parse(int argc, char * argv[]); // use mbsrtowcs etc

int wmain(const std::vector<std::wstring> args); // user starts here

#if defined(_WIN32) || defined(WIN32)
#include <windows.h>
extern "C" int main()
{
  setlocale(LC_CTYPE, "");
  int argc;
  wchar_t * const * const argv = CommandLineToArgvW(GetCommandLineW(), &argc);
  return wmain(std::vector<std::wstring>(argv, argv   argc));
}
#else
extern "C" int main(int argc, char * argv[])
{
  setlocale(LC_CTYPE, "");
  return wmain(parse(argc, argv));
}
#endif
// Serialization utilities

#include <iconv.h>

typedef std::basic_string<uint16_t> U16String;
typedef std::basic_string<uint32_t> U32String;

U16String toUTF16(std::wstring s);
U32String toUTF32(std::wstring s);

/* ... */

Bu doğru bir yazma deyimsel, taşınabilir, evrensel, kodlama-agnostik program çekirdek kullanarak sadece saf standart C/C , İyi tanımlanmış bir G/Ç arabirimi için UTF iconv? (Unicode normalleştirme veya aksan değiştirme gibi sorunlar Eğer gerçekten istiyorum karar sonra kapsamı dışındadır; unutmayınUnicodehoşuna gidebilir başka kodlama sistemi (karşıt olarak) vakti bu özelliklerini, örneğin libicu. gibi özel bir kütüphane kullanarak) ile anlaşma

Güncelleştirmeleri

Çok güzel çok yorumlar aşağıdaki birkaç gözlem daha eklemek istiyorum:

  • Eğer uygulamanızın açıkça istediği için anlaşma ile Unicode metin, sen iconv-dönüşüm kısmı çekirdek ve kullanımı uint32_t/char32_t-dizeler içten ile USC-4.

  • Windows kullanırken geniş dizeleri genellikle iyi, görünen etkileşim ile konsolu (herhangi bir konsol için önemli) sınırlı, orada görünmez olmak destek için mantıklı herhangi bir multi-byte kodlama konsolu ve mbstowcs aslında işe yaramaz (başka bir konu için önemsiz genişletme). -Geniş dize bağımsız değişken alan, diyelim ki, bir Kaşif bırak birlikteGetCommandLineW CommandLineToArgvW işleri (belki Windows için ayrı bir kapsayıcı olmalı).

  • Dosya sistemleri: kodlama hakkında bir fikrin yok gibi ve sadece bir dosya adı olarak boş sonlandırılmış bir dize herhangi bir Dosya al. Sistemlerin çoğu bayt dizeleri, ama/NTFS 16-bit dizeleri alır Windows. Dosyaları var ve bu veri işlerken (geçerli UTF16 (çıplak suretleri gibi) teşkil etmediğini 25 *örneğin* diziler geçerli NTFS olan dosya adları) keşfetmek zaman dikkat etmek gerekir. Standart C fopen 16-bit tüm olası dizeleri için eşler mümkün dönüşüm yok bu yana tüm NTFS dosyaları açmak için değil,. Windows özel _wfopen kullanılması gerekli olabilir. Bir sonucu olarak, genel olarak "" karakter "en başta. kavramı diye bir şey yok" olarak verilen bir dosya adı içerir, ne kadar iyi tanımlanmış bir kavram yok Böyle biline.

CEVAP
11 HAZİRAN 2011, CUMARTESİ


Bunu doğru bir şekilde çevirebilen, taşınabilir, evrensel, kodlama-agnostik program bir çekirdek sadece saf standart C/C kullanarak yazmaktır

Eğer programı Windows üzerinde çalıştırmak istiyorsanız hiç, ve hiç bir şekilde tüm bu özellikleri yerine getirmek için yok en azından. Windows, C ve C standartları hemen her yerde görmezden ve sadece wchar_t ile (mutlaka içten, ama sistem için tüm arayüzleri) bir iş var. Eğer ile başlayın örneğin

int main(int argc, char** argv)

zaten komut satırı argümanları için Unicode desteği kaybettiniz. Yazmak zorundasın

int wmain(int argc, wchar_t** argv)

bunun yerine, ya da hiçbiri C standardında GetCommandLineW işlev kullanın.

Daha spesifik olarak,

  • Windows Unicode uyumlu herhangi bir program aktif olarak komut satırı argümanları gibi şeyler için C ve C standardı görmezden, dosya ve I/O, ya da dosya ve dizin manipülasyon konsol gerekir. Bu kesinlikle değildeyimsel. Boost gibi Microsoft uzantıları veya ambalaj kağıtları kullanın.Dosya sistemi veya Qt yerine.
  • Taşınabilirlikson derece elde etmenin zor olduğunu, özellikle Unicode desteği için. Gerçekten bildiğinizi sandığınız her şey muhtemelen yanlıştır hazır olmak zorunda. Örneğin, dosyaları açmak için kullandığınız dosya adları aslında kullanılan dosya adları farklı olabilir, ve iki görünüşte farklı dosya adları aynı dosyayı temsil olabileceğini göz önünde bulundurmanız gerekir. İki dosyayı oluşturduktan sonrabirvebtek bir dosya ile karşılaşabilirsinizcya da iki dosyadveeOS geçtin. dosya adları farklı olan , Ya harici sarıcı bir kütüphane veya #ifdefs çok ihtiyacımız var.
  • Kodlama agnosticitygenelde özellikle taşınabilir olmasını istiyorsanız, pratikte işe yaramaz. wchar_t Windows UTF-16 kod birimi olduğunu ve char sık olduğunu biliyorum (bot her zaman değil) Linux UTF-8 kod birimi var. Kodlama-farkındalık çoğu zaman daha cazip amacımız: her zaman çalışmak ile bildiğinizden emin olun, ya da onları özetler bu kapsayıcı bir kütüphane kullanın.

Sanırım ben sonuç işte bu tamamen imkansız bir yapı taşınabilir Unicode özellikli uygulama C sürece isteyen kullanmak için ek kütüphaneler ve sisteme özel uzantıları ve koymak için çok çaba içinde. Ne yazık ki, çoğu uygulama zaten başarısız nispeten basit görevleri gibi "yazılı Yunan karakter konsolu" ya da "destekleyen herhangi bir dosya adı ile izin sisteminde doğru şekilde" ve bu tür görevler sadece ilk küçük adımları doğru gerçek Unicode desteği.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • ehowhome

    ehowhome

    22 NİSAN 2009
  • Howard Pinsky

    Howard Pinsk

    6 AĞUSTOS 2006
  • My Name Is Jeff

    My Name Is J

    26 ŞUBAT 2008