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.

\$\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\$ 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();
\$\endgroup\$
2
  • \$\begingroup\$ Thank you for your reply! It is indeed way simpeler. \$\endgroup\$
    – Toa Narumi
    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\$
    – Rick Davin
    May 6, 2019 at 16:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.