Home > Software design >  Converting a row of string numbers to int
Converting a row of string numbers to int

Time:01-06

I have a txt with multiple rows, in the first row the first number N is how many rows there'll be after the third and the second number M is the amount of colums there will be. The second row contains M amount of numbers. The third one is the same as the second one just with a lower number. The example looks like this:

6 8
9 9 9 9 9 9 9 9
5 5 5 5 5 5 5 5
8 4 6 6 6 6 6 6
7 5 7 6 6 6 6 5
6 6 6 5 5 5 5 6
8 6 8 7 7 7 7 6
8 6 6 6 6 6 6 6
8 6 6 6 6 6 6 1

So the N is 6 meaning there's six more rows after the 3rd one, M is 8 so there are 8 colums. I've already split the first row and declared them to variables, and got the 9 and 5 declared. Now I have to split the remaining rows in the same array, so they are like this: "8" "4" "6" "6" "6" "6" "6" "6" "7" "5" "7" "6" ect... I've tried putting the rows in an array and then split them into another with a for cicle but it doesn't seem to work. I've got this so far:

static void Main(string[] args)
        {
            string[] frow = Console.ReadLine().Split(' ');
            int dn = int.Parse(frow[0]);
            int an = int.Parse(frow[1]);
            string[] rows = new string[an];
            int[] points = new int[an * dn];
            string[] mxp = Console.ReadLine().Split(' ');
            string[] mnp = Console.ReadLine().Split(' ');
            int maxp = int.Parse(mxp[0]);
            int minp = int.Parse(mnp[0]);
            for (int i = 0; i < dn; i  )
            {
                rows[i] = Console.ReadLine();
                points[i] = rows[i].Split(' ');
            }
        }

Every help is appreciated.

CodePudding user response:

Why do something in one line of code when you can do it in a whole page?

This is what I was talking about in the comments. First I create a function that, when given a line of text, returns an array of integers:

public static bool TryGetLineOfNumbers (string line, out int[] numbers){
    numbers = null;     //out parameters must always be set, cover the failure case
    var individualStrings = line.Split(new char[]{' '}, StringSplitOptions.RemoveEmptyEntries);
    numbers = new int[individualStrings.Length];
    // convert the strings into numbers, failing on a conversion error
    for(var i = 0; i< individualStrings.Length;   i){
        if (!int.TryParse(individualStrings[i], out numbers[i])){
            return false;
        }
    }
    return true;
}

I'm way too lazy to type nine lines of numbers into a console, so I just created a hard-coded array of strings in my main function:

var testNumbers = new string[]{
    "6 8",
    "9 9 9 9 9 9 9 9",
    "5 5 5 5 5 5 5 5",
    "8 4 6 6 6 6 6 6",
    "7 5 7 6 6 6 6 5",
    "6 6 6 5 5 5 5 6",
    "8 6 8 7 7 7 7 6",
    "8 6 6 6 6 6 6 6",
    "8 6 6 6 6 6 6 1",
};

My intention was to have a function that read the console and returned an IEnumerable<string> (so that I could use the hard-coded array or the function in my testing), but I couldn't get DotNet Fiddle to handle yield return properly (it also didn't like interpolated strings). That function (which didn't work) looked like:

public static IEnumerable<string> GetStringsFromConsole(){
    var str = Console.ReadLine();
    if (!string.IsNullOrWhiteSpace(str)){
        yield return str;
    }
}

So, now my Main routine looks like:

public static void Main()
{
    var testNumbers = new string[]{
        "6 8",
        "9 9 9 9 9 9 9 9",
        "5 5 5 5 5 5 5 5",
        "8 4 6 6 6 6 6 6",
        "7 5 7 6 6 6 6 5",
        "6 6 6 5 5 5 5 6",
        "8 6 8 7 7 7 7 6",
        "8 6 6 6 6 6 6 6",
        "8 6 6 6 6 6 6 1",
    };
    //need to initialize these to keep the compiler happy
    var lineNumber = 0;
    int [,] numbers = null;
    int[] dimensions = null;
    
    foreach (var line in testNumbers)
    {
          lineNumber;   //i.e., it starts with one
        if (lineNumber == 1) {
            var firstLineValid = TryGetLineOfNumbers(line, out dimensions);
            if (!firstLineValid || dimensions.Length != 2) {
                throw new Exception ("The first line of text must have exactly two numbers");
            }
            numbers = new int[dimensions[0], dimensions[1]];
        } else if (lineNumber < 4){
            int[] ignoredNumbers;
            var line23Valid = TryGetLineOfNumbers(line, out ignoredNumbers);
            if (!line23Valid || ignoredNumbers.Length != dimensions[1]){
                throw new Exception ("The second or third line is in the incorrect format");
            }
        } else {
            int[] oneLine;
            var normalLineValid = TryGetLineOfNumbers(line, out oneLine);
            if (!normalLineValid || oneLine.Length != dimensions[1]){
                throw new Exception ("Line "   lineNumber.ToString()   " is incorrectly formatted");
            }
            for(var i = 0; i < dimensions[1];   i){
                numbers[lineNumber-4, i] = oneLine[i];
            }                   
        }
    }
    if (lineNumber != dimensions[0]   3){
        throw new Exception("Not enough inputted data");
    }
    
    //ok, got all the numbers, let's see them on the console:
    for(var i = 0; i < dimensions[0];   i){
        for(var j = 0; j < dimensions[1];   j){
            Console.Write(numbers[i,j].ToString()   " ");
        }
        Console.WriteLine();
    }
}

Yeah, it's a lot of code, but it's pretty self-explanatory. It also pays attention and validates the inputs. It's lightly tested

Reading the code over, it's probably worth refactoring the format and length test code (repeated three times) into a separate function, but that would be for another day.

CodePudding user response:

Here's just a general example of how you can split strings. Copy and paste your data to a file, and change the filePath string to match the path of the file. Run below. I suggest setting a breakpoint at the Console.ReadKey() and looking at each of the variables after they've been assigned to, to see what each function does:

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

namespace HelpingStackOverflow
{
   class Program
   {
       static void Main(string[] args)
       {

        string filePath = @"C:\Users\me\Desktop\data.txt";
        string fileContents = File.ReadAllText(filePath);
        string[] allLines = fileContents.Split('\n');
        int n = Convert.ToInt32(allLines[0].Split(" ")[0]);
        int m = Convert.ToInt32(allLines[0].Split(" ")[1]);
        string secondRow = allLines[1].Trim('\r');
        string thirdRow = allLines[2].Trim('\r');
        string[] remainingLines = allLines.Skip(3).ToArray();

        //so now you have different arrays
        //if you want to break a line into an additional array you can do so
        //and do whatever you want with the parts like this:

        List<string[]> allParts = new List<string[]>();
        foreach (string line in remainingLines)
        {
            var parts = line.Trim('\r').Split(" ");
            allParts.Add(parts);
        }
        Console.ReadKey();
    }
}

}

  •  Tags:  
  • Related