1

std::string一部のデータをかなり古い API に渡す必要があるため、aを aに変換しようとしていますchar*(キャストではなくコピー)。

一見、これを行うにはいくつかの方法がありますが、これをベクトルとして行うことが賢明だと提案されました。しかし、これを試してみると、結果が文字化けしました。コードは次のようになります。

const string rawStr("My dog has no nose.");
vector<char> str(rawStr.begin(), rawStr.end());
cout << "\"" << (char*)(&str) << "\"" << endl;

(不快な C キャストに注意してください - static_cast の使用は機能せず、おそらく何かを伝えています)

これを実行すると、次のようになります。

"P/"

明らかに正しくありません。gdbのベクトルを見てみました

(gdb) print str
$1 = std::vector of length 19, capacity 19 = {77 'M', 121 'y', 32 ' ', 100 'd', 111 'o', 
  103 'g', 32 ' ', 104 'h', 97 'a', 115 's', 32 ' ', 110 'n', 111 'o', 32 ' ', 110 'n', 
  111 'o', 115 's', 101 'e', 46 '.'}

最後にnullターミネータがありませんが、これは正しいように見えますが、これは懸念事項です. ベクトル ( sizeof(str)) のサイズは 24 で、文字が 8 ビットとして格納されていることを示しています。

どこが間違っていますか?

4

4 に答える 4

9

のインスタンスstd::vector自体は文字の配列ではなく、配列を指します。(char*)(&str)試すのではなく&str[0]

gdb の出力から判断すると、レガシー API に渡す前に、ベクトルの最後にゼロをプッシュすることもできます。

于 2013-05-30T07:56:39.483 に答える
7

まず、 は[ , )std::stringでカバーされる範囲内の要素として null 終端を含みません。第 2 に、ベクトルのアドレスは、ベクトルのデータの最初の要素のアドレスではありません。これには、またはが必要です:begin()end()&str[0]str.data()

#include <vector>
#include <string>
#include <iostream>

int main()
{
  const std::string rawStr("My dog has no nose.");
  std::vector<char> str(rawStr.begin(), rawStr.end());
  str.push_back('\0');
  std::cout << "\"" << &str[0] << "\"" << std::endl;
  std::cout << "\"" << str.data() << "\"" << std::endl; // C++11
}
于 2013-05-30T08:01:33.240 に答える
2

あなたがする必要がある2つのこと:

1) &str[0]; を使用して、ベクトル内の最初の文字のアドレスを取得します。標準ではベクトル メモリが連続していることを保証しているため、これはまったく問題ありません (少し不自然ではありますが)。&str は、必ずしも最初のデータ要素のアドレスではないベクトルのアドレスであるため、単純に記述することはできません。

2) 標準の c に似た関数を使用して文字を文字列として表示する場合は、ベクトルの最後にヌル ターミネータを挿入します。この 2 番目の点は間違っているかもしれません。rawStr.end() は、「私の犬には鼻がありません」に関連付けられた暗黙の null ターミネータを指していますか?

于 2013-05-30T07:58:39.060 に答える