[c++] How can I change the value of the elements in a vector?

I have this code, which reads in input from a file and stores it in a vector. So far, I've gotten it to give me the sum of the values within the vector and give the mean of the values using the sum.

What I'd like to do now is learn how to access the vector again and subtract a value from each element of the vector and then print it out again. For example, once the sum and mean are calculated, I'd like to be able to reprint each value in the terminal minus the mean. Any suggestions/examples?

#include <iostream>
#include <vector>
#include <fstream>
#include <cmath>

using namespace std;

int main()
{
    fstream input;
    input.open("input.txt");
    double d;
    vector<double> v;
    cout << "The values in the file input.txt are: " << endl;
    while (input >> d)
    {
        cout << d << endl;
        v.push_back(d);
    }

double total = 0.0;
double mean = 0.0;
double sub = 0.0;
for (int i = 0; i < v.size(); i++)
{
    total += v[i];
    mean = total / v.size();
    sub = v[i] -= mean;
}
cout << "The sum of the values is: " << total << endl;
cout << "The mean value is: " << mean << endl;
cout << sub << endl;
}

This question is related to c++ vector

The answer is


int main() {
  using namespace std;

  fstream input ("input.txt");
  if (!input) return 1;

  vector<double> v;
  for (double d; input >> d;) {
    v.push_back(d);
  }
  if (v.empty()) return 1;

  double total = std::accumulate(v.begin(), v.end(), 0.0);
  double mean = total / v.size();

  cout << "The values in the file input.txt are:\n";
  for (vector<double>::const_iterator x = v.begin(); x != v.end(); ++x) {
    cout << *x << '\n';
  }
  cout << "The sum of the values is: " << total << '\n';
  cout << "The mean value is: " << mean << '\n';
  cout << "After subtracting the mean, The values are:\n";
  for (vector<double>::const_iterator x = v.begin(); x != v.end(); ++x) {
    cout << *x - mean << '\n';  // outputs without changing
    *x -= mean;  // changes the values in the vector
  }

  return 0;
}

Well, you could always run a transform over the vector:

std::transform(v.begin(), v.end(), v.begin(), [mean](int i) -> int { return i - mean; });

You could always also devise an iterator adapter that returns the result of an operation applied to the dereference of its component iterator when it's dereferenced. Then you could just copy the vector to the output stream:

std::copy(adapter(v.begin(), [mean](int i) -> { return i - mean; }), v.end(), std::ostream_iterator<int>(cout, "\n"));

Or, you could use a for loop...but that's kind of boring.


You can access the values in a vector just as you access any other array.

for (int i = 0; i < v.size(); i++)
{         
  v[i] -= 1;         
} 

Your code works fine. When I ran it I got the output:

The values in the file input.txt are:
1
2
3
4
5
6
7
8
9
10
The sum of the values is: 55
The mean value is: 5.5

But it could still be improved.

You are iterating over the vector using indexes. This is not the "STL Way" -- you should be using iterators, to wit:

typedef vector<double> doubles;
for( doubles::const_iterator it = v.begin(), it_end = v.end(); it != it_end; ++it )
{
    total += *it;
    mean = total / v.size();
}

This is better for a number of reasons discussed here and elsewhere, but here are two main reasons:

  1. Every container provides the iterator concept. Not every container provides random-access (eg, indexed access).
  2. You can generalize your iteration code.

Point number 2 brings up another way you can improve your code. Another thing about your code that isn't very STL-ish is the use of a hand-written loop. <algorithm>s were designed for this purpose, and the best code is the code you never write. You can use a loop to compute the total and mean of the vector, through the use of an accumulator:

#include <numeric>
#include <functional>
struct my_totals : public std::binary_function<my_totals, double, my_totals>
{
    my_totals() : total_(0), count_(0) {};
    my_totals operator+(double v) const
    {
        my_totals ret = *this;
        ret.total_ += v;
        ++ret.count_;
        return ret;
    }
    double mean() const { return total_/count_; }
    double total_;
    unsigned count_;
};

...and then:

my_totals ttls = std::accumulate(v.begin(), v.end(), my_totals());
cout << "The sum of the values is: " << ttls.total_ << endl;
cout << "The mean value is: " << ttls.mean() << endl;

EDIT:

If you have the benefit of a C++0x-compliant compiler, this can be made even simpler using std::for_each (within #include <algorithm>) and a lambda expression:

double total = 0;
for_each( v.begin(), v.end(), [&total](double  v) { total += v; });
cout << "The sum of the values is: " << total << endl;
cout << "The mean value is: " << total/v.size() << endl;

You might want to consider using some algorithms instead:

// read in the data:
std::copy(std::istream_iterator<double>(input), 
          std::istream_iterator<double>(),
          std::back_inserter(v));

sum = std::accumulate(v.begin(), v.end(), 0);
average = sum / v.size();

You can modify the values with std::transform, though until we get lambda expressions (C++0x) it may be more trouble than it's worth:

class difference { 
    double base;
public:
    difference(double b) : base(b) {}
    double operator()(double v) { return v-base; }
};

std::transform(v.begin(), v.end(), v.begin(), difference(average));

Just use:

for (int i = 0; i < v.size(); i++)
{
    v[i] -= valueToSubstract;
}

Or its equivalent (and more readable?):

for (int i = 0; i < v.size(); i++)
    v[i] = v[i] - valueToSubstract;