文字列を文字の配列に変換しようとしています。(VC++/CLR)
以下のように記述したらエラーがでてしまい試行錯誤しています。
。
rray< char >^ g_CallNo
の部分を
g_CallNo
と変えてみましたが、同じエラーが出ます。
何が原因なのでしょうか?
【エラー内容】
error C2440: '=' : 'cli::array<Type,dimension> ^' から 'char' に変換できません。
///以下ソースです///////////////////////
#include "stdafx.h"
char g_CallNo[48];
namespace fsend
{
using namespace System;
public ref class Form1 : public System::Windows::Forms::Form{
//中略
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
String ^ s = txtbx_CallNo->Text;
array< char >^ g_CallNo = s->ToCharArray();
fsend_Call( g_CallNo );
}
};
}
/////////////////////////////////////ここまで////////////
C++学習を始めたばかりなのでそこも加味して、チェックしていただければ幸いです。
不足情報有れば、お伝えください。
よろしくお願いします。
System::String::ToCharArray
の戻り値はarray<System::Char>^です。
System::Char は char とは違います。
(Javaのcharの扱いと一緒だけど。)
.NET Frameworkを使うのであれば、charではなくSystem::Char(もしくはwchar_t)を
デフォルトで扱うようにしましょう。
どうしてもcharでなければいけない場合はそのつど文字コード変換してください。
ただし、Unicode→CP932ですとCP932で表現できない文字があると情報が落ちますけど。
Blueさん
分かりやすいご説明ありがとうございます。
Char→System::Charに変え、C2440のエラーは消えました。
勉強になります。
ただ…
ソースの最後の方の、
fsend_Call関数の中で、char型の変数を使っているのですが、
その変数が別プロジェクトと共有しているヘッダファイルに定義されており、
ヘッダファイルを書き換えることができません。
そこで、つど文字コードを変換する方法でやってみようと思います。
(wctomb 関数を使うとよいのでしょうか?)
結果報告を含め、改めて〆させて下さい。
System::Charの間違いかな?とは思うけど、一応
System::Runtime::InteropServices::Marshalクラスの
StringToHGlobalAnsi/FreeHGlobal
で一時的にAnsi文字列を得ることもできます。
#変換できない文字はありえます。
> wctomb 関数を使うとよいのでしょうか?
いいけど呼び出す前に一度だけ locale 設定の呪文を唱えましょう。
subaruさん、επιστημηさん
ありがとうございます。
アドバイスを参考にソースを追加してみました。
が、以下のエラーが出てしまいました。
【エラー内容】
error C2664: 'wcstombs' : 2 番目の引数を 'cli::array<Type> ^' から 'const wchar_t *' に変換できません。
二番目の引数はconstでなければ入らないのでしょうか?
だとすれば、このプログラムの場合、値をテキストボックスから受け取るので、wcstombs関数以外の方法を探さないといけないということ(??)なのでしょうか?
///以下ソースです//////////////////////////////
char g_CallNo[24];
public ref class Form1 : public System::Windows::Forms::Form{
//中略
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
String ^ s = txtbx_CallNo->Text;
array< wchar_t >^ w_CallNo = s->ToCharArray();//wchr_ban配列に変換
g_CallNo = (char)malloc(40);
setlocale(LC_ALL, "ja");
wcstombs( g_CallNo, w_CallNo, 40);//ワイド文字→マルチバイト
fsend_Call( g_CallNo );
}
};
}
**************************************************
int fsend_Call( char* CallNo ){
…
}
////////////////////////////ソースここまで/////
何か対処法はあるでしょうか?
どうぞよろしくお願いします。
ご参考に
http://social.msdn.microsoft.com/forums/ja-JP/vcexpressja/thread/00caa8bb-35e8-42b7-8721-c602ec1f30cc/
sample1かsample2のやり方が適当かな。
array<XXX>^ はmanaged配列であり、wcstombsが受け取れるnative配列(ポインタ)とは互換性がありません。
pin_ptrでnative領域に釘留めしてやらにゃならんでしょう。
↓コレではどうでしょうか。
pin_ptr<wchar_t> w_CallNo = &(s->ToCharArray())[0];
wcstombs( g_CallNo, w_CallNo, 40);
Blueさん、επιστημηさん
ありがとうございます。
おかげさまで旨く行きました。
以下に結果載せておきます(変数名少し変わっています)。
勉強になりました。
///以下ソースです//////////////////////////////////////////
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
String^ str_no;
char chr_no[48];
char * pt01;
char * pt02 = 0;
array< unsigned char >^ ar_no;
pin_ptr<const unsigned char> pi_no;
str_no = this->TBX_callNO_ch1->Text; //TxetBoxの文字列取得
ar_no = System::Text::Encoding::GetEncoding( L"Shift_JIS" )->GetBytes( str_no );
pi_no = &ar_no[ 0 ]; //アドレスを代入
strncpy_s( chr_no, 48, static_cast<const char*>( static_cast<const void*>( pi_no ) ), ar_no->Length );
for(pt01=g_CallNo, pt01=chr_no;
'0'<=*pt01&&*pt01<='9';
pt01++, pt02++)
*pt01 = *pt02; // ポインター操作での代入
*pt01 = '\0'; //最後にNULL付加
fsend_Call( g_CallNo ); // 配列渡し
}
**************************************************
int fsend_Call( char* CallNo ){…}
////////////////////////////ソースここまで/////////////////
string→charは思ったより大変なのですね。
ありがとうございました。
解決です。
編集 削除...そんなにめんどくさいかなぁ...
#include <iostream>
int main() {
System::String^ input = L"このUNICODE文字列をShift_JISに変換する";
char result[100];
char* p = result;
for each ( unsigned char ch in
System::Text::Encoding::GetEncoding(L"Shift_JIS")->GetBytes(input) ) *p++ = ch;
*p = '\0';
std::cout << '[' << result << ']';
}
επιστημηさん
こんなにすっきりしたコードになるんですね。
ありがとうございます。