0

Hey! I am trying to put some data from a textbox to an existing array.

Basically when I double click a node, the program will split the information from a text file to an array, parts[], and search for the relevant data to display in the textboxes.

Say the users make changes in the textboxes, I would like to read the information and put it back into parts[] and join back parts[] to a string and save it back to the original text file. (My code follows below.) When I run it, an error says Index was outside the bounds of the array. Did I do something wrong?

[edited] Here the full code:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
    private Field[] fieldArray = new Field[100];
    private string[] parts;

    public Form1()
    {
        InitializeComponent();
    }

    private void populateTree(string path, TreeNode tv1)
    {
        string[] dir = Directory.GetDirectories(path);
        foreach (string d in dir)
        {
            string entry = Path.GetFileName(d);
            TreeNode t = tv1.Nodes.Add("Folder", entry, 0);
            populateTree(d, t);
        }
        string[] files = Directory.GetFiles(path);
        foreach (string f in files)
        {
            string entry = Path.GetFileName(f);
            tv1.Nodes.Add(f, entry, 1);
        }
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        //populate the tree
        TreeNode t = treeView1.Nodes.Add("Units");
        populateTree(@"..\units\", t);

        for (int i = 0; i < 100; i++)
        {
            fieldArray[i] = new Field();
        }
        fieldArray[0].label = new Label();
        fieldArray[0].label.AutoSize = true;
        fieldArray[0].label.Location = new System.Drawing.Point(323, 9);
        fieldArray[0].label.Name = "Programtittle";
        fieldArray[0].label.Text = "UAI UnitDef Editor";
        this.Controls.Add(fieldArray[0].label);

        fieldArray[0].save = new Button();
        fieldArray[0].save.Location = new System.Drawing.Point(549, 404);
        fieldArray[0].save.Name = "Save";
        fieldArray[0].save.Size = new System.Drawing.Size(75, 23);
        fieldArray[0].save.Text = "Save";
        fieldArray[0].save.UseVisualStyleBackColor = true;
        this.Controls.Add(fieldArray[0].save);
        this.fieldArray[0].save.Click += new System.EventHandler(this.Save_Click);

        int clabel = 36;
        fieldArray[1].varName = new string[] { "unitname", "name", "buildCostEnergy", }; //define labels

        //popluate label
        for (int i = 0; i < fieldArray[i].varName.Length; i++)
        {
            fieldArray[1].label = new Label();
            fieldArray[1].label.AutoSize = true;
            fieldArray[1].label.Location = new System.Drawing.Point(323, clabel);
            fieldArray[1].label.Name = "label";
            this.Controls.Add(fieldArray[1].label);
            fieldArray[1].label.Text = fieldArray[1].varName[i];
            clabel = clabel + 26;
        }

        //populate textbox 
        int cbox = 33;
        for (int i = 0; i < fieldArray[i].varName.Length; i++) 
        {

            fieldArray[i].txtBox = new TextBox();
            fieldArray[i].txtBox.Location = new System.Drawing.Point(410, cbox);
            fieldArray[i].txtBox.Name = "txtBox";
            fieldArray[i].txtBox.Size = new System.Drawing.Size(100, 50);
            this.Controls.Add(fieldArray[i].txtBox);

            cbox = cbox + 26;
        }
    }

    private void populateLabelTxtBox(string path)
    {
        //f.txtBox.Multiline = true; //added for testing purpose; 

        //read,split file 
        string text = System.IO.File.ReadAllText(path);
        char[] delimiters = new char[] { '{', '=', ';', '}' };
        parts = text.Split(delimiters, StringSplitOptions.RemoveEmptyEntries);
        //fieldArray[1].varName = new string[] { "unitname", "name", "buildCostEnergy", };

        //display info in textbox 
        int a;
        int strNumber;
        int strIndex = 0;

        for (a = 0; a < fieldArray[1].varName.Length; a++)
        {
            for (strNumber = 0; strNumber < parts.Length; strNumber++)
            {
                strIndex = parts[strNumber].IndexOf(fieldArray[1].varName[a]);
                if (strIndex >= 0)
                    break;
            }

          strNumber = strNumber + 1;
          fieldArray[a].join = new int[]{strNumber};
          fieldArray[a].txtBox.Text = parts[strNumber]; 
        }

    }

    private void treeView1_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
    {
        if (treeView1.SelectedNode.Name != "Folder")
        {
            string text = System.IO.File.ReadAllText(treeView1.SelectedNode.Name);
            //f.txtBox.Text = text;
            populateLabelTxtBox(treeView1.SelectedNode.Name);
        }
    }

    private void Save_Click(object sender, EventArgs e)
    {
        //fieldArray[0].txtBox.Text = "Happy"; //on click save happy is display testing 
        //join[a] > holds number where item is taken 
        //parts[] store split text 

        for (int a = 0; a < fieldArray[1].varName.Length; a++)
        {
            parts[fieldArray[a].join[a]] = fieldArray[a].txtBox.Text;
        }
        //join parts[] up with . as connector 
        string combine = string.Join(".", parts);
        fieldArray[0].txtBox.Text = combine;

    }

}
}

there is also the code of the fields:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
class Field
{
    public string[] varName;
    public TextBox txtBox;
    public Label label;
    public ToolTip tip;
    public Button save;
    public int[] join;

    public Field()
    {
        varName= new string[3];
        txtBox = null;     
        label = null;
        tip = null;
        save = null;
        join = new int[3];

    }

}
}
8
  • 4
    It's really unclear to me what that loop is really meant to be doing. What's the significance of fieldArray[1].varName.Length? Is there any guarantee that fieldArray will be the same length, or that fieldArray[a].join[a] will be valid? What about the length of parts compared with fieldArray[1].varName.Length? Commented Mar 25, 2011 at 7:34
  • You also need to show us where you split the row. We need to see how each fieldArray and join item is populated. Can you edit your question and include this? Commented Mar 25, 2011 at 7:37
  • what does this mean at the beginning of your code at that link ? private Field[] fieldArray = new Field[100]; can it be the possible reason of Index was outside the bounds of the array error? Commented Mar 25, 2011 at 7:41
  • i included the full code. private void populateLabelTxtBox(string path) show the portion which i split. join item is at private void Save_Click(object sender, EventArgs e). @EmreVeriyaz private Field[] fieldArray = new Field[100]; is to create an array of fields @Jon Skeet, fieldArray[1].varName.Length is the length of the number of variables I was searching for. fieldArray is the name of the array which contains 100 fields. fieldArray[a]join[a] is an array of 100 fields,contains number where the data is been extracted for parts[] array. length of parts[] depends on the file that is selected. Commented Mar 25, 2011 at 7:45
  • @New27 i mean that 100 might be insufficient for your code. Commented Mar 25, 2011 at 7:49

1 Answer 1

1

First, sorry that this will be quite lengthy. I've written this as I went through your code and tried to understand it (rather unsuccessfully, by the way). First, I'll just tell you where I think the problem lies:

First the brief conclusion:

    for (int a = 0; a < fieldArray[1].varName.Length; a++)
    {
        parts[fieldArray[a].join[a]] = fieldArray[a].txtBox.Text;
        //                      ^^^
        //            this might be the problem.
    }

I suspect that a always runs from 0 to 2, while join might be an array with only 1 element, ie. the only valid index would be 0. This is due to an assignment in your method populateLabelTxtBox:

   fieldArray[a].join = new int[]{strNumber};
   //                            ^^^^^^^^^^^
   //              only one element in 'fieldArray[i].join'

And now for a long-ish walkthrough:

Pardon me for saying first that your code has quite a few issues, but I'll try to concentrate on the one you asked about.

Let's look at the for loop in your Save_Click event handler where I suspect the IndexOutOfRangeException is thrown:

    for (int a = 0; a < fieldArray[1].varName.Length; a++)
    {
        parts[fieldArray[a].join[a]] = fieldArray[a].txtBox.Text;
    }

The error could be caused by different array accesses. I went through the definitions and assignments to all these arrays — why do you need so many arrays, btw.? — to check their bounds.

  • fieldArray seems to have 100 items.
  • fieldArray[i].varName seems to have 3 items.
  • fieldArray[i].join also seems to have 3 items, if I base my judgment on the initialization code inside the Field class. (But this will turn out to be wrong further down; but please bear with me for the moment.)

Due to the second point made, I assume for now that your for loop counter a runs from 0 to 2. This means:

  • fieldArray[a] is probably OK, since fieldArray has room for 100 items and we're only looking at the first 3.
  • fieldArray[a].join[a] should also be OK, as it should have exactly 3 items and we're looking at all of them.

However, it is not clear whether parts[...] is a valid array access; this depends on two things:

  1. the number of items in parts, which depends on your input text file;
  2. the value of fieldArray[a].join[a], which is used as an index into parts.

fieldArray[a].join[a] must lie between 0 and the number of items in your input text file; so let's look at how join is actually populated. This seems to happen in populateLabelTxtBox:

for (a = 0; a < fieldArray[1].varName.Length; a++)
{
    for (strNumber = 0; strNumber < parts.Length; strNumber++)
    {
        strIndex = parts[strNumber].IndexOf(fieldArray[1].varName[a]);
        if (strIndex >= 0)
            break;
    }
   strNumber = strNumber + 1;
   fieldArray[a].join = new int[]{strNumber};
   fieldArray[a].txtBox.Text = parts[strNumber]; 
}

(By now I get the feeling that I could just chase after arrays and array indexes forever. Thus I suggest very strongly you re-think your code design to make it easier to understand and maintain.)

Two things seem suspect:

  • strNumber = strNumber + 1;
    (I must admit I don't understand your code well enough to see what you're doing here, so let's skip it.)

  • fieldArray[a].join =new int[]{strNumber};
    Which means fieldArray[a].join is now an array, not with 3, but with only 1 item! If you now look back at your Save_Click loop:

    for (int a = 0; a < fieldArray[1].varName.Length; a++)
    {
        parts[fieldArray[a].join[a]] = fieldArray[a].txtBox.Text;
        //                 ^^^^^^^^
        //             this might now fail
    }
    

fieldArray[a].join[a] is no longer likely to work, because a might be any number between 0 and 2 while join only allows index 0.


I'm not sure I've got everything right, but I've shown you a way to go through your code to find the error. I've also shown that your code is quite misleading in some respects, e.g. that you initialize arrays to a certain capacity, which will actually change to something else later on.

I hope this all be of some help to you.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.