views:

477

answers:

9
+1  Q: 

C# Simple File I/O

I'm trying to write a program that does this:

In this exercise exam scores for a class of students is stored in a file. You are to write a program that successfully opens the file, reads in the exam scores, finds the average score, the highest score, and the lowest score, and prints these out. The average score should be printed with 2 digits after the decimal point.

This is what I have so far:

static void Main()
{
    string myData = "";
    int temp = 0;
    int max = 0;
    int min = 0;
    double average = 0;
    StreamReader fileReader = new StreamReader("data.txt");

    do
    {
        myData = fileReader.ReadLine();

        if (myData != null)
        {
            max = int.Parse(myData);
            temp = int.Parse(myData);

            if (temp > max)
                temp = max;
        }
    } while (myData != null);

    fileReader.Close();
    Console.ReadLine();
}//End Main()

I don't exactly know how to proceed, any tips would be appreciated, how do I read in a new line and assign it to temp, because I don't think I'm doing it right.

+3  A: 

The first error I found is that max will always be exactly equal to temp because you assign them the same value, so this if will never be true:

max = int.Parse(myData);
temp = int.Parse(myData);

if (temp > max)
jeffamaphone
thanks, this really helped!
Alex
+1  A: 

For starters, you need to get rid of the line "max = int.Parse(myData)". Otherwise, you'll keep overwriting max with the current value.

Jimmy
+1  A: 

Since this is homework, I'll just give you some clues.

Right now, you're setting "max" each time through the loop. Try only setting temp, and see what happens. You might want to consider defaulting max (when you create it) to a very small number instead of 0.

Also, you'll need to do something similar for "min", but default it to a very large number.

int max = int.MinValue;
int min = int.MaxValue;

In order to get the average, you'll need to have a sum and a count, and keep track of those. Then, at the end, use a double to compute the average, and print. To get 2 decimal places, you can use average.ToString("N") - the "N" format does a nicely formatted number with 2 decimal places by default.

Reed Copsey
+1  A: 

How about you separate out the processes? Do the reading and fill a list of integers with the contents of the file. Then perform the processing for min / max and average later on.

Isolating issues help you focus on them. I like to call this noise reduction. As a contractor I get to work on a lot of messy code and one of the reasons they are hard to understand is that too much is going on at the same time. If you simplify whats going on the code almost writes itself. This is also called Separation of Concerns. This is a very important programming principle.

After you've isolated the issues and got the code working you can then try to put it all together again so the process is more efficient (if you do it inline with the file reading then you will only hold one line in memory at a time).

Quibblesome
`File.ReadAllLines(filename).Select(x=>int.Parse(x))` heheh
Will
+2  A: 

Not bad. Here's some pseudocode:

  1. File.ReadAllLines to get an array of strings (call this lines)
  2. Foreach line in lines
    1. Parse the double (? is each line guaranteed to be an int?)
    2. if max < parsed, max = parsed
    3. if min > parsed, min = parsed
    4. sum += parsed
  3. Print out min, max, (sum / lines.count).ToString("000.00")

Assumes the file looks like:

25
12
33.5
100
75
...

Will
BTW, notice File.ReadAllLines. The Framework has just about everything you will ever need. If there's a common algorithm, there is a class and method that does it, 99% of the time.
Will
+1  A: 

I take it that this is the general gist of your assignment. You should be leery of copying this code.

            double count = 0.0;
            double min = double.MaxValue;
            double max = double.MinValue;
            double total = 0.0;
            using(StreamReader sr = new StreamReader(@"c:\data.txt"))
            {
                while (!sr.EndOfStream)
                {
                    String line = sr.ReadLine();
                    double value = double.Parse(line.Trim());
                    if (value < min) min = value;
                    if (value > max) max = value;
                    total += value;
                    count++;
                }
            }

            Console.WriteLine("Min: {0}", min);
            Console.WriteLine("Max: {0}", max);
            Console.WriteLine("Avg: {0}", (total / count).ToString("0.00"));
            Console.ReadLine();
Thanks, I am not going to copy any code, I just needed some input on how to do it, everyone here has helped, I am now able to come up with my own solution from all of your help. Thanks for the hints and tips!
Alex
A: 
static void Main(string[] args)
{
    const string filename = @"data.txt";
    bool first = true;
    int min=0, max=0, total=0;

    var lines = File.ReadAllLines(filename);

    foreach (var line in lines)
    {
        var score = int.Parse(line.Trim());
        if (first)
        {
            min = max = total = score;
            first = false;
            continue;
        }
        if (score < min)
            min = score;
        if (score > max)
            max = score;
        total += score;
    }

    if (first)
    {
        Console.WriteLine("no input");
        return;
    }

    var average = (double)total/lines.Length;
    Console.WriteLine(string.Format("Min: {0}, Max: {1}, Average: {2:F2}", min, max, average));
}
orip
+6  A: 

Here is one way that will make your teacher sad :P

    static void Main(string[] args)
    {
        StreamReader file = new StreamReader("scores.txt");
        string[] split = file.ReadToEnd().Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);            

        IEnumerable<int> ints = split.Select(x => int.Parse(x));

        Console.WriteLine("Total Scores:" + ints.Count());
        Console.WriteLine("Max:" + ints.Max());
        Console.WriteLine("Min:" + ints.Min());
        Console.WriteLine("Average:" + ints.Average().ToString("0.00"));
        Console.ReadLine();
    }

While this is technically correct, this is counter-productive to understanding algorithms (however basic they may be), and I suggest you look at the other answers. But this demonstrates how versatile the .NET framework is.

<3 LINQ

Baddie
holy cow, that is messin' with my head
Alex
A: 

Hey thanks to everybody who helped out and offered suggestions, here is my final code implementation (without using arrays)

using System;
using System.IO;

class Program
{
static void Main()
{
    string line = "";
    int value = 0;
    int max = 0;
    int min = 100;
    int total = 0;
    double count = 0.0;
    double average = 0;

    StreamReader fileReader = new StreamReader(@"data.txt");

    do
    {
        line = fileReader.ReadLine();

        if (line != null)
        {
            value = int.Parse(line);

            if (value > max)
                max = value;

            if (value < min)
                min = value;

            total += value;
            count++;
        } 
    } while (line != null);

    average = total / count;

    Console.WriteLine("Max: {0}", max);
    Console.WriteLine("Min: {0}", min);
    Console.WriteLine("Avg: {0:f2}", average); 

    Console.ReadLine();
}//End Main()
}//End class Program
Alex