0

I try to get a file's content into an array in C#. My program is similar to a shopping list. I'm not able to store the data as a JSON file cause of some requirements.

I decided to store the data like:

3x water
2x fish

I grabbed the data using a simple StreamReader and got all the data into a string. I tried to separate the string by \n using split and store the data into a string array.

Now I wanted to split each string again to get the quantity of the product. I tried splitting each index using a foreach and storing them in a second array. I also tried to store the data in the same array.

I want to get something like

string[] cars = {"3", "water", "2", "fish"};

or store the data in a list. Is my attempt a bad one?

Is there a way to do it much more easily?

6
  • I'd start by not storing the "x" after the number. Then you'd just split each line on the space and using int.Parse on the first item to get a numeric value. But you really need to include your code and if it's working then this might be off topic and codereview.stackexchange.com might be a better fit if you're asking for a review of your existing working code. Commented Jun 25, 2020 at 14:21
  • I forget to say that the file from where I get the data should be easily readable by eye. Thats the reason why I dont use a json. Commented Jun 25, 2020 at 14:26
  • 2D object array would be easier to handle I think! Commented Jun 25, 2020 at 14:28
  • 1
    Would it be better if you got an array of classes / structs for each row of Cars like : Car[] cars = new Car[] { new Car(3, "water"), new Car(2, "fish") };? Commented Jun 25, 2020 at 14:35
  • 1
    What requirement prevents you from storing as JSON but allows you to come up with an arbitrary format? Commented Jun 25, 2020 at 14:40

2 Answers 2

2

Easy is a very subjective requirement.

You could write it in one statement with a variant of Split that restricts it to splitting at most once (so you can use an x in a description), and uses SelectMany to fold down all the lines into a single array of strings - as you asked.

string[] cars = File.ReadAllLines("input.txt")
                    .SelectMany(line => line.Split(new char[] { 'x' }, 2))
                    .Select(s => s.Trim())
                    .ToArray();

...but I wouldn't.

I think that maintainability is important. This code is understandable, useful, and obvious.

using System;
using System.Collections.Generic;
using System.IO;

class Program
{
    public class Car
    {
        private int quantity;
        private string description;

        public Car(int quantity, string description)
        {
            this.quantity = quantity;
            this.description = description;
        }

        public override string ToString() => $"{quantity}x {description}";
    }

    static void Main(string[] args)
    {
        // Use a list to store all the entries.
        List<Car> cars = new List<Car>();

        string[] lines = File.ReadAllLines("input.txt");

        // Parse each line of the file.
        foreach (var line in lines)
        {
            // Ignore completely blank lines.
            if (string.IsNullOrWhiteSpace(line))
                continue;

            // Find the delimiter 'x'.
            int pos = line.IndexOf('x');

            // Handle case where no delimiter is present.
            if (pos < 0)
                throw new FormatException("The line is in an invalid format because it does not contain an 'x'.");

            // Split the string into two parts at the delimiter position.
            string firstPart = line.Substring(0, pos); // everything before the delimiter
            string lastPart = line.Substring(pos + 1); // everything after the delimiter

            // Interpret the first part as an integer.
            if (!int.TryParse(firstPart, out int quantity))
                throw new FormatException("The quantity is not a number.");

            // Disallow zero or less for quantities.
            if (quantity < 1)
                throw new InvalidDataException("The quantity is not a positive number.");

            // Trim whitespace from the description.
            string description = lastPart.Trim();

            // Require a non-empty description.
            if (string.IsNullOrWhiteSpace(description))
                throw new InvalidDataException("The description is missing.");

            cars.Add(new Car(quantity, description));
        }
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you very much
0

If we suppose that each item has it's own line inside the file, this solution goes through each line and separates the quantity and the name of the item, after that these are stored in an array.

 private static string[] GetData()
        {
            using (StreamReader sr = new StreamReader("source.in"))
            {
                
                int numberOfItems = File.ReadAllLines("source.in").Length;
                string[] Data = new string[numberOfItems * 2];
                int DataIndex = -1;

                string line;

                while ((line = sr.ReadLine()) != null)
                {
                    //Separate the things
                    int index = line.IndexOf('x');

                    string num = line.Substring(0, index++);
                    Data[++DataIndex] = num;

                    string itm = line.Substring(++index);
                    Data[++DataIndex] = itm;
                }

                return Data;
            }
        }

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.