Reputation: 634
The contents of my file are:
1,2,5
2,4
2,3
1,2,4
1,3
2,3
1,3
1,2,3,5
1,2,3
And my code is:
#include<iostream>
#include<set>
#include<vector>
#include<fstream>
#include<sstream>
#include<set>
#include<cstdlib>
#include<algorithm>
using namespace std;
struct store {
string a;
int count;
};
int main() {
store ap[100];
vector<string> v;
set<string> input;
int mycount;
ifstream fin("trans.txt");
string line, s, str1, token;
while(!fin.eof()) {
fin >> line;
// cout<<"i cant understand but correct"<<line<<endl;
istringstream str1(line);
while(getline(str1, token, ',')) {
//cout<<"the token are\t"<<token<<endl;
v.push_back(token);
input.insert(token);
}
//v.push_back(token);
//input.insert(token);
int i = 0;
for(set<string>::iterator it = input.begin(); it != input.end(); it++) {
mycount = count(v.begin(), v.end(), *it);
s = *it;
ap[i].a = s;
ap[i].count = mycount;
cout << ap[i].a << "\t" << "mycount" << ap[i].a << endl;
i++;
}
}
}
I am implementing Apriori algorithm each line represents the transaction i.e the items stored in a file my file consists of numbers like this how to store the occurrences of each number and its count
My output should be like this:
1 6
2 7
3 7
4 2
5 2
However I am unable to store individually I mean 1 and all its occurrences 2 and all its occurrences etc etc.
Can any tell me how to store like above example
Upvotes: 2
Views: 1216
Reputation: 42964
If the numbers you are reading are in a small range (e.g. 0-10, or even 0-200, etc.), instead of using [std::map
(http://en.cppreference.com/w/cpp/container/map), you could use a simple array.
Map's key is the array index, and map's value (i.e. occurrences) is the array value for that index.
e.g. the occurrences of number 3 are stored in the integer array at index 3.
See the following commented code for details.
I compiled that code with VS2010 SP1 (VC10) and executed it, and it seems to work correctly (at least for your input file sample data).
#include <cstdlib>
#include <exception>
#include <fstream>
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <string>
using namespace std;
int main()
{
static const int kExitOk = 0;
static const int kExitError = 1;
try
{
// Open text file for reading
ifstream inFile("data.txt");
// Occurrence table
static const int kMaxNum = 10;
int occurrences[kMaxNum + 1] = {0}; // init to 0s
// Line read from file
string line;
// For each line in file
while (getline(inFile, line))
{
// Process each line content using string streams
istringstream iss(line);
// Read numbers (separated by comma) from current line
string token;
while (getline(iss, token, ','))
{
// Convert from string to integer
const int num = atoi(token.c_str());
// Just do a bounds checking for safety...
if (num < 0 || num > kMaxNum)
throw runtime_error("Bad input number found in file.");
// Update occurrence of given number
occurrences[num]++;
}
}
// Print occurrences
for (int i = 0; i <= kMaxNum; i++)
{
if ( occurrences[i] != 0 )
{
cout << i << ' ' << occurrences[i] << '\n';
}
}
return kExitOk;
}
catch(const exception& e)
{
cerr << "\n*** ERROR: " << e.what() << endl;
return kExitError;
}
}
If you want to use a std::map
, just add #include <map>
, and replace the array definition with:
// Occurrence table
map<int, int> occurrences;
You can print the map content with code like this:
// Print occurrences
for (auto it = occurrences.begin(); it != occurrences.end(); ++it)
{
cout << it->first << ' ' << it->second << '\n';
}
Note that using std::map
the occurrence update code is formally the same as for the array case:
// Update occurrence of given number
occurrences[num]++; // works also for std::map
Upvotes: 4
Reputation: 490178
I'd start with a ctype_facet that classifies everything but digits (and, optionally -
) as "whitespace", so it'll be completely skipped as you read the data:
struct number_only: std::ctype<char> {
number_only() : std::ctype<char>(get_table()) {}
static mask const *get_table() {
static std::vector<mask> rc(table_size, space);
std::fill_n(&rc['0'], 10, digit);
rc['-'] = punct;
return &rc[0];
}
};
With that, reading the data becomes much more straightfoward -- we don't have to do anything to ignore the commas because extracting an int from the stream will do that for us automatically. Once we read them, we just increment their count in a map, then print out the map:
typedef std::pair<int, int> count;
std::ostream &operator<<(std::ostream &os, count const &p) {
return os << p.first << "\t" << p.second;
}
int main() {
std::map<int, int> numbers;
int temp;
std::cin.imbue(locale(local(), new number_only);
while (std::cin >> temp)
++numbers[temp];
std::copy(numbers.begin(), numbers.end(),
std::ostream_iterator<count>(std::cout, "\n"));
}
Upvotes: 3
Reputation: 7220
You should consider using a map, where the key is the number, and the value it's count.
http://www.cplusplus.com/reference/map/map/
It basically lets you do something similar to this. I know this is not valid C++ though :) but it should give you an idea of what I mean.
std::map<int, int> numbers;
for (read number from file) {
numbers[number from file] = numbers[number from file] + 1;
}
Upvotes: 1