Program that reads file with numbers

I am working on a program that read the file with car model and fuel consumption.

In file I have cars like A|12.45, where A stand for model and number stands for fuel consumption per 100Km. Every car is in it's own line.

File looks like that:

A|8.11

B|14.38

C|13.05

Here we can see that B has highest consumption but when I run that program in console it shows up as 1438 L without dot in the middle. How can I fix this?

I have a code that looks like this:

    static void Main(string[] args)
    {

        StreamReader readF = File.OpenText(@"D:\CarList.txt");
        string line = readF.ReadLine();

        double highest = 0;
        double lowest = 300;

        string nameHighest= "";
        string nameLowest= "";

        while (line != null)
        {

            string[] temp = line.Split('|');


            if (Convert.ToDouble(temp[1]) > highest)
            {
                highest= Convert.ToDouble(temp[1]);
                nameHighest = temp[0];
            }


            if (Convert.ToDouble(temp[1]) < lowest)
            {

                lowest = Convert.ToDouble(temp[1]);
                nameLowest = temp[0];
            }

            line = readF.ReadLine();
        }
        readF.Close();


        Console.WriteLine("Highest consumption: " + nameHighest + ". It consumes " + highest + " L per 100Km.");
        Console.WriteLine("Lowest consumption " + nameLowest + ". It consumes " + lowest + " L per 100Km");

        Console.ReadKey();
    }

Thanks!

Jon Skeet
people
quotationmark

I strongly suspect this is because the default culture on your machine is one that uses , instead of . for a decimal separator. You can use double.Parse and specify CultureInfo.InvariantCulture to parse it using the invariant culture which does use . for the separator.

I would actually rewrite your code in several steps.

Step 1: use double.Parse, and only do so once per line - likewise extract temp[0] once per line.

Step 2: use double.NegativeInfinity as the initial "highest" and double.PositiveInfinity as the initial "lowest", so that any finite entry will register.

Step 3: use a format string at the end. With C# 6 we can use string interpolation, but at least we can make it simpler than it is before then.

Step 4: use File.ReadLines instead of reading them "manually"

At this point we have:

using System;
using System.Globalization;
using System.IO;

class Test
{
    static void Main(string[] args)
    {
        double highest = double.NegativeInfinity;
        double lowest = double.PositiveInfinity;

        string nameHighest= "";
        string nameLowest= "";

        foreach (var line in File.ReadLines("test.txt"))
        {
            string[] temp = line.Split('|');
            string name = temp[0];
            double consumption = double.Parse(
                temp[1],
                CultureInfo.InvariantCulture);

            if (consumption > highest)
            {
                highest = consumption;
                nameHighest = name;
            }

            if (consumption < lowest)
            {
                lowest = consumption;
                nameLowest = name;
            }
        }

        Console.WriteLine(
            "Highest consumption: {0}. It conumes {1}L per 100km",
            nameHighest, highest);
        Console.WriteLine(
            "Lowest consumption: {0}. It conumes {1}L per 100km",
            nameLowest, lowest);
    }
}

Step 5: use LINQ to separate the reading and parsing of the data from the using it - although I'm storing everything in a list so we can go through it twice in a minute...

using System;
using System.Globalization;
using System.IO;
using System.Linq;

class Test
{
    static void Main(string[] args)
    {
        var cars = File.ReadLines("test.txt")
            .Select(line => line.Split('|'))
            .Select(bits => new { Name = bits[0], Consumption = double.Parse(bits[1]) })
            .ToList();

        if (cars.Count == 0)
        {
            Console.WriteLine("No cars!");
            return;
        }

        var highest = cars[0];
        var lowest = cars[0];

        foreach (var car in cars.Skip(1))
        {
            if (car.Consumption > highest.Consumption)
            {
                highest = car;
            }

            if (car.Consumption < lowest.Consumption)
            {
                lowest = car;
            }
        }

        Console.WriteLine(
            "Highest consumption: {0}. It consumes {1}L per 100km",
            highest.Name, highest.Consumption);
        Console.WriteLine(
            "Lowest consumption: {0}. It consumes {1}L per 100km",
            lowest.Name, lowest.Consumption);
    }
}

Step 6: Use MoreLINQ's MinBy and MaxBy to make it really simple:

using MoreLinq;
using System;
using System.Globalization;
using System.IO;
using System.Linq;

class Test
{
    static void Main(string[] args)
    {
        var cars = File.ReadLines("test.txt")
            .Select(line => line.Split('|'))
            .Select(bits => new { Name = bits[0], Consumption = double.Parse(bits[1]) })
            .ToList();

        if (cars.Count == 0)
        {
            Console.WriteLine("No cars!");
            return;
        }

        var highest = cars.MaxBy(c => c.Consumption);
        var lowest = cars.MinBy(c => c.Consumption);

        Console.WriteLine(
            "Highest consumption: {0}. It consumes {1}L per 100km",
            highest.Name, highest.Consumption);
        Console.WriteLine(
            "Lowest consumption: {0}. It consumes {1}L per 100km",
            lowest.Name, lowest.Consumption);
    }
}

people

See more on this question at Stackoverflow