At the file scope all words beginning with underscore are reserved.
See: http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier/228797#228797 https://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier/228797#228797
At the file scope all words beginning with underscore are reserved.
See: http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier/228797#228797
At the file scope all words beginning with underscore are reserved.
See: https://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier/228797#228797
Here is what I would do:
#include <map>
#include <memory>
#include <iterator>
#include <algorithm>
#include <iostream>
// Simple formatter used to
// Print the data in a particular way. This formatter is tied to the particular storage format.
struct OutputFormater
{
std::map<std::string, std::pair<int, int> >::value_type const& data;
OutputFormater(std::map<std::string, std::pair<int, int> >::value_type const& d)
: data(d)
{}
friend std::ostream& operator<<(std::ostream& stream, OutputFormater const& value)
{
std::string const& name = value.data.first;
int const& count = value.data.second.first;
int const& sum = value.data.second.second;
return stream << name << ": " << sum << ": " << (sum/count) << " ";
}
};
This I hope makes main very east to read.
int main()
{
std::map<std::string, std::pair<int, int> > data;
std::string name;
int count;
int totalCount = 0;
int totalSum = 0;
// Read in the data
while(std::cin >> name >> count)
{
totalCount++;
totalSum += count;
data[name].first++; // increment the count;
data[name].second += count; // increment the sum of counts;
}
// Copy the container to a stream using a formatter.
std::copy(data.begin(), data.end(), std::ostream_iterator<OutputFormater>(std::cout, "\n"));
if (totalCount > 0)
{
std::cout << totalSum << ": " << totalSum/totalCount << "\n";
}
}
Here is what I would do:
#include <map>
#include <memory>
#include <iterator>
#include <algorithm>
#include <iostream>
// Simple formatter used to
// Print the data in a particular way. This formatter is tied to the particular storage format.
struct OutputFormater
{
std::map<std::string, std::pair<int, int> >::value_type const& data;
OutputFormater(std::map<std::string, std::pair<int, int> >::value_type const& d)
: data(d)
{}
friend std::ostream& operator<<(std::ostream& stream, OutputFormater const& value)
{
std::string const& name = value.data.first;
int const& count = value.data.second.first;
int const& sum = value.data.second.second;
return stream << name << ": " << sum << ": " << (sum/count) << " ";
}
};
This I hope makes main very east to read.
int main()
{
std::map<std::string, std::pair<int, int> > data;
std::string name;
int count;
int totalCount = 0;
int totalSum = 0;
// Read in the data
while(std::cin >> name >> count)
{
totalCount++;
totalSum += count;
data[name].first++; // increment the count;
data[name].second += count; // increment the sum of counts;
}
// Copy the container to a stream using a formatter.
std::copy(data.begin(), data.end(), std::ostream_iterator<OutputFormater>(std::cout, "\n"));
if (totalCount > 0)
{
std::cout << totalSum << ": " << totalSum/totalCount << "\n";
}
}
Comments:
At the file scope all words beginning with underscore are reserved.
See: http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier/228797#228797
std::multimap<string,float> _map;
The aexct rules are a pain to remember (I had to go and check to make sure it was reserved). So I never prefix an identifier with '_'.
I would not define stream operators for standard types.
istream& operator>>(istream& stream, pair<string,float> &in )
ostream& operator<<(ostream& stream, pair<string,float> &out )
The trouble with doing this is that you may (in larger projects) clash with other people doing the same or with standard operators. (I though this would already work for std::pair without any work (obviously I was wrong)) I would only ever write stream operators fro my own types.
References are your friend:
istream *is = &cin;
Why take the address of a stream. Create a reference:
istream& is = &cin;
This is almost certainly wrong:
(*is) >> input;
_map.insert(input);
What happens if the input operator fails?
while(is >> input)
{
// Do until the input fails.
}
So rewriting your loop:
pair<string,float> input;
while(is >> input)
{
// Is not the whole point that a name may appear multiple times.
// Otherwise why compute the sum and average for each name
// Thus you need to increment the count.
myMap[input.first] += input.second;
}
Not a big deal with a small object but I would get in the habit of using references.
pair<string,float> p_pair = (*mit); // This makes a copy.
pair<string,float> const& p_pair = (*mit); // This is an alias to the object.