8

それを解決する方法がわかりません:

想像してみてください。4 つの Web サイトがあるとします。

  • A: UTF-8
  • B: ISO-8859-1
  • C:アスキー
  • D: UTF-16

C++ で書かれた私のプログラムは次のことを行います: Web サイトをダウンロードして解析します。ただし、内容を理解する必要があります。私の問題は、">"やのようなASCII文字で行われる解析ではありません"<"

問題は、プログラムが Web サイトのテキストからすべての単語を見つけなければならないことです。単語は、英数字の任意の組み合わせです。次に、これらの単語をサーバーに送信します。データベースと Web フロントエンドは UTF-8 を使用しています。だから私の質問は:

  • 「任意の」(または最も使用されている) 文字エンコーディングを UTF-8 に変換するにはどうすればよいですか?
  • C++ で UTF-8 文字列を操作するにはどうすればよいですか? wchar_t2バイト長なので動かないと思います。UTF-8 のコードポイントは最大 4 バイトです...
  • そのようなUTF-8文字列に対して、、、、のisspace()ようisalnum()strlen()関数はありますか?tolower()

std::cout注意してください: 私はC++ で出力 (のような) を行いません。単語をフィルタリングしてサーバーに送信するだけです。

UTF8-CPP については知っていますが、is*()機能がありません。そして、私が読んだように、他の文字エンコーディングから UTF-8 に変換されません。UTF-* から UTF-8 までのみ。

編集:言い忘れましたが、プログラムは移植可能でなければなりません:Windows、Linux、...

4

4 に答える 4

10

「任意の」(または最も使用されている) 文字エンコーディングを UTF-8 に変換するにはどうすればよいですか?

ICU (International Components for Unicode) がここでのソリューションです。これは一般に、Unicode サポートの最終決定権であると考えられています。Boost.Locale と Boost.Regex でさえ、Unicode に関してはそれを使用します。ラッパー (Boost など) の代わりに ICU を直接使用することをお勧めする理由については、Dory Zidon の回答に関する私のコメントを参照してください。

特定のエンコーディング用のコンバーターを作成します...

#include <ucnv.h>

UConverter * converter;
UErrorCode err = U_ZERO_ERROR;
converter = ucnv_open( "8859-1", &err );
if ( U_SUCCESS( error ) )
{
    // ...
    ucnv_close( converter );
}

...そして、UnicodeStringクラスを適切に使用します。

wchar_t は 2 バイトなので動かないと思います。

のサイズwchar_tは実装定義です。AFAICR、Windows は 2 バイト (UCS-2 / UTF-16、Windows のバージョンによって異なります)、Linux は 4 バイト (UTF-32) です。いずれにせよ、標準は のUnicode セマンティクスを定義wchar_tしていないため、それを使用することは移植性のない当て推量です。推測しないで、ICU を使用してください。

そのような UTF-8 文字列用の isspace()、isalnum()、strlen()、tolower() などの関数はありますか?

UTF-8 エンコーディングではありませんが、とにかく内部的には使用しません。外部表現には UTF-8 が適していますが、内部表現には UTF-16 または UTF-32 が適しています。上記の関数は、Unicode コード ポイント (つまり、UChar32) 用に存在します。参照。uchar.h .

注意: C++ では出力 (std::cout など) は行いません。単語をフィルタリングしてサーバーに送信するだけです。

BreakIteratorを確認してください。

編集:言い忘れましたが、プログラムは移植可能でなければなりません:Windows、Linux、...

まだ言っていない場合は、ICUを使用して、多くのトラブルを回避してください。一見すると少し重いように見えるかもしれませんが、これ最高の実装であり、非常に移植性が高く (Windows、Linux、および AIX で使用しています)、プロジェクトで何度も何度も使用してそのため、API の学習に費やした時間が無駄になりません。

于 2013-04-25T07:42:11.067 に答える
3

これで探しているものがすべて得られるかどうかはわかりませんが、少しは役立つかもしれません。あなたは見てみましたか:

1) Boost.Locale ライブラリ ? Boost.Locale は Boost 1.48 (2011 年 11 月 15 日) でリリースされ、UTF8/16 との間の変換が容易になりました

ドキュメントからのいくつかの便利な例を次に示します。

string utf8_string = to_utf<char>(latin1_string,"Latin1");
wstring wide_string = to_utf<wchar_t>(latin1_string,"Latin1");
string latin1_string = from_utf(wide_string,"Latin1");
string utf8_string2 = utf_to_utf<char>(wide_string);

2) または、変換は C++11 の一部ですか?

#include <codecvt>
#include <locale>
#include <string>
#include <cassert>

int main() {
  std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> convert;
  std::string utf8 = convert.to_bytes(0x5e9);
  assert(utf8.length() == 2);
  assert(utf8[0] == '\xD7');
  assert(utf8[1] == '\xA9');
}
于 2013-04-25T07:13:03.383 に答える
1

C++ で UTF-8 文字列を操作するにはどうすればよいですか? wchar_t は 2 バイトなので動かないと思います。UTF-8 のコードポイントは最大 4 バイトです...

これは簡単です。/ のドロップイン置換である tinyutf8 という名前  のプロジェクト  ありますstd::stringstd::wstring

その後、ユーザーはcodepointsをエレガントに操作できますが、その表現は常に s でエンコードされcharます。


「任意の」(または最も使用されている) 文字エンコーディングを UTF-8 に変換するにはどうすればよいですか?

(C++11)の同様のテンプレートを参照することstd::codecvt_utf8をお勧めします。<codecvt>

于 2016-11-30T15:09:53.557 に答える
0

UTF-8 は、8 番目のビットを利用して非 ASCII (7 ビット コード) に複数のバイトを使用するエンコーディングです。そのため、マルチバイト シーケンス内では ,'\'は見つかりません。'/'そしてisdigit動作します(アラビア語やその他の数字ではありません)。

これは ASCII のスーパーセットであり、すべての Unicode 文字を保持できるため、確実に char および string で使用できます。

HTTP ヘッダーを調べます (大文字と小文字は区別されません)。それらは ISO-8859-1 にあり、空の行と HTML コンテンツの前にあります。

Content-Type: text/html; charset=UTF-8

存在しない場合は、存在する可能性もあります

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="UTF-8">      <!-- HTML5 -->

ISO-8859-1 は Latin 1 であり、コンマ引用符などの特殊文字に 0x80 - 0xBF を使用する Windows Latin-1 拡張である Windows-1252 から変換することをお勧めします。ISO-8859-1 が規定されていましたが、MacOS のブラウザでもこれらを理解できます。

変換ライブラリ: @syam によって既に言及されています。

変換

UTF-16 は考慮しないでください。ヘッダーを読み取り、文字セットのメタ ステートメントまでを 1 バイト文字として開始できます。

シングルバイトエンコーディングから UTF-8 への変換は、テーブルを介して行うことができます。たとえば、Java で生成されたもの: const char* table[]char によってインデックス付けされた a.

table[157] = "\xEF\xBF\xBD";


public static void main(String[] args) {
    final String SOURCE_ENCODING = "windows-1252";
    byte[] sourceBytes = new byte[1];
    System.out.println("    const char* table[] = {");
    for (int c = 0; c < 256; ++c) {
        String comment = "";
        System.out.printf("       /* %3d */ \"", c);
        if (32 <= c && c < 127) {
            // Pure ASCII
            if (c == '\"' || c == '\\')
                System.out.print("\\");
            System.out.print((char)c);
        } else {
            if (c == 0) {
                comment = " // Unusable";
            }
            sourceBytes[0] = (byte)c;
            try {
                byte[] targetBytes = new String(sourceBytes, SOURCE_ENCODING).getBytes("UTF-8");
                for (int j = 0; j < targetBytes.length; ++j) {
                    int b = targetBytes[j] & 0xFF;
                    System.out.printf("\\x%02X", b);
                }
            } catch (UnsupportedEncodingException ex) {
                comment = " // " + ex.getMessage().replaceAll("\\s+", " "); // No newlines.
            }
        }
        System.out.print("\"");
        if (c < 255) {
            System.out.print(",");
        }
        System.out.println();
    }
    System.out.println("    };");
}
于 2013-04-25T07:07:49.847 に答える