Burada çok iyi cevaplar var, ancak Windows / Visual Studio ile ilgili ekleyebileceğim birkaç şey olduğunu düşünüyorum. Tis, VS2015 ile olan deneyimime dayanıyor. Linux'ta temel olarak cevap std::string
her yerde kodlanmış UTF-8 kullanmaktır . Windows / VS'de daha karmaşık hale gelir. İşte nedeni. Windows, char
s kullanılarak saklanan dizelerin yerel ayar kod sayfası kullanılarak kodlanmasını bekler . Bu hemen hemen her zaman ASCII karakter kümesini ve ardından bulunduğunuz yere bağlı olarak 128 diğer özel karakterdir. Bunu sadece Windows API'sini kullanırken değil, bu dizelerin standart C ++ ile etkileşime girdiği diğer üç önemli yer olduğunu da belirteyim. Bunlar dizgi değişmezleri, dosya adını std::cout
kullanmaya <<
ve aktarmaya çıktıdır std::fstream
.
Burada, bir dil uzmanı değil, bir programcı olduğumun başında olacağım. USC2 ve UTF-16'nın aynı olmadığını takdir ediyorum, ancak benim amacım için değiştirilebilir olacak kadar yakınlar ve onları burada böyle kullanıyorum. Aslında hangi Windows'un kullandığından emin değilim, ama genellikle de bilmeme gerek yok. Bu cevapta UCS2'yi belirttim, eğer bu konuyla ilgili bilgisizliğimden birini rahatsız edersem şimdiden özür dilerim ve yanlış bir şeyim varsa değiştirmek için mutluyum.
Dize değişmez değerleri
Yalnızca kod sayfanız tarafından temsil edilebilecek karakterler içeren dize değişmezleri girerseniz, VS bunları kod sayfanıza göre karakter kodlaması başına 1 bayt ile dosyanızda depolar. Kod sayfanızı değiştirirseniz veya kaynağınızı farklı bir kod sayfası kullanarak başka bir geliştiriciye verirseniz, karakterin farklı olacağını düşünüyorum (ancak test etmedim). Kodunuzu farklı bir kod sayfası kullanarak bir bilgisayarda çalıştırırsanız, karakterin de değişip değişmeyeceğinden emin değilim.
Kod sayfanız tarafından temsil edilemeyen herhangi bir dize değişmezi girerseniz, VS dosyayı Unicode olarak kaydetmenizi ister. Dosya daha sonra UTF-8 olarak kodlanacaktır. Bu, tüm ASCII olmayan karakterlerin (kod sayfanızda bulunanlar dahil) 2 veya daha fazla baytla temsil edileceği anlamına gelir. Bu, kaynağınızı başka birine verirseniz, kaynak aynı görüneceği anlamına gelir. Ancak, kaynağı derleyiciye geçirmeden önce VS, UTF-8 kodlu metni kod sayfası kodlu metne dönüştürür ve kod sayfasında eksik olan tüm karakterlerin yerini alır ?
.
VS'de bir Unicode dizgi değişmezini doğru şekilde temsil etmenin tek yolu, dizgi değişmezinden önce L
geniş bir dizgi değişmezi yapmaktır. Bu durumda VS, UTF-8 kodlu metni dosyadan UCS2'ye dönüştürür. Daha sonra bu dize hazır std::wstring
bilgisini bir kurucuya geçirmeniz veya utf-8'e dönüştürmeniz ve bir std::string
. İsterseniz, Windows API işlevlerini kullanarak kod sayfanızı kullanarak kodlamak için kullanabilirsiniz std::string
, ancak geniş bir dize hazır bilgisi kullanmamış olabilirsiniz.
std :: cout
Kullanarak konsola çıkarılırken <<
sadece kullanabilirsiniz std::string
değil, std::wstring
ve metin yerelleştirme Codepage kullanarak kodlanmalıdır. Eğer bir std::wstring
Windows API işlevlerinden birini kullanarak dönüştürmek gerekir ve kod sayfanızda olmayan herhangi bir karakter ile değiştirilir ?
(belki karakteri değiştirebilirsiniz, hatırlayamıyorum).
std :: fstream dosya adları
Windows işletim sistemi, dosya adları için UCS2 / UTF-16 kullanır, böylece kod sayfanız ne olursa olsun, herhangi bir Unicode karakteri olan dosyalarınız olabilir. Ancak bu, kod sayfanızda olmayan karakterlere sahip dosyalara erişmek veya dosya oluşturmak için kullanmanız gerektiği anlamına gelir std::wstring
. Başka yolu yok. Bu, std::fstream
diğer sistemlerde derlenmeyeceği için Microsoft'a özgü bir uzantıdır . Std :: string kullanıyorsanız, yalnızca kod sayfanızda yalnızca karakter içeren dosya adlarını kullanabilirsiniz.
Seçenekleriniz
Sadece Linux üzerinde çalışıyorsanız, muhtemelen bu kadar uzağa gitmediniz. Sadece std::string
her yerde UTF-8 kullanın .
Sadece Windows üzerinde çalışıyorsanız, std::wstring
her yerde UCS2 kullanın . Bazı saflar UTF8'i kullandıktan sonra gerektiğinde dönüştürebilir, ancak neden güçlükle uğraşabilirsiniz.
Çapraz platform iseniz o zaman dürüst olmak için bir karışıklık. UTF-8'i Windows'ta her yerde kullanmaya çalışırsanız, dize değişmezlerine ve konsola çıktıya gerçekten dikkat etmelisiniz. Orada dizelerinizi kolayca bozabilirsiniz. std::wstring
Linux'ta her yerde kullanırsanız , geniş sürümüne erişemeyebilirsiniz std::fstream
, bu yüzden dönüşümü yapmanız gerekir, ancak yolsuzluk riski yoktur. Kişisel olarak bunun daha iyi bir seçenek olduğunu düşünüyorum. Birçoğu katılmıyorum, ama yalnız değilim - örneğin wxWidgets tarafından alınan yol.
Başka bir seçenek Linux ve Windows'ta unicodestring
olduğu gibi typedef yazmak std::string
ve std::wstring
Windows'ta L ön eki ve Linux'ta hiçbir şey önermeyen UNI () adında bir makroya sahip olmak olabilir.
#include <fstream>
#include <string>
#include <iostream>
#include <Windows.h>
#ifdef _WIN32
typedef std::wstring unicodestring;
#define UNI(text) L ## text
std::string formatForConsole(const unicodestring &str)
{
std::string result;
//Call WideCharToMultiByte to do the conversion
return result;
}
#else
typedef std::string unicodestring;
#define UNI(text) text
std::string formatForConsole(const unicodestring &str)
{
return str;
}
#endif
int main()
{
unicodestring fileName(UNI("fileName"));
std::ofstream fout;
fout.open(fileName);
std::cout << formatForConsole(fileName) << std::endl;
return 0;
}
her iki platformda da iyi olacağını düşünüyorum.
Yanıtlar
Yani sorularınızı cevaplamak için
1) Windows için programlıyorsanız, Windows'ta olası yolsuzluk sorunlarıyla uğraşmak veya #ifdefs
farklılıklar üzerinde çalışmak için platformla belirli bir kod yazmak istemiyorsanız, her zaman, çapraz platform varsa, belki de her zaman Linux o zaman asla.
2) Evet. Ayrıca Linux'ta tüm Unicode için de kullanabilirsiniz. Windows'da bunu tüm unicode için yalnızca UTF-8 kullanarak manuel olarak kodlamayı seçerseniz kullanabilirsiniz. Ancak Windows API ve standart C ++ sınıfları std::string
, yerel ayar kod sayfası kullanılarak kodlanmasını bekler . Bu, tüm ASCII artı bilgisayarınızın kullanmak üzere ayarladığı kod sayfasına bağlı olarak değişen 128 karakter daha içerir.
3) Buna inanıyorum, ancak değilse, sadece 'std :: basic_string' wchar_t
yerine basit bir typedefchar
4) Geniş karakter, 1 bayt standart char
türden daha büyük bir karakter türüdür. Windows'ta 2 bayt, Linux'ta 4 bayt.