- PR -

while文とfor eachの違い及び、不定な配列サイズの宣言の仕方

1
投稿者投稿内容
ネーブル
常連さん
会議室デビュー日: 2006/08/26
投稿数: 27
投稿日時: 2006-09-02 09:24
今日はよろしくお願いします。
リストビューで選択した項目を別の配列にコピーしようと思いMSDNを参考に下記のように書いてみました。
コード:
array<String^>^ listname = gcnew array<String^>(255);
ListView::SelectedListViewItemCollection^ filename = this->listView1->SelectedItems;
	System::Collections::IEnumerator^ myEnum = filename->GetEnumerator();
	 array<String^ >^ result = gcnew array<String^>(255);
	int i = 1;
	while ( myEnum->MoveNext() ) {
		ListViewItem^ item = safe_cast<ListViewItem^>(myEnum->Current);
		result[i] = item->SubItems[ 5 ]->Text;
		MessageBox::Show(result[ i ]) ;
		i++;
	}



【質問】1
array<String^ >^ result = gcnew array<String^>(255);
現在このように予め予想してサイズを宣言していますが配列のサイズが不定な場合の
宣言はどのように書いたらよいのでしょうか?

【思いつく方法】
一行に必ず、配列の要素一つ含まれている前提で、while構文でカウンタを回して
ReadEndLineで行数を数えるれば出来ると思うのですが、他に簡潔な方法はありませんでしょか。

【質問】2
上記のコードをfor eachの構文で書くにはどう書けばよいでしょうか。

【思いつく方法】
このようにしましたが、itemのキャストが巧くいかずエラーとなります。
コード:
array<String^>^ listname = gcnew array<String^>(255);
ListView::SelectedListViewItemCollection^ filename = this->listView1->SelectedItems;
ListViewItem^ item = safe_cast<ListViewItem^>(myEnum->Current);
	for each( item in filename);{
		result[i] = item;
		MessageBox::Show(result[i]);
		i++;
	}


Blue
大ベテラン
会議室デビュー日: 2005/09/12
投稿数: 230
お住まい・勤務地: 知っている人は知っている
投稿日時: 2006-09-02 12:12
引用:

配列のサイズが不定な場合の宣言はどのように書いたらよいのでしょうか?


this->listView1->SelectedItemsのCountプロパティでいくつアイテムを持っているかを取得できます。
よって、
コード:

array<String^>^ result = gcnew array<String^>(filename->Count);


となります。

もっとも、本当に上限がわからない場合は、Listジェネリッククラスを使いますが。

引用:

上記のコードをfor eachの構文で書くにはどう書けばよいでしょうか。


for eachでかく場合
filename->GetEnumerator()
のようにIEnumeratorを取得せずに、
コード:

//ListViewItem^ item = safe_cast<ListViewItem^>(myEnum->Current); // 削除
for each(ListViewItem^ item in filename);{


とすればいいでしょう。

ちょっとまとめると、
コード:

    array< String^ >^ result = gcnew array< String^ >( this->listView1->SelectedItems->Count );
    int i = 0;
    for each ( ListViewItem^ item in this->listView1->SelectedItems )
    {
        result[ i ] = item->SubItems[ 5 ]->Text;
        MessageBox::Show( result[ i ] );
        i++;
    }

ネーブル
常連さん
会議室デビュー日: 2006/08/26
投稿数: 27
投稿日時: 2006-09-02 17:02
Blueさんありがとうございます、そしてお世話になります。Countプロパティ、for eachの使い方、良く理解できました。
ところで最後にもう一点質問させてください。
引用:

もっとも、本当に上限がわからない場合は、Listジェネリッククラスを使いますが。


下記のコードの様な場合でしょうか?
このコードは前段を省略していますがOpenFileDialogメッソドでファイルを開いて、
ファイル名をpathに受けて、コンボボックスの項目を取得しています、この場合
コード:
array<String^>^ listname = gcnew array<String^>(255);


ここで、256行以上のファイルを開くと例外エラーが発生しますこの場合は
どのようにしたら良いでしょうか
コード:
array<String^>^ listname = gcnew array<String^>(path->LastIndexOf);


読込んだ行数をpathに着目してこのようにしてみましたが、使い方が間違っているみたいです^^);
コード:
// コンボボックスの項目を取得
private: bool LoadCombBox( String^ path ) {
	StreamReader^ sr = gcnew StreamReader( path,
		System::Text::Encoding::GetEncoding( "shift-jis" ));
	array<String^>^ listname = gcnew array<String^>(255);		// 読込んだファイル全行を格納する配列listnameを準備
	ArrayList^ myALList = gcnew ArrayList;			// 全種類のlistnameを格納するリスト型配列myALListを準備
	int i = 1;
	String^ buff;
	String^ tmp = sr->ReadLine()->Substring(37, 12);		// 読込んだ行の37文字目から12文字をtmpにセット
	myALList->Add(tmp);
	while ((buff = sr->ReadLine()) != nullptr) {			// ファイルの終わりまで一行づつ読込む
		listname[i] = buff->Substring(37, 12);
		if (myALList->Contains(listname[i]) == false){	// リスト型配列myALListからlistnameを検索し、含まれていない場合myALListにfilenameを加える
		myALList->Add(listname[i]);
		//MessageBox::Show(listname[i]);
	}
	i++;
}


Blue
大ベテラン
会議室デビュー日: 2005/09/12
投稿数: 230
お住まい・勤務地: 知っている人は知っている
投稿日時: 2006-09-02 17:45
引用:

ネーブルさんの書き込み (2006-09-02 17:02) より:
コード:
// コンボボックスの項目を取得
private: bool LoadCombBox( String^ path ) {




の用途が良くわかりませんけど。
(bool型の値を返していないのと、せっかく取得した情報がこの関数内でしか有効でない)

それと、myALListがあるならばlistnameの必要性はあるのか?と思います。
コード:
using namespace System::Collections::Generic;

private: bool LoadCombBox( String^ path ) {
    StreamReader^ sr = nullptr;
    List< String^ >^ listname = gcnew List< String^ >();
    
    try
    {
        sr = gcnew StreamReader( path, Text::Encoding::GetEncoding( L"Shift_JIS" ) );
        String ^line, ^temp;
        while ( ( line = sr->ReadLine() ) != nullptr )
        {
            temp = line->Substring( 37, 12 );
            if ( !listname->Contains( temp ) )
            {
                listname->Add( temp );
            }
        }
    }
    catch ( Exception^ ex )
    {
        // エラー処理
        MessageBox::Show( ex->Message );
        // return false;
    }
    finally
    {
        if ( sr != nullptr )
            sr->Close();
    }
    // return true;
}


ネーブル
常連さん
会議室デビュー日: 2006/08/26
投稿数: 27
投稿日時: 2006-09-02 18:19
Blueさんお世話になります。
説明不足でした。
引用:

用途が良くわかりませんけど。 (bool型の値を返していないのと、せっかく取得した情報がこの関数内でしか有効でない)


前段で〜、と書いた部分ですが、そこの部分でファイルのオープンと関数の呼出しその戻値をboolで
判定しているためです。

呼出側の関数一部抜粋
コード:
if (LoadLogFile( dlg->FileName ) == false ){
	MessageBox::Show("ファイルの読込みに失敗しました")
	}
return;


コード:
List< String^ >^ listname = gcnew List< String^ >();


こういう使い方もあるのですね、参考になりました、明確な回答ありがとうございました。
1

スキルアップ/キャリアアップ(JOB@IT)