Spectrator
Spectrator

Reputation: 1

I want to split an already split string

Hey everyone I was hoping you could help me with my little problem. I want to split an already split string but I get the error: "The index was outside the bounds of the array".

I know that my array is too small but I don't know how to increase that in this instance. Here is the code.

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

namespace Reserveringssysteem
{
    public partial class Form2 : Form
    {
        public string naam;
        public string adres;
        public string datum;
        public int kamernr;
        public int id;
        public int indexnr;
        public int indexnrb;
        public int indexnrc;

        Kamer[] reserveringArray = new Kamer[6];
        public Form2()
        {
            InitializeComponent();
        }

        private void backbtn_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void Form2_Load(object sender, EventArgs e)
        {
            using (StreamReader sr = new StreamReader(@"C:\Users\Gebruiker\Desktop\OIS\Hotelsysteem\Reserveringen.txt", Encoding.Default))
            {
                string text = sr.ReadToEnd();
                string[] lines = text.Split(';');
                foreach (string s in lines)
                {
                    id = Convert.ToInt32(s.Split(':')[0]);
                    indexnr = s.IndexOf(':');
                    naam = s.Split('/')[indexnr];
                    indexnra = s.IndexOf("/");
                    adres = s.Split('<')[indexnra];
                    indexnrb = s.IndexOf('<');
                    kamernr = Convert.ToInt32(s.Split('>')[indexnrb]);
                    indexnrc = s.IndexOf('>');
                    datum = s.Split(';')[indexnrc];
                    ListViewItem opbouwera = new ListViewItem(Convert.ToString(id));
                    opbouwera.SubItems.Add(naam);
                    opbouwera.SubItems.Add(adres);
                    opbouwera.SubItems.Add(Convert.ToString(kamernr));
                    opbouwera.SubItems.Add(datum);
                    reserveringlistview.Items.Add(opbouwera);
                }


            }
        }
    }
}

The problem occurs from the moment I start using indexnra. I hope one of you guys can help me out here.

Upvotes: 0

Views: 104

Answers (2)

Sergey Berezovskiy
Sergey Berezovskiy

Reputation: 236228

I would go with regular expression to parse data from your lines. Because it describes layout of input string instead of working with substrings and indexes of some separators. Also I would use custom object which would store person data in nicely named fields:

public class Person
{
    public int Id {get;set;}
    public string Name {get;set;}
    public string Address {get;set;}
    public string Appartment {get;set;}
    public DateTime Date {get;set;}
}

And here is regular expression which defines groups for each part of data in input string:

  • (?<id>\d+) first group is id - sequence of digits
  • : then goes separator with some spaces
  • (?<name>[\w\s]+) name which consists of letters and spaces
  • / second separator
  • (?<address>[\w\d\s]+) address - letters, digits, spaces
  • <\s*(?<app>\d+)\s*> appartment number - digits in angular brackets
  • \s+ some spaces
  • (?<date>\d{4}-\d{2}-\d{2}) date in yyyy-dd-MM format

Usage:

var regex = new Regex(@"(?<id>\d+):(?<name>[\w\s]+)/(?<address>[\w\d\s]+)<\s*(?<app>\d+)\s*>\s*(?<date>\d{4}-\d{2}-\d{2})");
var people = from line in lines
             let match = regex.Match(line)
             where match.Success
             select new Person {
                 Id = Int32.Parse(match.Groups["id"].Value),
                 Name = match.Groups["name"].Value.Trim(),
                 Address = match.Groups["address"].Value.Trim(),
                 Appartment = match.Groups["app"].Value,
                 Date = DateTime.ParseExact(match.Groups["date"].Value.Trim(),"yyyy-dd-MM",null)
             };

For this sample file

1: Jeroen Wasser Poppy Paashaas/ Bijloopstraat 21< 5> 2017-31-12;2: Bob White/ Bijloopstraat 22< 15> 2016-28-10;

You will have two people parsed:

[
  {
    "Id": 1,
    "Name": "Jeroen Wasser Poppy Paashaas",
    "Address": "Bijloopstraat 21",
    "Appartment": "5",
    "Date": "2017-12-31T00:00:00"
  },
  {
    "Id": 2,
    "Name": "Bob White",
    "Address": "Bijloopstraat 22",
    "Appartment": "15",
    "Date": "2016-10-28T00:00:00"
  }
]

Then grab collection of people and display them in ListView. I.e. separate data access (reading file and parsing people) with presentation (displaying data on UI).


NOTE: You can also use unnamed groups in regex. It will be less readable, but more compact:

(\d+):([\w\s]+)/([\w\d\s]+)<\s*(\d+)\s*>\s*(\d{4}-\d{2}-\d{2})

And you will have to read groups by index instead of name

Id = Int32.Parse(match.Groups[1].Value),

Upvotes: 2

D Stanley
D Stanley

Reputation: 152556

These lines are an example of the problem:

indexnr = s.IndexOf(':');
naam = s.Split('/')[indexnr];

IndexOf will return the position within the string of the : character (e.g. 9 if the colon is the 10th character since the index is zero-based).

s.Split('/') will return an array of strings, so in that example you would be asking for the 10th string if you used a value of 9 for indexnr.

All that to say that the output of IndexOf is very likely not the appropriate index to use to find a particular string after calling Split.

It's not clear from your code what your expected output is - if you add an example input and the expected output you can probable get a better method for getting what you need.

Upvotes: 2

Related Questions