read a text file and use the first row to create a two-dimensional array c #

0

I have this .txt I want to be able to use the first row of the file as size to create a two-dimensional array in this case 7 would be the number of columns and 210 rows and then save all the rows that follow the txt in that array , in this case the data are the decimal numbers that are separated by blank spaces

210 7
15.26   14.84   0.871   5.763   3.312   2.221   5.22
14.88   14.57   0.8811  5.554   3.333   1.018   4.956
14.29   14.09   0.905   5.291   3.337   2.699   4.825
13.84   13.94   0.8955  5.324   3.379   2.259   4.805
16.14   14.99   0.9034  5.658   3.562   1.355   5.175
14.38   14.21   0.8951  5.386   3.312   2.462   4.956
14.69   14.49   0.8799  5.563   3.259   3.586   5.219
14.11   14.1    0.8911  5.42    3.302   2.7 5
16.63   15.46   0.8747  6.053   3.465   2.04    5.877 

I had this code in c ++ and I really do not understand how to do it in c # I just need the fix with the data to continue the rest of my code porian help me

ifstream database;
database.open("irisdata.txt");

if(database.fail())
{
    cout<<"error";
    getch();
    exit(0);
}
database>>fil>>col;
for(int i=0;i<fil;i++)
{
    for(int j=0;j<col;j++)
    {
        database>>a[i][j];

    }
}
    
asked by sherpensglen 21.05.2017 в 04:57
source

1 answer

1

I will try to write the code in a way that reflects the structure of C ++, with the intention that this makes it easier to understand it.

The first drawback when translating is that when you try to open a file that you do not have permission to or that does not exist you will have an exception instead of an error code that you can verify with a if . Therefore if(database.fail()) will become a try .

On the other hand, I'm going to need to use FileReader . Although FileStream offers a lower level interface, StreamReader is closer to << .

First part of the code:

StreamReader database;
try
{
    database = new StreamReader("irisdata.txt");
}
catch (Exception exc)
{
    Console.WriteLine("error");
    Console.ReadKey();
    return 0;
}

The exception you receive can be SecurityException or one of several IOException (notably FileNotFoundException ).

So that return 0; is equivalent to exit(0); I'm assuming that the code is in int Main() . In another case the equivalent is Environment.Exit(0); .

Now the problem is that .NET does not include the functionality of reading one word at a time (read up to space). I want to write down if you read several char one by one, it is better to define the grammar with a list of valid characters. However in this case I will opt for the easy way (read the whole line and separate by spaces):

var valores = database.ReadLine().Split(' ');

But we have string , we need int ...

var fil = int.Parse(valores[0]);
var col = int.Parse(valores[1]);

This is the part where I tell you that you consider what would happen without the first line of the file does not have a space. Or what would happen if it does not contain numerical values. Or what would happen if the format of the number does not match what is in the file ... you did not care when you wrote C ++, so I give you a C # code that ignores those concerns.

We continue with the for :

for(int i=0;i<fil;i++)
{
    var columnas = database.ReadLine().Split(new char[]{' '}, StringSplitOptions.RemoveEmptyEntries);
    for(int j=0;j<col;j++)
    {
        a[i][j] = columnas[j];
    }
}

Once again I am reading a line and separating by space. However, I am using an overhead of Split that receives a parameter StringSplitOptions . The reason for this is that apparently the file lines use more than one space as separation.

If there should be a specific amount of spaces you can use:

var columnas = database.ReadLine().Split(new string[]{"   "}, StringSplitOptions.None);

However, the version I placed earlier is more versatile.

I do not know the data type of a , in fact I do not see that you have stored memory for a in C ++ (that can be a problem in C ++, maybe you have a buffer overflow vulnerability). In this regard, in C # you probably want to define a as a 2D array (before for ):

var a = new string[fil, col];

And you would use it this way:

a[i, j] = columnas[j];

Of course, you might want an array of float or double or something else. In that case you can use float.Parse , double.Parse or the corresponding conversion method.

Now, I see in the example that there is a line that has fewer elements:

(...)
14.69   14.49   0.8799  5.563   3.259   3.586   5.219
14.11   14.1    0.8911  5.42    3.302   2.7 5
16.63   15.46   0.8747  6.053   3.465   2.04    5.877 
(...)

By using database.ReadLine().Split(' ') you will have as many elements as there are in the line. This means that by doing columnas[j] you can have a IndexOutOfRangeException .

As a solution I suggest placing the for internal% in this way:

for(int j=0;j<Math.Min(col, columnas.Length);j++)

That will prevent you from trying to read beyond the end of the arrangement. It also means that in a the missing value will remain with the default value ( null if it is string , 0 if it is numeric, etc ...).

Finally you have to close the file. You did not close the file in C ++! So that we do not forget to close the file, and to make sure that it closes even in case of error, use a block using . Alternatively you can use a block try...finally .

However, I would say that you will place all the code within the try that we saw at the beginning ...

try
{
    using (var database = new StreamReader("irisdata.txt"))
    {
        // resto del código ...
    }
}
catch (Exception exc)
{
    Console.WriteLine("error");
    Console.ReadKey();
}

I want to add that in .NET the try blocks are declarative. For the code enter block try is not an instruction, and therefore has no impact on performance (unless the exception occurs).

    
answered by 21.05.2017 в 14:18