1
\$\begingroup\$

I have made an exercise where I need to calculate the average per row of a .txt file. (see below)

Toa Narumi gradeA 10 8 7 4 6,5
Jean-François Le Clerk gradeB 5 4 7
Joe GradeC 10 10

I only want the numbers behind the name and grade. This is my code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Linq;
namespace RenoD_Oef_Strings
{
 class Program
 {
 static void Main(string[] args)
 {
 // Variablen
 StreamReader bestand = new StreamReader(@"F:\RenoD_Oef_Strings\Punten.txt");
 string strRow; // String used to read every row of .txt file
 double?[] dblPoints; // Double array used to store all values
 List<string> strInput = new List<string>(); // String List used to store all data from .txt
 // Code
 while ((strRow = bestand.ReadLine()) != null) // Read row per row in .txt
 {
 strInput = strRow.Split(' ').ToList(); // Puts every word in the row in to the list
 int intX = 0;
 foreach(string strX in strInput) // Calculate how many strings are in the list
 {
 intX++;
 }
 dblPoints = new double?[intX]; // Calculate the max number of elements the double array can have
 intX = 0;
 foreach(var x in strInput) // Checks if elements in the list can be converted in to a double 
 {
 try
 {
 double dblR = Convert.ToDouble(x); // If element can be converted in to a double, it will be stored in the double array
 dblPoints[intX] = dblR;
 intX++;
 }
 catch
 {
 intX++; // If element CAN NOT be converted in to a double, it will be still be stored in the double array but without any value
 }
 }
 double dblAverage = 0; // Double used to save the total average of one row
 intX = 0;
 foreach(var k in dblPoints)
 {
 if (k.HasValue) // Elements without value will be ignored
 {
 dblAverage += Convert.ToDouble(k); // All double values will be added up
 intX++; // Used to see how much double values there are to calculate average
 }
 }
 dblAverage = Math.Round(dblAverage/intX, 2); // Calculate average + round up to two decimals
 Console.WriteLine(dblAverage.ToString());
 }
 bestand.Close();
 Console.ReadKey(); 
 }
 }
}

What I have done is

  • Read row per row .txt file

  • Put all elements of that row in a list

  • Calculate how many elements that the double array will need to store (same number of elements the list has), which I later on use to store all doubles of the list

  • Check if elements in the list can be converted in to a double array; If the element can be converted in to a double, it will be stored in the double array.

If element CAN NOT be converted in to a double, it will be still be stored in the double array but without any value.

  • Only calculate the average of the elements in my double array that have values.

I have tested the code, and it works without any issue.

My question is, have I taken a good approach? What would you have done to make it more efficient?

I have tried searching in other threads for solutions. I have seen simular questions, but was unable to find any exactly the same as my exercise.

t3chb0t
44.6k9 gold badges84 silver badges190 bronze badges
asked May 5, 2019 at 11:37
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Some tips: Dont mix german and english words. You use an object oriented language: Try to structure your code in functions. Then try to structure your code in classes. Dont mention the type of a variable in its name. This is old fashioned style. Dont write unnecessary code - use the appropriate methods of your language. If you explicitly want to implement already implemented features by yourself - use the "reinventing-the-wheel"-tag. Good luck and a lot of fun! \$\endgroup\$ Commented May 5, 2019 at 15:57

1 Answer 1

2
\$\begingroup\$
  • Enclose the file reading in a using statement
  • Use double.TryParse or regex to parse the numbers
  • Use Linq extention method Average() to calculate average
  • The size of strInput is strInput.Count, no need for a loop

Hear is a simpler code:

using (StreamReader bestand = new StreamReader(@"F:\RenoD_Oef_Strings\Punten.txt"))
{
 string strRow; // String used to read every row of .txt file
 // Code
 while ((strRow = bestand.ReadLine()) != null) // Read row per row in .txt
 {
 List<string> strInput = strRow.Split(' ').ToList(); // String List used to store all data from .txt
 List<double> dblPoints = new List<double>(); // Double list used to store all values
 foreach (var x in strInput) // Checks if elements in the list can be converted in to a double 
 {
 if (double.TryParse(x, out double result))
 {
 dblPoints.Add(result);
 }
 }
 double dblAverage = dblPoints.Average();
 Console.WriteLine(dblAverage.ToString());
 }
}
Console.ReadKey();
t3chb0t
44.6k9 gold badges84 silver badges190 bronze badges
answered May 5, 2019 at 12:09
\$\endgroup\$
2
  • \$\begingroup\$ Thank you for your reply! It is indeed way simpeler. \$\endgroup\$ Commented May 5, 2019 at 13:11
  • \$\begingroup\$ Clean and does the trick. There is theoretical edge case where a grade could be NaN, which passes the TryParse check but the average would also be a NaN. If this could be a possibility, it would need to be accounted for. \$\endgroup\$ Commented May 6, 2019 at 16:11

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.