none
構造体をつかってプログラムしたがエラーが出てうまくいかない。 RRS feed

  • 質問

  • 60過ぎの手習いで、VB2010の勉強を始めました。
    いま構造体を勉強していますが、
    構造体の配列を構造体の要素とする下記のようなプログラムは、
    だめでしょうか?
    どこか間違っているのでしょうか?
    エラーが出ますが、どうすればよいかわかりません。
    教えていただけませんでしょうか?
    よろしくお願いします。


    Public Class Form1
        Public Structure 販売台数
            Dim 販売年月日 As String
            Dim 店別販売台数() As 品名
        End Structure

        Public Structure 品名
            Dim 店名 As String
            Dim テレビ As Integer
            Dim 冷蔵庫 As Integer
            Dim エアコン As Integer
        End Structure

        Private Sub Button1_Click(ByVal sender As System.Object _
                    , ByVal e As System.EventArgs) Handles Button1.Click
            Dim 販売台帳(364) As 販売台数  ’1年分
            Dim 店別販売台数(9) As 品名   ’10店舗分

            販売台帳(0).販売年月日 = "2011/11/29"
            販売台帳(0).店別販売台数(0).店名 = "○○電気"
            販売台帳(0).店別販売台数(0).テレビ = 5
            販売台帳(0).店別販売台数(0).冷蔵庫 = 3
            販売台帳(0).店別販売台数(1).店名 = "△△商店"
            販売台帳(0).店別販売台数(1).エアコン = 2
            販売台帳(1).販売年月日 = "2011/11/29"
            販売台帳(1).店別販売台数(0).店名 = "○○電気"
            販売台帳(1).店別販売台数(0).エアコン = 1

            MessageBox.Show(販売台帳(0).販売年月日 & " " & 販売台帳(0).店別販売台数(0).店名 _
                       & "テレビ" & 販売台帳(0).店別販売台数(0).テレビ & "台販売", "確認")
        End Sub
    End Class


    NullReferenceExceptionはハンドルされませんでした。
    オブジェクト参照がオブジェクト インスタンスに設定されていません。

    2011年11月30日 12:12

回答

  • > Dim 店別販売台数(9) As 品名   ’10店舗分

    ↑ これは意味がないのでは? 以下のようにしたらどうなりますか?

    For i As Integer = 0 To 販売台帳.Length - 1
        販売台帳(i).店別販売台数 = New 品名(9) {}
    Next

    2011年11月30日 15:09
  • 外池と申します。以下、失礼な表現があればご容赦頂きたいです。おそらく、「配列」というものの概念を、一部をご理解されていて、一部をまだご存知ないのだと思います。

    「配列の名前」を宣言することと、複数のデータが実際に格納される「入れ物」を用意することが、プログラムの中で必ずしも一行で表せるわけではない、ということです。「配列の名前」は、「入れ物」に固有の名前ではない、ということも重要な点です。

    Integerの変数の場合、変数名は、すなわち、入れ物に固有の名前です。Integerの「テレビ」に代入した値と、Integerの「冷蔵庫」に代入した値は、必ず別の入れ物に入って、混同されることはありません。(SubやFunctionの呼び出しで使う変数名で例外がありますが割愛します。)

    しかし、配列の名前は、入れ物に固有の名前ではありません。

    入れ物を「指し示す」変数の名前とご理解ください。「指し示す」ことを「参照」と言います。喩えですが、書類キャビネットの扉に取り付ける、取替え可能な識別札を想像してください。札そのものを用意しても、書類キャビネットを確保したことになりません。札を用意して、書類キャビネットを確保して、そして、確保したキャビネットの扉に札を取り付けるわけです。

    もし必要があれば、札を取り外して、別のキャビネットに取り付けることもできます。(例えば、キャビネットが一杯になって、もっと大きなキャビネットに引越しする場合。) あるいは、2つの札を用意して、1つのキャビネットに並べて表示することもできます。(同じ書類・資料であっても、部署によって識別名が違うこともありますよね。)

    配列の場合、まったく同じ手続きを踏みます。(踏めます)

    お示し頂いたプログラムを拝見すると、「販売台数」という構造体の中に「店別販売台数」という名前の配列が宣言されていますが、どこにも「入れ物」を確保する手続きが書かれていません。これがエラーの原因です。

    「オブジェクト参照がオブジェクト インスタンスに設定されていません。」というエラーメッセージは、この喩えに当てはめると、

    「札」は用意されているけれども、「札」はまだキャビネットに取り付けられていない。

    という意味です。


    (ホームページを再開しました)
    2011年12月1日 5:07

すべての返信

  • > Dim 店別販売台数(9) As 品名   ’10店舗分

    ↑ これは意味がないのでは? 以下のようにしたらどうなりますか?

    For i As Integer = 0 To 販売台帳.Length - 1
        販売台帳(i).店別販売台数 = New 品名(9) {}
    Next

    2011年11月30日 15:09
  • SurferOnWwwさん さっそくの投稿ありがとうございます。

    Dim 店別販売台数(9) As 品名  を消し

    For i As Integer = 0 To 販売台帳.Length - 1
        販売台帳(i).店別販売台数 = New 品名(9) {}
    Next

    をいれたら、正常に働くようになりました。

    ありがとうございます。

    しかし、ご教授いただいた

    For i As Integer = 0 To 販売台帳.Length - 1
        販売台帳(i).店別販売台数 = New 品名(9) {}
    Next

    で、なんのために、なにをしているのかわかりません。

    手数をおかけし恐縮ですが、初心者のわたしに理解できるようご教授願えれば幸いです。

    よろしくお願いします。


    2011年11月30日 19:00
  • 「販売台帳の、各店舗の、品目の販売成果を書く欄を作った」といったところでしょう。

    大事なのは「販売成果を書き込んだ」のではなく「販売成果を書く欄を作った」というところです。

     

    それと「エラーがでます」ではなく、発生したエラーを記述して「こんなエラーが出ました」と書きましょう。

    場合によっては開発環境も書きましょう。

    「初心者」という言葉を使うのは控えましょう。

     


    • 編集済み galaco 2011年12月1日 3:31
    2011年12月1日 3:27
  • 発生したエラーをプログラムの後に書いておりましたが、

    わかるように書いていなければ意味ありませんでしたね。

    失礼しました。

    貴重なご指導ありがとうございました。

    これからも、ご指導のほどよろしくお願いします。

     

    2011年12月1日 5:03
  • 外池と申します。以下、失礼な表現があればご容赦頂きたいです。おそらく、「配列」というものの概念を、一部をご理解されていて、一部をまだご存知ないのだと思います。

    「配列の名前」を宣言することと、複数のデータが実際に格納される「入れ物」を用意することが、プログラムの中で必ずしも一行で表せるわけではない、ということです。「配列の名前」は、「入れ物」に固有の名前ではない、ということも重要な点です。

    Integerの変数の場合、変数名は、すなわち、入れ物に固有の名前です。Integerの「テレビ」に代入した値と、Integerの「冷蔵庫」に代入した値は、必ず別の入れ物に入って、混同されることはありません。(SubやFunctionの呼び出しで使う変数名で例外がありますが割愛します。)

    しかし、配列の名前は、入れ物に固有の名前ではありません。

    入れ物を「指し示す」変数の名前とご理解ください。「指し示す」ことを「参照」と言います。喩えですが、書類キャビネットの扉に取り付ける、取替え可能な識別札を想像してください。札そのものを用意しても、書類キャビネットを確保したことになりません。札を用意して、書類キャビネットを確保して、そして、確保したキャビネットの扉に札を取り付けるわけです。

    もし必要があれば、札を取り外して、別のキャビネットに取り付けることもできます。(例えば、キャビネットが一杯になって、もっと大きなキャビネットに引越しする場合。) あるいは、2つの札を用意して、1つのキャビネットに並べて表示することもできます。(同じ書類・資料であっても、部署によって識別名が違うこともありますよね。)

    配列の場合、まったく同じ手続きを踏みます。(踏めます)

    お示し頂いたプログラムを拝見すると、「販売台数」という構造体の中に「店別販売台数」という名前の配列が宣言されていますが、どこにも「入れ物」を確保する手続きが書かれていません。これがエラーの原因です。

    「オブジェクト参照がオブジェクト インスタンスに設定されていません。」というエラーメッセージは、この喩えに当てはめると、

    「札」は用意されているけれども、「札」はまだキャビネットに取り付けられていない。

    という意味です。


    (ホームページを再開しました)
    2011年12月1日 5:07
  • 外池さんの、よくわかるようにとの懇切丁寧な”たとえ話”での説明ありがとうございました。

    おかげさまで、私なりに理解できたつもりです。

    SurferOnWwwさん、galacoさん、外池さん大変お世話になりました。

    これからもご指導よろしくお願いします。

     

    2011年12月1日 9:42
  • すでに解決済みで、今さらながらのレスですが・・・

    > For i As Integer = 0 To 販売台帳.Length - 1
    >     販売台帳(i).店別販売台数 = New 品名(9) {}
    > Next
    >
    > で、なんのために、なにをしているのかわかりません。

    外池さんの "札" と "キャビネット" の例を使うと、以下のよ
    うなことです。

    (1) 「New 品名(9) {}」はキャビネットの準備。

    (2) 「販売台帳(i).店別販売台数」は配列の i 番目の札。

    (3) 「=」 はキャビネットに札を貼り付け。

    (4) For ループで、i を 0 から 364 まで変化させて上記 (1)
    ~ (3) を、繰り返す。

     

    2011年12月1日 12:39