stringstreamをCString(もしくはstringやchar)で取得するには?

解決


なちゅら  2010-01-15 23:01:03  No: 71262

CString text = "あいう";

"    あいう"
と処理して取得しようとしています。

CString text = "あいう";
stringstream s_txt;
s_txt << setw(10) << setfill(' ') << text;
text = s_txt.str().c_str();   //★

CStringではsetfillが使えず、
調べたところstringstreamならできそうだったので
上記のようにしました。
…が、★実行後のtextは"  00385514"でした。
そもそもやり方が間違っていそうな気はするんですが、
どうすれば空白埋めができるでしょうか?
それとも、こういうことはできないのでしょうか…

VC++6.0  MFCダイアログベースです。
よろしくお願いします。


みい  2010-01-15 23:20:12  No: 71263

・Formatで書式を"%10.10s"にして"あいう"を入れる
・GetLengthで文字数調べて足りない分だけInsertでスペースを挿入
どちらでもCStringにスペースを入れることができます


なちゅら  2010-01-15 23:26:20  No: 71264

ご指摘の方法を試した所、できました!
setfillを使おうとするからいけなかったんですね…

みいさん、ありがとうございました。


επιστημη  URL  2010-01-15 23:50:35  No: 71265

/*
 option: 
  -EHsc -DAFX_DLL
    - or -
  -EHsc -DAFX_DLL -DUNICODE -D_UNICODE
*/

#include <afxwin.h> // CString
#include <iostream> // cout, wcout
#include <iomanip>  // setw, setfill
#include <sstream>  // stringstream, wstringstream

using namespace std;

#ifndef UNICODE
int main() {
  CString text = "あいう";
  stringstream s_txt;
  s_txt << setw(10) << setfill(' ') << text;
  text = s_txt.str().c_str();   //★
  cout << '[' << static_cast<const char*>(text) << ']' << endl; ;
}
#endif
> setfillを使おうとするからいけなかったんですね…

↓いけなくないですがー

#ifdef UNICODE
#include <locale>

int main() {
  wcout.imbue(locale("japanese"));
  CString text = "あいう";
  wstringstream s_txt;
  s_txt << setw(10) << setfill(L' ') << static_cast<const wchar_t*>(text);
  text = s_txt.str().c_str();   //★
  wcout << '[' << static_cast<const wchar_t*>(text) << ']' << endl; ;
}
#endif


yoh2  2010-01-16 08:28:04  No: 71266

> s_txt << setw(10) << setfill(' ') << text;

VC++6だと、ここの 「<< text」で、std::stringstream::operator<<(const void *)が
呼ばれている節があります。「<< static_cast<LPCTSTR>(text)」なら
std::operator<<(ostream &, const char *) が呼び出されるようですが。
※ MBCS版のみ調査。

気になったのでちょっと実験してみた所、operator const char *()による
型変換と、オーバーロードされたoperator<<()との組み合わせによって
妙なふるまいをすることが分かりました。

-----------------------------------------------------------------
/*
 * 3つあるoperator<<()は、basic_ostream関連のoperator<<()に、
 * 同様のプロトタイプを持つものがあります。
 * (テンプレートパラメータや戻り値型は端折ってますが)
 */
#include <iostream>

struct X
{
    // operator<<() その1
    void operator<<(const void *) { std::cout << "X::operator(const void *)\n"; }
};

// operator<<() その2
template<typename T>
void operator<<(X &, const T *) { std::cout << "::operator<< <T>(X &, const T *)\n"; }

// operator<<() その3
void operator<<(X &, const char *) { std::cout << "::operator<<(X &, const char *)\n"; }

struct Y
{
    operator const char *() const { return "hoge"; }
};

int main()
{
    X x;
    Y y;

    x << y;                                             // A
    x << static_cast<const char *>(y);                  // B

    std::cout << y << '\n';;                            // C
    std::cout << static_cast<const char *>(y) << '\n';  // D

    return 0;
}
-----------------------------------------------------------------

VC++6の場合、Aではoperator<<()その1が呼ばれ、Bではその3が呼ばれました。
また、Cでは文字列のアドレスが出力され、Dでは文字列の内容が出力されました。
一方、VC++2008とgcc-4.3.4の場合、A、Bではともにoperator<<()その3が
呼ばれ、C、Dではともに文字列の内容が出力されました。

さらに奇妙なことに、結局呼ばれることがないはずのoperator<<()その2の
定義を消すと、VC++6でもVC++2008やgccと同様の結果になりました。

まあ、C++98以前の処理系のVC++6に、C++98規格を持ち出して云々するのも
ナンセンスなのでやめておきますが、明示的にキャストしてやれば
期待通りになるのでひとまずの回避策になりそうです。

# というか、関数選択規則が複雑すぎるので、C++規格を引っ張り出して
# 検証するのが面倒臭いというのが本音だったり。
## ついでに言うと、Digital Mars C++ 8.42nではさらに違った挙動に。
## 何なんだ一体……


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加