1. ## Algorithm Questions

I have a file filled with sales info each line in the text file is a different sale done by a different Sales Person which is denoted by a 2 char code as in 'r1'. But sale people repeat and there's no foreknowlege how many sales people there will be and of course no knowledge how many sales each will have... Well I need to parse out each unique sales person and the # sales each has and at the end a total of all sales.

My algorithm:
pull out each unique SalesPerson's ID
cycle input file through map/set counting qty of each ID(sales)
output each id and associated sales with each
total of count of all sales

Not quite sure how to do this or if I have it all together some suggestions would help alot..

2. Here's some code of what I had so far it doesn't compile because of what data I sent through...

Code:
```int TsrGrouper(string inSource2)
/*Searches given file and tallys up each TSR's sales in a formatted report
by month*/

{
ifstream source(inSource2.c_str());
string line;
int x=0;
char *Tsrmap[16];
while (getline(source,line))
{
//cout<<line.substr(513,2)<<"  ";
if (!Tsrmap[line.substr(513,2)])
Tsrmap[line.substr(513,2)] = true;

for (Tsrmap[x],x>15,x++){
cout<<"  "<<Tsrmap[x]<<endl;
}
}

return 0;
}```
I was trying to add one of each ID to the map and then I would cycle through the file again and make a counter for each ID to get a count of sales.. Need some clues on how to use this or maybe an array I know that map doesn't allow Tsrmap[line.subtring(513,2)]
because it has to refer to a int but there is a way right???

3. hmm, seems to me you need a little refresher on C++ before going much further. but basically, the steps I would suggest would be:

1) begin with a container of sales-persons records.
2) read each sale into a container of sale-transactions.
3) to obtain sales by person implement:

Code:
```for each salesperson {
total = 0
for each transaction {
if transaction.salesperson == salesperson {
}
}
output the sales for this person
}```
4) for total sales of course, just run through all transactions and accumulate the total.

4. I was reading up on containers when I came across this example would this be able to be converted over to my problem?? I know that I have to change the multiset to something other than char but not sure I would be able to use char* or string. Again my Saleperson Id's are two characters long. This code runs as is. Is this modifiable to my task?
Code:
```#include "stdafx.h"
#include <iostream>
#include <sstream>
#include <fstream>
#include <functional>
#include <set>
#include <string>
#include <map>
using namespace std;

int main()
/*Searches given file and tallys up each TSR's sales in a formatted report
by month*/
{
multiset<char> ms1;

// Load set1 using the insert method.
string s1("now is the time for all good men to come ");
s1.append("to the aid of their country");

ms1.insert(s1.begin(),s1.end());    // Arguments are a pair of iterators

string letters("abcdefghijklmnopqrstuvwxyz");

// count returns the number of keys in the multiset
// equal to the given value
for (int i = 0; i < letters.length(); i++) {
cout << letters[i] << ": " << ms1.count(letters[i]) << endl;
}

cout << "ms1 has " << ms1.size() << " elements" << endl;
return 0;

}```

5. Try taking a look into std::map.

i.e.
std::map< std::string, std::list<Sale> >

That way, you can do something like:
Code:
```std::map< std::string, std::list<Sale> > mapOfSales

mapOfSales["r1"].push_back(Sale("boots", "\$500"));
...

//For each salesman/saleswoman:
for(std::map< std::string, std::list<Sale> >::iterator mapIt = mapOfSales.begin();
mapIt != mapOfSales.end(); ++mapIt)
{
//Display the ID of this particular salesman

for(std::list<Sale>::iterator listIt = (*mapIt).begin();
listIt != (*mapIt).end(); ++listIt)
{
//Display the details of the sale
}
}```
Otherwise, you might like to look into a std::multimap, though I haven't had experience with them.

6. **Didn't want to edit my post, because that would kill the indentation in the code and I'm too lazy to fix it..

Made a mistake, everywhere you see (*mapIt), it should actually be (mapIt->second).

If you just want the number of sales, you can do:
Code:
```std::map<std::string, int> theMap;
...
//each time you come across a sale by "r1":
(theMap["r1"])++;
...
for(std::map<std::string, int>::iterator mapIt = theMap.begin(); mapIt != theMap.end(); ++mapIt)
std::cout << mapIt->first << " made " << mapIt->second << " sales.\n";```

7. Here's what I got in terms of data to use

The sales person's id is at location (513,2) on a line. Each line is a sale.
I need to bring in one person's ID and count how many lines(sales) that ID has. Then go to the next ID making sure that the previous ID's don't equal the present one.
And then out put something like this
Report for December
TSR(sales person) Orders
r1 8
r2 9
f3 15
t2 12
g2 7
t3 11
r2 14
y1 19

Total 95

No other data of the source file is needed just the id and how many sales each ID got.

8. >>making sure that the previous ID's don't equal the present one.
I don't get it, why does it matter what the previous ID was?

Go through my second example, you can very very easily adapt it to your needs. In fact, the part that I've written should work pretty much without change; all you need to do is to put the code into a loop where you read a line, get the salesperson's ID, and increase their 'sales' count. Then, the last bit of code in my example will print the table for you, pretty much exactly as you said. The loop you've already got written (the one you posted originally) is about 75% there already.

9. After I sent up my last post I saw your last reply but I'm still having problems with loading the map has to be a char*??

Here's my code I'm trying
Code:
```std::map<std::string, int> theMap;
while (getline(source,line))
{

theMap.insert(line.substr(513,2));
}

//each time you come across a sale by "r1":
(theMap["r1"])++;

for(std::map<std::string, int>::iterator mapIt = theMap.begin(); mapIt != theMap.end(); ++mapIt)
std::cout << mapIt->first << " made " << mapIt->second << " sales.\n";

return 0;
}```
With this modified would I be able to cycle through each salesperson to output each ID's sales and then total up everything at the end?
Thanks again for all the help

10. >>making sure that the previous ID's don't equal the present one.
I don't get it, why does it matter what the previous ID was?

What I mean is that the ID repeats and when that ID repeats wouldn't it just count how many times that ID exists all over again?

11. This is the error I get with using
theMap.insert(line.substr(513,2));

:\Documents and Settings\tbixler\Desktop\parser\TSR Reports\TSR Reports.cpp(48) : error C2664: 'struct std:air<class std::_Tree<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,struct std:air<class std::ba
sic_string<char,struct std::char_traits<char>,class std::allocator<char> > const ,int>,struct std::map<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,int,struct std::less<class std::basic_string<char,struct s
td::char_traits<char>,class std::allocator<char> > >,class std::allocator<int> >::_Kfn,struct std::less<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<int> >::iterator,bool> __thiscall
std::map<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,int,struct std::less<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<int> >::insert(const
struct std:air<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const ,int> &)' : cannot convert parameter 1 from 'class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >' to
'const struct std:air<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const ,int> &'
Reason: cannot convert from 'class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >' to 'const struct std:air<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const ,i
nt>'
No constructor could take the source type, or constructor overload resolution was ambiguous

Sorry for the length of the errror ....

12. This is the error I get with using theMap.insert(line.substr(513,2));
Yes, insert() takes a std:pair<key_type, value_type>, in this case std:pair<std::string, int>. What's convenient though, is that the [] operator automagically inserts a new key/value pair into the map if one doesn't already exist with the same key. So when you reach this line:
Code:
`(theMap[line.substr(513,2)])++;`
If the ID/count pair weren't already inserted into the map, then it will automatically be inserted here, and then the value will be incremented. Also, I'm not 100% sure about this, but I believe it will initialize count to 0 when it is inserted (I ran a test and it initialized it to 0, but it might have just been because of debugging stuff the compiler added). So instead of doing an insert(), just put the ++ line in there.

In case it doesn't initialize it to 0 though, you can do this to ensure that it does what you want:
Code:
```std::map<...>::iterator it = theMap.find(line.substr(523,2));
if(it == theMap.end()) //If no entries counted yet
theMap[line.substr(523,2)] = 1; //Then add it, and initialize it to a count of 1
else
(it->second)++; //Otherwise, increase the counter.```
Just to note, (a map's iterator)->first is the 'key' of the pair, in this case the std::string that you use as the 'index', while ->second is the 'value' of the pair, in this case the int counter.

If you have any questions about how it all works, feel free to ask (I don't know how much of this you already know and understand, you seem to know a fair bit, so I won't explain unless you don't understand).

Hope this helps! :)

13. Here's what i ended up with:

Code:
```TsrGrouper(string inSource2)
/*Searches given file and tallys up each TSR's sales in a formatted report
by month*/
{
ifstream source(inSource2.c_str());
string line;
int total=0;
std::map<std::string, int> theMap;
while (getline(source,line))
{

theMap[line.substr(513,2)]++;
}
for(std::map<std::string, int>::iterator mapIt = theMap.begin(); mapIt != theMap.end(); ++mapIt)
{
cout << mapIt->first << " made " << mapIt->second << " sales.\n";
total+=mapIt->second;

}
cout<<"Total Sales: "<<total<<endl;
return 0;
}```
It works great I added the total sales to make sure no lines were missed so the counts for the files should be right.
Thanks alot I wasn't quite sure how the code was coming out till it actually ran... Automagically!!!
Thanks again.

14. Always glad to help. I hope you really learned how it all works, because maps are a little confusing at first, but they're a very powerful tool to keep in your backyard when you need them