質問
私は、次の文字列を持っています:
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]、私は2つの値を取得する "\ x0d \ X0A" だけではなく、 '\のx0d' が。
さらに興味深いのは、 '\ XF5' ですのmyString [6]の値、です。今回はそれがの\ x0dが存在していなかったようなものだし、正しい位置が参照されました。
私の質問は次のようになります。文字列オブジェクト:STD内の\ 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は」改行文字です。
UPDATE:それは可能であることはstd ::文字列は「\ x0dの\のX0A」は、単一の文字としてみなしので、文字列の中で一つだけの位置を占めていますか?このは「\ x0d」はstdに関して「謎」の文字がある::文字列?
解決
あなたは確かにこれはstd::string
で起こっているされていますか? std::string::operator[]
はconst char &
を返すので、それはどのように2つの文字('\x0d'
およびの'\x0a'
)を返すことができますか?
のみ"\x0d\x0a"
をLinuxで使用されているのに対し、前者と後者の変換はWindows環境では比較的一般的ですので、'\x0a'
は通常、Windowsで行末に使用されたこと - 例えば、私はの行動を考えていますfopen
で呼び出されたときに"wt"
。私は似た何かがあなたに起こっているよね。
の編集の:元の質問にあなたのコメントに基づいて、私は何が起こっているかを推測することができると思います。
。私はあなたの文字列が本当にあなたはそれが含まれていると思うものを含んでいないと信じています。メカニズムは、あなたが(おそらくofstream
は?)行末変換を実行しているファイルに出力する文字列を使用しているので、あなたは誤解されています。これは'\n'
(Unixの行末コード)(Windowsの行末コード)を'\r\n'
に変換されていることを意味します。行末翻訳の目的は、オペレーティングシステム間のコードの移植性を高めることです。あなたは、のバイナリモードの中のファイルを開いて、それを阻害することができます。 ofstream
のために、これはあなたがファイルを開いたときにios_base::binary
フラグを指定することで行われますが、このフラグはデフォルトで設定されていません。
(異なる上、行末マーカーの詳細については、Wikipediaの記事のnoreferrer">この
これは、私が起こっていると考えているものです。あなたの文字列が実際に含まれている あなたはそれをこのような何かを出力しています: そのための行末変換は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'
でmyString[5]
が'\x0d\x0a'
として出力されている、そしてそれはあなたを混乱されているものですが、上記のexpalinedます。
他のヒント
ここで間違って起こっていることの一つは、次の行は何を期待しませんです。
std::string myString = "\xff\xff\xff\x00\xff\x0d\x0a\xf5";
これはC ++ std::string(const char *)
にCスタイルのNULLで終わる文字列を変換するように設計されてstd::string
コンストラクタを呼び出します。このコンストラクタは、それがNULLバイト(\ X00)に達するまで、新しいstd::string
に与えられたポインタとコピーしから始まるバイトを読み取ります。これは、strlen()
としてC関数の挙動と一致している。
myString
が構築されたときにだから、それはXFF、\ XFF、\ XFF \バイトで、長さ3の文字列で構成されています。 2より大きいインデックスへのアクセスが(せいぜいランタイムエラーを生成する、または未定義の動作で最悪)配列の末尾からバイトにアクセスしている。
std::string
は中間ヌルバイトを保持することができますが、をNULLバイトがコンストラクタに渡されたCスタイルの文字列を終了すると解釈されるので、のように文字列を初期化するために上記のコンストラクタを使用することはできません。
これは、\のX00バイトで再びあなたのコードをしようとして価値があるだろうただ、それはあなたが既に説明したものとどう違うのか確認するために、何か他のものに変更されます:
std::string myString = "\xff\xff\xff\x01\xff\x0d\x0a\xf5"
また、あなたが得るかを確認するには、上記のコンストラクタの後myString.length()
を確認します。
あなたは、次のコンストラクタで文字列を作成します。string(char const *)
これは、NULがC文字列を終了受けます。だから、最初の0の文字に応じてその長さを見つけます。
:呼び出すことによって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を参照してください。さらに読み取るための/文字列/ の
おそらく、[]演算子を悪用されます。
[]演算子はCONST文字を返します。しかし、あなたはおそらくポインタとしてこれを使用したため、2つの文字を取得している - 私たちはこれを確認するために、あなたの実際のコードを参照する必要があります。
。 あなたはそのための唯一の(正しい)文字を取得している理由はおそらくですので、は0x00は、c-文字列のヌル・ターミネータです。
あなたが取得するときに何が起こる[4]?
は、Visual Studio 2008では、\のX00は、文字列の末尾と考えられています。あなたは[5]あなたがエラーを取得するのmyStringにアクセスしようとするのでmyString.lenghtは3を返します。