配列データについて
投稿者 shu  (社会人)
投稿日時
2014/7/15 07:59:20
少し前に解決した投稿に対し別の問題が発生したのでしょうか?
提示した例外が関係しそうな箇所は
> Dim Data() = Split(Items(0), "\\") '名前の方の値を\\句切り
> If Data(i).Length <> Nothing Then
> a = a + "データ=" + Data(i)
> Writer.WriteLine("ユーザ情報=" & a & ",説明=" & Items(1) & "")
この辺ですね。
配列の大きさを
チェックして処理する必要があります。
提示した例外が関係しそうな箇所は
> Dim Data() = Split(Items(0), "\\") '名前の方の値を\\句切り
> If Data(i).Length <> Nothing Then
> a = a + "データ=" + Data(i)
> Writer.WriteLine("ユーザ情報=" & a & ",説明=" & Items(1) & "")
この辺ですね。
配列の大きさを
チェックして処理する必要があります。
投稿者 カラス  (社会人)
投稿日時
2014/7/15 11:00:55
返信ありがとうございます。
前回の区切りはなんとか出来ました。
指摘していただいた通り、
> If Data(i).Length <> Nothing Then
ここで表示されます。
Redim Data(4)を追加して大きさを指定してみたのですが、
うまくいきません。
前回の区切りはなんとか出来ました。
指摘していただいた通り、
> If Data(i).Length <> Nothing Then
ここで表示されます。
Redim Data(4)を追加して大きさを指定してみたのですが、
うまくいきません。
投稿者 鳩山田小十郎  (社会人)
投稿日時
2014/7/15 12:01:18
>Redim Data(4)を追加して大きさを指定してみたのですが、
これだと出来るのはData(0)~(3)の4個じゃないの?
そこでData(4)を要求されたらそりゃインデックスはみ出てるって言うよ
これだと出来るのはData(0)~(3)の4個じゃないの?
そこでData(4)を要求されたらそりゃインデックスはみ出てるって言うよ
投稿者 魔界の仮面弁士  (社会人)
投稿日時
2014/7/15 13:11:38
>> ・Dataが配列1~5まであるとして、値がなければスルー
分割された Data が 5 個以上になるためには、
その行に、「\\」が 4 個以上存在する必要がありますね。
>> Dim Data() = Split(Items(0), "\\") '名前の方の値を\\句切り
>> For i As Integer = 4 To 0 Step -1
>> If Data(i).Length <> Nothing Then
i の範囲を 4 ~ 0 固定としていますが、その場合、Items(0) 内に
「\\」が4個以上あることを保証しなければなりません。
仮に、「\\」が 4 個未満だった場合、Data(4) は存在しないため、
『インデックスが配列の境界外です』のエラーになってしまうでしょう。
もし、「\\」の数が未定義なのであれば、配列の要素数に応じた数を指定するために、
For i As Integer = UBound(Data) To LBound(Data) Step -1
のように、UBound 関数や GetUpperBound メソッド、あるいは Length プロパティなどを
併用すると良いでしょう。もしくは、For Each を使うというのも手です。
なお、配列数が 5 個に満たない場合には、そもそも列挙したく ないのであれば、
For での列挙前に、「If Data.Length < 5 Then」などの条件で除外しておくと良いでしょう。
5 個以上あることが確実なら、元の「For i As Integer = 4 To 0 Step -1」のままでも問題ありません。
>> If Data(i).Length <> Nothing Then
文字列の長さを調べるのであれば、Nothing と比較するのではなく、
If Data(i).Length <> 0 Then
のように、 0 と比較する方が素直だと思いますよ。
仮に、Data(i) そのものが Nothing では無いことを判定する意図だとすれば、
If Data(i) IsNot Nothing Then
もしくは
If Not Data(i) Is Nothing Then
と書く必要があります。
あるいは、
If String.IsNullOrEmpty( Data(i) ) Then
といった書き方もあります。これは、Nothing か空文字かを判定します。
> a = a + "データ=" + Data(i)
文字列連結時には、「+ 演算子」ではなく「& 演算子」を使うほうが望ましいです。VB では。
>>Redim Data(4)を追加して大きさを指定してみたのですが、
今回、ReDim は不要というか無意味です。
配列サイズの確保は Split 関数側で行われますので、事前に ReDim したとしても、
最終的には「\\」の で分割された総数分の配列を示すことになります。
> これだと出来るのはData(0)~(3)の4個じゃないの?
違います。VB の配列宣言は、『配列の添字の最大値』を指定しますので、
『ReDim Data(0 To 4)』や『ReDim Data(4)』は、Data(0)~Data(4)が確保されます。
分割された Data が 5 個以上になるためには、
その行に、「\\」が 4 個以上存在する必要がありますね。
>> Dim Data() = Split(Items(0), "\\") '名前の方の値を\\句切り
>> For i As Integer = 4 To 0 Step -1
>> If Data(i).Length <> Nothing Then
i の範囲を 4 ~ 0 固定としていますが、その場合、Items(0) 内に
「\\」が4個以上あることを保証しなければなりません。
仮に、「\\」が 4 個未満だった場合、Data(4) は存在しないため、
『インデックスが配列の境界外です』のエラーになってしまうでしょう。
もし、「\\」の数が未定義なのであれば、配列の要素数に応じた数を指定するために、
For i As Integer = UBound(Data) To LBound(Data) Step -1
のように、UBound 関数や GetUpperBound メソッド、あるいは Length プロパティなどを
併用すると良いでしょう。もしくは、For Each を使うというのも手です。
なお、配列数が 5 個に満たない場合には、そもそも列挙したく ないのであれば、
For での列挙前に、「If Data.Length < 5 Then」などの条件で除外しておくと良いでしょう。
5 個以上あることが確実なら、元の「For i As Integer = 4 To 0 Step -1」のままでも問題ありません。
>> If Data(i).Length <> Nothing Then
文字列の長さを調べるのであれば、Nothing と比較するのではなく、
If Data(i).Length <> 0 Then
のように、 0 と比較する方が素直だと思いますよ。
仮に、Data(i) そのものが Nothing では無いことを判定する意図だとすれば、
If Data(i) IsNot Nothing Then
もしくは
If Not Data(i) Is Nothing Then
と書く必要があります。
あるいは、
If String.IsNullOrEmpty( Data(i) ) Then
といった書き方もあります。これは、Nothing か空文字かを判定します。
> a = a + "データ=" + Data(i)
文字列連結時には、「+ 演算子」ではなく「& 演算子」を使うほうが望ましいです。VB では。
>>Redim Data(4)を追加して大きさを指定してみたのですが、
今回、ReDim は不要というか無意味です。
配列サイズの確保は Split 関数側で行われますので、事前に ReDim したとしても、
最終的には「\\」の で分割された総数分の配列を示すことになります。
Dim Data() As String 'この時点では、Data は Nothing
ReDim Data(100) 'この時点では、Data(0)~Data(100) が確保される
Data = Split(Items(0), "\\") 'Data(0)~Data(「\\」の出現数 + 1) な配列で上書きされる
> これだと出来るのはData(0)~(3)の4個じゃないの?
違います。VB の配列宣言は、『配列の添字の最大値』を指定しますので、
『ReDim Data(0 To 4)』や『ReDim Data(4)』は、Data(0)~Data(4)が確保されます。
投稿者 鳩山田小十郎  (社会人)
投稿日時
2014/7/15 13:19:49
あー
VBは最大値の指定だったんですねぇ。
VBは最大値の指定だったんですねぇ。
投稿者 HiDE-Ada  (社会人)
投稿日時
2014/7/15 18:13:08
単に
a="" '' 宣言時にNothingを代入しているだけなので、毎回初期化
For i As Integer = Data.Length-1 To 0 Step -1
a &= "データ=" & Data(i) '' &=って使えたかな?+=ならOK?
Next
でよいのでは?
ただ、結果をみるとわかりますが
ユーザ情報=データ=コメントデータ=パスワード2データ=User3,説明=テスト3
のようになっちゃいますね。
a="" '' 宣言時にNothingを代入しているだけなので、毎回初期化
For i As Integer = Data.Length-1 To 0 Step -1
a &= "データ=" & Data(i) '' &=って使えたかな?+=ならOK?
Next
でよいのでは?
ただ、結果をみるとわかりますが
ユーザ情報=データ=コメントデータ=パスワード2データ=User3,説明=テスト3
のようになっちゃいますね。
投稿者 カラス  (社会人)
投稿日時
2014/7/15 20:27:32
皆様ありがとうございます。
for文の開始を
For i As Integer = UBound(Data) To LBound(Data) Step -1
に変え、If文の開始を
If Data(i).Length <> 0 Thenに変え、さらに&演算子を使用することでうまく値を取ることができました。
HiDE-Adaさんのおっしゃるとおり、aを初期化しないといけなかったのでその処理も入れました。
for文の開始を
For i As Integer = UBound(Data) To LBound(Data) Step -1
に変え、If文の開始を
If Data(i).Length <> 0 Thenに変え、さらに&演算子を使用することでうまく値を取ることができました。
HiDE-Adaさんのおっしゃるとおり、aを初期化しないといけなかったのでその処理も入れました。
Visual Basic 2010を使用しています。
csvから値を読み込み、配列を使ってデータを取り出したいのですが、中々うまくいきません。
「インデックスが配列の境界外です。」と出てしまいます。
タブ句切りをした後に、さらに「\\」で区切って、さらに「\\」で区切った値を分けて使用したいです。
下記の条件も加えてやっています。
・Dataが配列1~5まであるとして、値がなければスルー
・値があればaに値を追加していき、その値を最後に別のcsvに書き込む
・後ろの値から書き込む
test.csv
---------------------------------------------------------
"名前""説明"
"User1" "テスト1"
"User2\\パスワード1" "テスト2"
"User3\\パスワード2\\コメント" "テスト3"
"User4\\パスワード3" "テスト4"
....
---------------------------------------------------------
Dim Reader As New System.IO.StreamReader("C:\test\test.txt")
Dim Writer As New StreamWriter("C:\test\test2.txt")
Dim a As String = Nothing
Dim Items()
Dim Line As String = Reader.ReadLine 'csv1行読み込み
Line = Reader.ReadLine 'ファイルの1行目を飛ばす
Do Until IsNothing(Line) 'データがなくなるまで読み込む
Items = Line.Split(vbTab) 'タブ句切り
Dim Data() = Split(Items(0), "\\") '名前の方の値を\\句切り
For i As Integer = 4 To 0 Step -1
If Data(i).Length <> Nothing Then
a = a + "データ=" + Data(i)
Else
End If
Next
Writer.WriteLine("ユーザ情報=" & a & ",説明=" & Items(1) & "")
Line = Reader.ReadLine '次の行を読み込む
Loop
Reader.Close()
Writer.Close()
助言よろしくお願いします。