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).