環境は、VC++でMFCでやってます。
・エディットボックスから取得した文字をcharのバッファに
入れたいのですが、次の方法でやっているとなぜか落ちるように
なりました。
エディットボックスから取得した文字が10文字より大きいなら
10文字にしてそれをバッファに入れます。文字列の終端コードは
10文字の場合は入らなくてもいいです。
10文字未満の場合は、残りを0で埋めなければなりません。
char CharArray[10];
CString Str(");
GetDlgItem( IDC_EDIT1 )->GetWindowText( Str );
// 10文字にカット
if(Str.GetLength(10) >= 10){
Str = Str.Left( 10 );
}
// charのバッファに格納
memcpy( CharArray, Str.GetBuffer(0), sizeof(char) * 10);
・今度は、逆にcharのバッファに入っている文字をCStringにいれて
エディットボックスに出力したいのですが、同様に落ちるように
なりました。
charのバッファには、終端コードが含まれていない場合もあります。
charのバッファには、10文字未満の文字列が入っている場合は、
残りのバッファは、0で埋められています。
CString Msg;
Msg = CharArray;
Msg = Msg.Left( 10 );
GetDlgItem( IDC_EDIT )->SetWindowText( Msg );
これらのソースに問題があるのでしょうか?
もっと何か効果的なやり方があるように思えるのですが、
うまく考えつかなかったので、どなたかご存知の方教えてください。
>char CharArray[10];
>CString Str(");
>GetDlgItem( IDC_EDIT1 )->GetWindowText( Str );
>// 10文字にカット
>if(Str.GetLength(10) >= 10){
> Str = Str.Left( 10 );
>}
>// charのバッファに格納
>memcpy( CharArray, Str.GetBuffer(0), sizeof(char) * 10);
あんまし、自信なしですが
1. CharArray[10+1];
ZeroMemory(CharArrya, sizeof(CharArray)); // とでもしておきますか。
2. GetLength()ですか。(引数なし)
3. 0ぢゃなくて、GetBuffer(10)ですか。
4. ReleaseBuffer()してますか?
>もっと何か効果的なやり方があるように思えるのですが、
wsprintf(CharArray, %s, Str);
のほうが楽チンかな。
#書き込み側は問題ないんぢゃない。(^^;
void CPRG1Dlg::OnButton1()
{
// TODO: この位置にコントロール通知ハンドラ用のコードを追加してください
char CharArray[10] ;
CString Str(") ;
GetDlgItem (IDC_EDIT1)->GetWindowText (Str) ;
// 10文字にカット
// if(Str.GetLength(10) >= 10){
if(Str.GetLength () > 10) {
Str = Str.Left (10) ;
}
// charのバッファに格納
// memcpy ( CharArray, Str.GetBuffer (0), sizeof (char) * 10) ;
memset (CharArray, 0x00, sizeof (CharArray)) ;
// charのバッファには、10文字未満の文字列が入っている場合は、
// 残りのバッファは、0で埋められています。
strcpy (CharArray, Str) ;
MessageBox (CharArray) ;
//・今度は、逆にcharのバッファに入っている文字をCStringにいれて
// エディットボックスに出力したいのですが、同様に落ちるように
// なりました。
Str.Empty () ;
Str.Insert (0, CharArray) ;
GetDlgItem (IDC_EDIT1)->SetWindowText (Str) ;
}
> // charのバッファに格納
> memcpy( CharArray, Str.GetBuffer(0), sizeof(char) * 10);
Strの長さが10文字未満の場合、Strのバッファは10バイトより
短い可能性があります。
その場合、Strのバッファからはみ出た部分をアクセスしようとして、
場合によっては落ちるでしょう。
strncpyのヘルプを見てみると、まさに要望どおりの動作をする
関数であることが分かります。よって、以下の2行でOKです。
GetDlgItem( IDC_EDIT1 )->GetWindowText( Str );
strncpy(CharArray, Str, sizeof(CharArray));
> CString Msg;
> Msg = CharArray;
CStringへ文字配列を代入する時には、代入される文字配列の終端記号までを
コピーしようとします。CharArrayに10文字いっぱい入っていて終端記号がない場合、
CharArrayバッファからはみ出た部分をアクセスしようとして、
場合によっては落ちるでしょう。
CStringのコンストラクタには、文字列の長さを指定できるバージョンがあります。
よって、以下の2行で可能です。
CString Msg(CharArray, 10);
GetDlgItem( IDC_EDIT )->SetWindowText( Msg );
>エディットボックスから取得した文字が10文字より大きいなら
>10文字にしてそれをバッファに入れます。文字列の終端コードは
>10文字の場合は入らなくてもいいです。
>10文字未満の場合は、残りを0で埋めなければなりません。
char CharArray[10] = {0}; // とりあえず0クリア
char buffer[11]; // NULを含む為,11Bytes確保
int r = GetDlgItem(IDC_EDIT1)->GetWindowText(buffer, 11); // 最大10Bytes読む。
memcpy(CharArray, buffer, r); // 複製
終端コードを常にいれて良いなら,
char CharArray[10];
int r = GetDlgItem(IDC_EDIT1)->GetWindowText(CharArray, 10);
memset(CharArray + r, 0, 10 - r); // 0クリア
Bunさん、Kさん、dairygoodsさん、YuOさん、ありがとうございました。
普段、MFCばかり使ってポインタの意識が薄れていました。
>Bunさん、Kさん
ご指摘のとおり、
GetLength()でした。これは、記述ミスです。
>dairygoodsさん
感動しました。いろいろ考えたのにこんなに簡単にやってのけるとは
この方法でやってみます。
・文字列取得時
GetDlgItem( IDC_EDIT1 )->GetWindowText( Str );
strncpy(CharArray, Str, sizeof(CharArray));
(理由)
取得した文字列が10文字未満のとき0埋めをしてくれ、
10文字以上のとき10文字分のサイズを取得してくれる
・文字列出力時
CString Msg(CharArray, 10);
GetDlgItem( IDC_EDIT )->SetWindowText( Msg );
(理由)
バッファに格納されている10文字分をCStringに入れてくれる
ただ、気になる点が1つ
CString Msg(CharArray, 10);
charのバッファの最後に終端コードが入ってなくても
大丈夫なのでしょうか?
コンストラクタで自動的に入れてくれるのでしょうか?
> ただ、気になる点が1つ
> CString Msg(CharArray, 10);
> charのバッファの最後に終端コードが入ってなくても
> 大丈夫なのでしょうか?
自動的に入ります。
気になる点があったら、自分でプログラムを作って確認したほうが
早くて確実ですよ(^^;
ありがとうございました。
自分でも確認はしたのですが、不安なもので...
でも解決してよかったです。