0

ワイド文字列の文字数を決定する同じコードを実行しました。テストされた文字列には、ASCII、数字、および韓国語が含まれています。

#include <iostream>

using namespace std;

template <class T,class trait>
void DumpCharacters(T& a)
{
    size_t length = a.size();
    for(size_t i=0;i<length;i++)
    {
        trait n = a[i];
        cout<<i<<" => "<<n<<endl;
    }

    cout<<endl;
}

int main(int argc, char* argv[])
{
    wstring u = L"123abc가1나1다";
    wcout<<u<<endl;
    DumpCharacters<wstring,wchar_t>(u);

    string s = "123abc가1나1다";
    cout<<s<<endl;
    DumpCharacters<string,char>(s);

    return 0;
}

明らかなことは、Visual C++ 2010 の wstring.size() は、ASCII 文字か国際文字かに関係なく、文字数 (11 文字) を返すことです。ただし、Mac OS X の XCode 4.2 では文字列データのバイト数 (17 バイト) を返します。

xcodeのバイト数ではなく、ワイド文字列の文字長を取得する方法を教えてください。

--- 2月12日追記 --

wcslen() も xcode で 17 を返すことがわかりました。vc++ では 11 を返します。テストしたコードは次のとおりです。

const wchar_t *p = L"123abc가1나1다";
size_t plen = wcslen(p);

--- 2月18日追記 --

llvm 3.0 が間違った長さの原因であることがわかりました。この問題は、コンパイラ フロントエンドを llvm3.0 から 4.2 に変更すると修正されます。

wcslen() は Xcode と VC++ では動作が異なり、詳細は VC++ に記載されています。

4

4 に答える 4

4

バージョンが 17 文字を使用している場合はエラーですstd::wstring。11 文字のみを使用する必要があります。gcc と clang の最近の SVN ヘッドを使用すると、 に 11 文字、std::wstringに 17 文字が使用されstd::stringます。これは期待通りだと思います。

標準 C++ ライブラリは、内部的に「文字」とは何かについて、マルチワード エンコーディング (たとえば、タイプの単語にはcharUTF-8、16 ビットの単語には UTF-16) が使用される場合に期待されるものとは異なる考えを持っていることに注意してください。 . これは、文字列を説明する章の最初の段落です (21.1 [strings.general]):

この句は、配列以外の POD (3.9) タイプのシーケンスを操作するためのコンポーネントについて説明します。この節では、そのような型を char 様型と呼び、char 様型のオブジェクトを char 様オブジェクトまたは単に文字と呼びます。

これは基本的に、Unicode を使用する場合、さまざまな関数コード ポイントを構成するものに注意を払うのではなく、文字列を一連の単語として処理することを意味します。これは重大な影響であり、たとえば部分文字列を生成するときに、マルチバイト文字が簡単に分割される可能性があるため、何が起こるかが分かります。現在、標準 C++ ライブラリはマルチバイト エンコーディングの処理を内部的にサポートしていません。これは、エンコーディングから文字への変換がデータの読み取り時に行われると想定されているためです (それに対応して、データの書き込み時にも別の方法で行われます)。マルチバイトのエンコードされた文字列を内部で処理している場合は、サポートがまったくないため、これに注意する必要があります。

このような状況は、実際には問題であると認識されています。C++2011 の場合、文字タイプchar32_tが追加されました。これは、Unicode 文字をより適切にサポートする必要がありますwchar_t(Unicode は 20 ビットを使用するため)。wchar_tUnicode が最大 16 ビットの使用を約束していたときに一部のプラットフォームで行われた選択である 16 ビットのみのサポートが許可されていました)。ただし、これはまだ文字の組み合わせには対応していません。C++ 委員会は、これが問題であり、標準 C++ ライブラリでの適切な文字処理があればよいことを認識していますが、これまでのところ、この問題に対処するための包括的な提案を前に出す人はいません (このようなものを提案するが、方法がわからない場合は、お気軽にお問い合わせください。提案の提出方法をお手伝いします)。

于 2012-02-11T18:18:56.440 に答える
1

XCode 4.2は"123abc가1나1다"、初期化時にプログラムのソースコードで文字列リテラルを表すために、狭いマルチバイトエンコーディングとしてUTF-8(または非常に類似したもの)を使用したようstring sです。その文字列の UTF-8 表現の長さはたまたま 17 バイトです。

ワイド文字表現 ( に格納u) は 11 ワイド文字です。ナロー エンコーディングからワイド エンコーディングに変換する方法は多数あります。これを試して:

#include <iostream>
#include <clocale>
#include <cstdlib>

int main()
{
    std::wstring u = L"123abc가1나1다";
    std::cout << "Wide string containts " << u.size() << " characters\n";

    std::string s = "123abc가1나1다";
    std::cout << "Narrow string contains " << s.size() << " bytes\n";

    std::setlocale(LC_ALL, "");
    std::cout << "Which can be converted to "
              << std::mbstowcs(NULL, s.c_str(), s.size())
              << " wide characters in the current locale,\n";
}
于 2012-02-11T17:42:56.513 に答える
0

文字列の長さを取得するの.length()ではなく、を使用します。.size()

于 2012-02-11T18:37:39.093 に答える
0

std::string と std::wstring は、char と wchar_t でテンプレート化された std::basic_string の typedef です。size() メンバー関数は、文字列の要素数 (char または wchar_t の数) を返します。"" と L"" はエンコーディングを扱いません。

于 2012-02-12T09:10:46.993 に答える