-1

次の文字列があります。

index                                       0   1   2   3   4   5   6   7
std::string myString with the content of "\xff\xff\xff\x00\xff\x0d\x0a\xf5"

myString[3] を参照しているときに、期待される '\x00' 値が得られます。

しかし、myString[5] を参照すると、'\x0d' ではなく 2 つの値 "\x0d\x0a" が得られます。

さらに興味深いのは、'\xf5' である myString[6] 値です。今回は \x0d が存在せず、正しい位置が参照されたようです。

私の質問は次のとおりです: std:string オブジェクトの \x0d 文字の特別な点は何ですか? インデックス作成時にスキップされるのはなぜですか? 数え方はこんな感じです。

index                     0   1   2   3   4   5   5   6
std::string myString = "\xff\xff\xff\x00\xff\x0d\x0a\xf5"

コメントとして、'\x0d' 文字は 13 番目の ASCII 文字「キャリッジ リターン」であり、'\x0a' は改行文字です。

更新: std::string が "\x0d\x0a" を単一の文字と見なし、文字列内の 1 つの位置のみを占める可能性はありますか? この '\x0d' は std::string に関して「謎」の文字ですか?

追加情報: http://en.wikipedia.org/wiki/Newline

4

5 に答える 5

9

これは で起こっていstd::stringますか? std::string::operator[]を返すconst char &ので、どうやって 2 つの文字 ('\x0d' '\x0a') を返すのでしょうか?

とは言っても、"\x0d\x0a"通常は Windows では行末に使用されるのに対し、'\x0a'Linux では のみが使用されるため、前者から後者への変換は Windows では比較的一般的です。たとえば、 でfopen呼び出されたときの動作を考えてい"wt"ます。あなたにも似たようなことが起こっていると思います。

編集:元の質問に対するコメントに基づいて、何が起こっているのか推測できると思います。

あなたの文字列には、実際には含まれていると思われるものが含まれていないと思います。文字列をファイルに出力するために使用しているメカニズム(おそらくofstream?)が行末変換を実行しているため、誤解されています。これは、'\n'(Unix の行末コード) が'\r\n'(Windows の行末コード) に変換されていることを意味します。行末変換の目的は、オペレーティング システム間でのコードの移植性を高めることです。ファイルをバイナリモードで開くことにより、これを禁止できます。の場合ofstream、これはファイルを開くときにフラグを指定することによって行われios_base::binaryますが、このフラグはデフォルトでは設定されていません。

(さまざまなオペレーティング システムでの行末マーカーの詳細については、このウィキペディアの記事を参照してください。)

これが私が信じていることです。あなたの文字列には実際に含まれています

index                 0   1   2   3   4   5   6
myString contents  "\xff\xff\xff\x00\xff\x0a\xf5"

次のように出力しています。

ofstream file("myfile.txt");
for(size_t i=0; i<myString.size(); i++)
    ofstream << myString[i];

上で説明した行末変換のため、'\x0a'inmyString[5]は として出力されており'\x0d\x0a'、それがあなたを混乱させています。

于 2009-09-02T08:11:44.037 に答える
9

ここで間違っていることの 1 つは、次の行が期待どおりに動作しないことです。

std::string myString = "\xff\xff\xff\x00\xff\x0d\x0a\xf5";

これはstd::string(const char *)、C スタイルの null で終わる文字列を C++ に変換するように設計されたコンストラクターを呼び出しますstd::string。このコンストラクターは、指定されたポインターから始まるバイトを読み取りstd::string、null バイト (\x00) に達するまでそれらを新しいポインターにコピーします。これは、 などの C 関数の動作と一致していstrlen()ます。

したがって、あなたmyStringが構築されるとき、バイト \xff、\xff、\xff を持つ長さ 3 の文字列で構成されます。2 より大きいインデックスへのアクセスは、配列の末尾から離れたバイトにアクセスしています (せいぜい実行時エラーが発生するか、最悪の場合未定義の動作が発生します)。

std::stringは中間の null バイトを保持できますが、上記のコンストラクターを使用してそのような文字列を初期化することはできません。これは、null バイトがコンストラクターに渡された C スタイルの文字列を終了するものとして解釈されるためです。

\x00 バイトを別のものに変更して、コードをもう一度試して、既に説明したものとどのように異なるかを確認する価値があります。

std::string myString = "\xff\xff\xff\x01\xff\x0d\x0a\xf5"

また、myString.length()上記のコンストラクターの後に何が得られるかを確認してください。

于 2009-09-02T09:02:32.313 に答える
2

次のコンストラクターで文字列を作成します。string(char const *)

NUL で終了する C 文字列を受け取ります。そのため、最初の 0 文字に従って長さを見つけます。

size: を指定する他のコンストラクターを使用する必要がありますstring(char const *,size_t n)

std::string myString("\xff\xff\xff\x00\xff\x0d\x0a\xf5",8);

詳細については、 http://www.cplusplus.com/reference/string/string/string/を参照してください。

于 2009-09-02T09:07:47.810 に答える
0

Visual Studio 2008 では、\x00 は文字列の末尾と見なされます。したがって、myString.length は 3 を返します。myString[5] にアクセスしようとすると、エラーが発生します。

于 2009-09-02T08:42:31.493 に答える
0

[] 演算子の使い方が間違っている可能性があります。

[] 演算子は const char を返します。ただし、おそらくこれをポインターとして使用しているため、2 つの文字を取得しています。これを確認するには、実際のコードを確認する必要があります。

0x00 は c-string の null ターミネータであるため、おそらく 1 つの (正しい) 文字しか得られないのはそのためです。

[4] を取得するとどうなりますか?

于 2009-09-02T08:21:07.060 に答える