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();
}
}
}
