エディットボックスからcharのバッファに格納

[戻る]
roccy 2002/04/13(土) 14:11:06
環境は、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 );

これらのソースに問題があるのでしょうか?
もっと何か効果的なやり方があるように思えるのですが、
うまく考えつかなかったので、どなたかご存知の方教えてください。

Bun 2002/04/13(土) 15:35:52
>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);
のほうが楽チンかな。

#書き込み側は問題ないんぢゃない。(^^;

K 2002/04/13(土) 17:30:45
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) ;
}

dairygoods 2002/04/13(土) 21:14:36
> // 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 );

YuO [E-Mail] 2002/04/14(日) 20:13:54
>エディットボックスから取得した文字が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クリア

roccy 2002/04/15(月) 00:31:06
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のバッファの最後に終端コードが入ってなくても
大丈夫なのでしょうか?
コンストラクタで自動的に入れてくれるのでしょうか?

dairygoods 2002/04/15(月) 10:04:39
> ただ、気になる点が1つ
> CString Msg(CharArray, 10);
> charのバッファの最後に終端コードが入ってなくても
> 大丈夫なのでしょうか?

自動的に入ります。

気になる点があったら、自分でプログラムを作って確認したほうが
早くて確実ですよ(^^;

roccy 2002/04/15(月) 12:07:27
[[解決]]
ありがとうございました。
自分でも確認はしたのですが、不安なもので...
でも解決してよかったです。

古いスレッドには追加発言できません。