tags:

views:

109

answers:

6

This is relatively simple program. But I want to get some feedback about how I can improve this program (if any), for example, unnecessary statements?

#include<iostream>
#include<fstream>
using namespace std;

double Average(double*,int);

int main()
{

    ifstream inFile("data2.txt");

    const int SIZE = 4;
    double *array = new double(SIZE);
    double *temp;
    temp = array;

    for (int i = 0; i < SIZE; i++)
    {
        inFile >> *array++;
    }
    cout << "Average is: " << Average(temp, SIZE) << endl;
}

double Average(double *pointer, int x)
{
    double sum = 0;

    for (int i = 0; i < x; i++)
    {
        sum += *pointer++;
    }
    return (sum/x);
}

The codes are valid and the program is working fine. But I just want to hear what you guys think, since most of you have more experience than I do (well I am only a freshman ... lol)

Thanks.

+4  A: 

Fix the memory leak. i.e delete temp; Also, check if the file is open/created..etc

ideally, you should manipulate/traverse the array using your temp variable instead of using *array itself

SysAdmin
Also, deal with empty files, partially filled files. What if the file has more than 4 entries? Put a space between `double*,` and `int` in `double Average(double*,int);`.
Hamish Grubijan
i didn't get the third statement "traverse the array..." may you describe it a little bit more in detail, please? thank you!
JohnWong
@johnWong - "traverse the array..." is what you are doing now. accessing one element at a time in the for loop until the last one
SysAdmin
hi, sysadmin. thanks. please be patient with me, if you think I am being stupid :D. haha. i see. i thought i needed to save the first address, so i saved it in temp. how should i rewrite that part? *array itself is just a pointer variable, right?
JohnWong
@JohnWong - nobody thinks you are stupid. :). basically, what you have done is correct. but my suggestion is to not move the pointer to which memory was allocated. do the other way round. i.e in the for loop instead of using *array use *temp and pass the *array into Average()
SysAdmin
i got you. is there a speed or security difference b/w passing the original allocation *array vs *temp? thanks sysadmin. lol hahaa cuz i keep asking questions may be obvious to some people :) thanks dude
JohnWong
no issue in this simple program. but in a big project, if something goes wrong because of this, you would spend a lot of time unnecessarily debugging...thats all.
SysAdmin
+1  A: 

If x is 0, then Average will generate a divide-by-zero error.

Chris AtLee
right, an additional warning can be added. great thought!
JohnWong
How about when x is negative? Do you want to deal with exceptions or use C-style errno, other? So far there is no C++ really. I bet this program will compile with a C compiler.
Hamish Grubijan
@Hamish: I bet it doesn't with it using `new` and iostreams.
Georg Fritzsche
+2  A: 

Since we're talking about C++, I would suggest using STL containers and algorithms. I also find that in most cases it's better to use references or smart pointers (e.g. boost::shared_ptr) instead of raw pointers. In this case there's no need for pointers at all.

Here is how you could write your program:

#include <fstream>
#include <vector>
#include <iostream>
#include <numeric>
#include <iterator>

using namespace std;

int main()
{
    ifstream f("doubles.txt");
    istream_iterator<double> start(f), end;
    vector<double> v(start, end);

    if (v.empty())
    {
        cout << "no data" << endl;
        return 0;
    }

    double res = accumulate(v.begin(), v.end(), 0.0);
    cout << "Average: " << res / v.size() << endl;
    return 0;
}
Alex - Aotea Studios
wooo this is very advance. We did touch on STL and vectors, but not too much. Thanks for spending ur time, it's a great reference.
JohnWong
A: 

Sorry to post this as an answer - seem to have trouble commenting (or is this intentional? new to the site). In terms of your question 'what do you mean by traversing the array'? That's just another term for looping through an object (an array here). While your code

for (int i = 0; i < SIZE; i++)  
{  
    inFile >> *array++;  
}  

is valid, it's a bit awkward: you're mixing two paradigms, referencing by pointer with referencing by indices. You're counting down to 3, but actually use the pointer. I assume he meant to suggest to instead actually use the 'i' as in

for (int i = 0; i < SIZE; i++)
{
    inFile >> array[i];  
}  

(you could also eliminate the i loop and instead use the pointer progression to steer your loop.).

gnometorule
You need to have a reputation of 50 to comment on answers and questions other then your own - see the FAQ entry *"What is reputation?"*. You also don't need `<pre>` or `<code>` - use the `101` button or just indent code by 4 spaces.
Georg Fritzsche
Ah, most useful. I was seriously struggling to get code entered.
gnometorule
hi, for your last comment: using pointer progression. you mean *array++ in the for loop condition () ?
JohnWong
Oups. While I personally wouldn't mix the i with the pointer inside the loop, I didn't read carefully: when he spoke about temp variable, I thought it referred to the (temporary) variably 'i'. But, of course, he meant temp, and to simply use temp to store, then array to get the average (just inverse their use). To loop using a pointer, you'd have to first zero initialize the entire array with a sentinel ('\0', say) at end, then do something like while (temp!= '\0'){ infile>>*temp++; }; but that's very C so I'm not sure that's a good idea.
gnometorule
or maybe temp is not null? later i will adapt the idea of structure in c++, and and then assigning (structname)->nextAdress and with null for the last address.
JohnWong
+4  A: 

You are not initializing your array correctly. This statement:

double *array = new double(SIZE);

Allocates one double and initializes it to the value of SIZE. What you should be doing is using array allocation:

double *array = new double[SIZE]; 

Another general problem is you rarely ever want to assign dynamically allocated memory to a raw pointer. If you want to use base types instead of higher level objects such as std::vector, you should always use a smart pointer:

boost::scoped_array<double> array(new double[SIZE]);

Now the array will automatically get freed regardless of how you leave your scope (i.e. from a newly added return or from an exception).

R Samuel Klatchko
hi, thanks. thank you for pointing out the two differences. new double [SIZE] is an array allocation, right. and i do treat memory allocation as linear arrangement, which is an array, i suppose. i am still not quite understand the problem with (). I do see your point about [] for an array allocation.
JohnWong
@JohnWong - `new double(SIZE)` allocates **1** double object. By itself, there is nothing wrong with that; the issue is that the code treats it like an array which causes a "buffer overflow".
R Samuel Klatchko
A: 

Here are some "code review" comments:

In main():

  1. Change SIZE to "size_t" instead of int
  2. Why SIZE is uppercase? (May be the author's convention is to have constants as uppercase, in that case it is fine.)
  3. Combine temp declaration and assignment into one statement as: double * temp = array;
  4. What if inFile is not available or can't be opened for reading?
  5. What if inFile have less than SIZE number of items?
  6. Change the loop variable i to size_t.
  7. Remove blank line before declaration of inFile.
  8. Return some number (e.g. 0) from main().
  9. Correct the allocation of array.

In Average():

  1. Change the second argument of Average to size_t.
  2. Assert and/or guard for pointer being non-NULL
  3. Assert and/or guard against division by zero.

Acknowledgement: Some points are collected from other answers. I tried to make a complete list as far as I could.

ArunSaha
thank you for your inputs. i really enjoy this kind of conversation. this discussion reflects how much i still need to learn :) so for size_t, do i need specify how many?
JohnWong