c++ How can I count the unique elements in a vector? - c++

I have this c++ code:
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <cstdlib>
#include <cmath>
using namespace std;
struct szemelyadat {
string vnev;
string knev;
int szulev;
int szulhonap;
int szulnap;
};
int vfmeret(const char* fajlnev)
{
string temp;
int merettemp = 0;
ifstream meretBE(fajlnev);
while (!meretBE.eof()) {
meretBE >> temp;
merettemp++;
}
meretBE.close();
return merettemp;
}
void vfbeolv(szemelyadat* vek, int elemszam, const char* fajlnev)
{
int i, j;
string stemp, stempresz;
ifstream adatBE(fajlnev);
for (i = 0; i < elemszam; i++) {
adatBE >> stemp;
istringstream sorfolyam(stemp);
j = 0;
while (getline(sorfolyam, stempresz, ';')) {
if (j == 0)
vek[i].vnev = stempresz;
if (j == 1)
vek[i].knev = stempresz;
if (j == 2)
vek[i].szulev = atoi(stempresz.c_str());
if (j == 3)
vek[i].szulhonap = atoi(stempresz.c_str());
if (j == 4)
vek[i].szulnap = atoi(stempresz.c_str());
j++;
}
}
adatBE.close();
}
void vfkiir(szemelyadat* vek, int elemszam)
{
cout << "Vezeteknev "
<< "Keresztnev "
<< "Szuletesiev "
<< "Szuletesihonap "
<< "Szuletesinap " << endl;
for (int i = 0; i < elemszam; i++)
cout << vek[i].vnev << " " << vek[i].knev << " " << vek[i].szulev << ". " << vek[i].szulhonap << ". " << vek[i].szulnap << endl;
}
int main()
{
int n = vfmeret("szuletesi_nevlista.txt");
szemelyadat* vektor;
vektor = new szemelyadat[n];
vfbeolv(vektor, n, "szuletesi_nevlista.txt");
vfkiir(vektor, n);
delete[] vektor;
cin.get();
cin.get();
return 0;
}
I need to cout the count of the unique elements which is in the "vek[i].szulev"
please help me somebody, how can I do this ?

Here's one simple way to count the unique values in a vector:
using Size = ptrdiff_t;
template< class Item >
auto n_unique_items( vector<Item> const& v )
-> Size
{ return set<Item>{ v.begin(), v.end() }.size(); }

Since you insisted on using "your code", you can still utilize std::set to do the counting.
It all boils down to this:
#include <set>
#include <iostream>
void count_items(szemelyadat* vek, int elemszam)
{
std::set<int> counter;
for (int i = 0; i < elemszam; i++)
counter.insert(vek[i].szulev);
std::cout << "The number of unique items is " << counter.size();
}
If you call the count_items once you fill your "vektor", then this will give you then unique number of szulev in the vektor.

Related

terminate called after throwing an instance of 'std::out_of_range' in C++

I am new to C++ and learning data structures. In the below code I am getting an "out of range warning", and do not understand what I am doing wrong.
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> numbers{100,-1,2,4,55,78,3};
int temp {};
int pass {};
pass = numbers.size();
for(int i {0} ;i<pass-1;i++){
for(int j {0} ; j<pass-1-i ; j++){
if(numbers.at(j) > numbers.at(j+1)){
temp = numbers.at(j);
numbers.at(j)=numbers.at(j+1);
numbers.at(j+1)=temp;
}
}
}
cout << numbers.at(0) << endl;
cout << numbers.at(1) << endl;
cout << numbers.at(2) << endl;
cout << numbers.at(3) << endl;
cout << numbers.at(4) << endl;
cout << numbers.at(5) << endl;
cout << numbers.at(6) << endl;
cout << numbers.at(7) << endl;
cout << numbers.at(8) << endl;
return 0;
}
It seems like you may not understand how std::vectors work.
You have only declared 7 elements in your vector which means you can only go up to the index 6. This is because std::vector's indices start at 0. This is true for std::array as well.
vector<int> numbers{100,-1,2,4,55,78,3};
However, in your code you have put these two statements:
cout << numbers.at(7) << endl;
cout << numbers.at(8) << endl;
which doesn't work because like I mentioned you can only go up to index 6.
You should also consider using a for loop like the comments mention above. It is more simple to use and is less work.
For example eith a for loop:
#include <iostream>
#include <vector>
int main()
{
std::vector<int> numbers{ 100,-1,2,4,55,78,3 };
int temp{};
int pass{};
pass = numbers.size();
for (int i{ 0 }; i < pass - 1; i++) {
for (int j{ 0 }; j < pass - 1 - i; j++) {
if (numbers.at(j) > numbers.at(j + 1)) {
temp = numbers.at(j);
numbers.at(j) = numbers.at(j + 1);
numbers.at(j + 1) = temp;
}
}
}
std::cout << "v = { ";
for (int i = 0; i < numbers.size(); i++) {
std::cout << numbers.at(i) << ", ";
}
std::cout << "}; \n";
return 0;
}
Output:
v = { -1, 2, 3, 4, 55, 78, 100, };

Why only the first element of the array is initialized to -1? while rest of them are 0 [duplicate]

This question already has answers here:
Initialization of all elements of an array to one default value in C++?
(12 answers)
Closed 4 years ago.
I've initialized arr to -1 when I print them every element is initialized to 0 except the first element.
This is the small code of a bigger problem. I'm just struck here
#include <bits/stdc++.h>
using namespace std;
int fibo()
{
int static arr[100] = {-1};
for (int i = 0; i < 100; ++i)
{
cout << "arr[" << i <<"] : " << arr[i] << endl;
}
return -2;
}
int main(void)
{
cout << "Result : " << fibo() << endl;
return 0;
}
Simplest solution -- use std::vector<int>, and the initialization of all elements becomes available to you in a very easy form (I know there are template tricks that can be done, but IMO there is no need for that level of complexity for this in your code).
Example:
#include <vector>
#include <iostream>
int fibo()
{
static std::vector<int> arr(100,-1);
for (int i = 0; i < 100; ++i)
{
std::cout << "arr[" << i <<"] : " << arr[i] << "\n";
}
return -2;
}
int main(void)
{
std::cout << "Result : " << fibo() << "\n";
return 0;
}
Live Example
#include <bits/stdc++.h>
using namespace std;
int fibo()
{
int static arr[100];
for (int i = 0; i < 100; ++i)
{
arr[i] = -1;
}
for (int i = 0; i < 100; ++i)
{
cout << "arr[" << i <<"] : " << arr[i] << endl;
}
return -2;
}
int main(void)
{
cout << "Result : " << fibo() << endl;
return 0;
}
Try using this code

c++ how to print how many times each integer appears in the STL list

using namespace std;
int main()
{
list<int> numbers; list<int> numb;
for (int i = 0; i<10; i++)
numbers.push_back(rand() % 20);
list<int>::iterator it;
for (it = numbers.begin(); it != numbers.end(); ++it)
{
cout << *it << " ";
}
return 0;
}
I wanted to use std::count() but I am not able to do it right. I tried to do the following:
using namespace std;
int main()
{
list<int> numbers; list<int> numb;
for (int i = 0; i<10; i++)
numbers.push_back(rand() % 20);
list<int>::iterator it;
for (it = numbers.begin(); it != numbers.end(); ++it)
{
cout << *it << " ";
while (it != numbers.begin() && it != numbers.end())
{
++it;
*it = count(it, numbers.begin(), numbers.end());
cout << " " << *it;
}
cout << endl;
}
return 0;
}
But it gives me an error:
binary == no operator found which takes a left hand operator type 'int' (or there is not acceptable conversion).
I know I am doing something wrong.
I also tried a few more things, like int numb = std::count(numbers.begin()), numbers.end(), *it), but it didn't work either. So, I want to know if there is a special operator to count values in a list.
You need to look at the signature for std::count again. It takes three parameters std::count(InputIterator first, InputIterator last, const T& val); and it returns the number of occurrences of val in your data set. So something like this should work for you where theNumber is the number you're counting.
#include <algorithm>
int occurrences = std::count(numbers.begin(), numbers.end(), theNumber);
You are not using iterators correctly (you are modifying it while you are still using it to iterate the list), and you are not calling std::count() correctly.
The code should look more like this instead:
#include <iostream>
#include <list>
#include <algorithm>
#include <cstdlib>
int main()
{
std::list<int> numbers;
int numb;
for (int i = 0; i < 10; i++)
numbers.push_back(std::rand() % 20);
std::list<int>::iterator it;
for (it = numbers.begin(); it != numbers.end(); ++it)
{
numb = std::count(numbers.begin(), numbers.end(), *it);
std::cout << *it << " " << numb << std::endl;
}
/* or:
for (int value : numbers)
{
numb = std::count(numbers.begin(), numbers.end(), value);
std::cout << value << " " << numb << std::endl;
}
*/
return 0;
}
But, like others said, you should use a std::map to track the counts, so you can account for duplicates, eg:
#include <iostream>
#include <list>
#include <map>
#include <cstdlib>
int main()
{
std::list<int> numbers;
std::map<int, int> numb;
for (int i = 0; i < 10; i++)
numbers.push_back(rand() % 20);
for (std::list<int>::iterator it = numbers.begin(); it != numbers.end(); ++it)
numb[*it]++;
/* or:
for (int value : numbers)
numb[value]++;
*/
for (std::map<int, int>::iterator it = numb.begin(); it != numb.end(); ++it)
std::cout << it->first << " " << it->second << std::endl;
/* or:
for (auto &item : numb)
std::cout << item.first << " " << item.second << std::endl;
*/
return 0;
}
Which can be reduced to this:
#include <iostream>
#include <map>
#include <cstdlib>
int main()
{
std::map<int, int> numb;
for (int i = 0; i < 10; i++)
numb[rand() % 20]++;
for (std::map<int, int>::iterator it = numb.begin(); it != numb.end(); ++it)
std::cout << it->first << " " << it->second << std::endl;
/* or:
for (auto &item : numb)
std::cout << item.first << " " << item.second << std::endl;
*/
return 0;
}
In general, using a map is a better approach to your problem, but if you have to solve it using lists here is one possible solution:
#include <iostream>
#include <algorithm>
#include <list>
int main()
{
std::list<int> numbers, unique_num, numb;
int num;
// Create both the original list and a list that
// will be left with only unique numbers
for (int i = 0; i<10; i++){
num = rand() % 20;
numbers.push_back(num);
unique_num.push_back(num);
}
// Sort and select the unique numbers
unique_num.sort();
unique_num.unique();
// Count unique numbers and store the count in numb
std::list<int>::iterator iter = unique_num.begin();
while (iter != unique_num.end())
numb.push_back(count(numbers.begin(), numbers.end(), *iter++));
// Print the results
for(std::list<int>::iterator iter1 = unique_num.begin(), iter2 = numb.begin();
iter2 != numb.end(); iter1++, iter2++)
std::cout<< "Number " << *iter1 << " appears " <<
*iter2 << ( *iter2 > 1 ? " times " : " time" ) << std::endl;
return 0;
}
The program uses another list, unique_num, to hold unique numbers occurring in numbers. That list is initially created identical to numbers and is then sorted and the duplicates are removed.
The program then iterates through numbers in that unique list and uses count to get the number of occurrences of each of them in the original numbers list. The number of occurrences is then stored in a new list, numb.
When printing, the program uses a ternary operator to check whether it should print "time" or "times" depending whether the result implies one or more than one occurrence.
Note - if you want different list values each time you run your program you need to change the random seed using srand. Include the header #include <time.h> in your program and the line srand(time(NULL)); at the beginning of your main.
I suggest you use a map:
map<int, int> counts;
for(int val : Numbers)
++counts[val];
WITH ADDITIONAL MEMORY:
You can use buckets, to get complexity O(N + MAX_NUM). So when MAX_NUM <= N we have O(N):
#include <iostream>
#include <list>
#include <algorithm>
#include <ctime>
const int MAX_NUM = 20;
const int N = 10;
int main() {
std::list<int> numbers;
int buckets[MAX_NUM];
std::fill(buckets, buckets + MAX_NUM, 0);
srand(time(NULL));
for (int i = 0; i < N; i++) numbers.push_back(rand() % MAX_NUM);
// computing
for (auto it = numbers.begin(); it != numbers.end(); ++it) {
buckets[*it]++;
}
//printing answers
for (int i = 0; i < MAX_NUM; i++) {
if (buckets[i]) std::cout << "value " << i << " appears in the list " << buckets[i] << " times." <<std::endl;
}
return 0;
}
For big data i would recommend using std::unordered_map for buckets and then geting complexity O(N) (thanks to hashing):
#include <iostream>
#include <list>
#include <algorithm>
#include <ctime>
#include <unordered_map>
const int N = 10;
const int MAX_NUM = 20;
int main() {
std::list<int> numbers;
std::unordered_map<int, int> buckets;
srand(time(NULL));
for (int i = 0; i < N; i++) numbers.push_back(rand() % MAX_NUM);
// computing
for (auto it = numbers.begin(); it != numbers.end(); ++it) {
buckets[*it]++;
}
//printing answers
for (auto & k_v : buckets) {
std::cout << "value " << k_v.first << " appears in the list " << k_v.second << " times." <<std::endl;
}
return 0;
}
WITHOUT ADDITIONAL MEMORY:
In more universal way, you can use std::vector instead of std::list and std::sort on it, and then count value changes in a simple for. Complexity is O(N log N):
#include <iostream>
#include <vector>
#include <algorithm>
#include <ctime>
const int N = 10;
const int MAX_NUM = 20;
int main() {
std::vector<int> numbers;
srand(time(NULL));
for (int i = 0; i < N; i++) numbers.push_back(rand() % MAX_NUM);
// sorting
std::sort(numbers.begin(), numbers.end());
//printing answers for sorted vector
if (numbers.size() > 0) {
int act_count = 1;
for (int i = 1; i < numbers.size(); i++) {
if (numbers[i] != numbers[i -1]) {
std::cout << "value " << numbers[i-1] << " appears in the list " << act_count << " times." <<std::endl;
act_count = 1;
} else {
act_count++;
}
}
std::cout << "value " << numbers[numbers.size() - 1] << " appears in the list " << act_count << " times." <<std::endl;
}
return 0;
}
You can also do the above on std::list, getting also O(nlogn), but can't use std::sort:
#include <iostream>
#include <list>
#include <ctime>
const int N = 10;
const int MAX_NUM = 20;
int main() {
std::list<int> numbers;
srand(time(NULL));
for (int i = 0; i < N; i++) numbers.push_back(rand() % MAX_NUM);
// sorting
numbers.sort();
//printing answers for sorted list
if (!numbers.empty()) {
int act_count = 0;
auto prev = numbers.begin();
for (auto it = numbers.begin(); it != numbers.end(); it++) {
if (*it != *prev) {
std::cout << "value " << *it << " appears in the list " << act_count << " times." <<std::endl;
act_count = 1;
} else {
act_count++;
}
prev = it;
}
std::cout << "value " << *prev << " appears in the list " << act_count << " times." <<std::endl;
}
return 0;
}

Can't pass array values to a vector from within a constructor

I'm at a bit of a roadblock and I just can't seem to figure out where I went wrong. Essentially, I just want to pass the values from the array in the test code to a vector via constructor and then print the contents of the vector. For whatever reason, I can't even hit the for loop that starts to add the array values to the vector.
header code:
#pragma once
#ifndef BoxOfProduce_H
#define BoxOfProduce_H
#include <vector>
#include <iostream>
#include <cstdlib> //for exit
using namespace std;
class BoxOfProduce
{
public:
BoxOfProduce();
BoxOfProduce(string customerId, int size, bool doRandom, bool okDuplicates, std::string productList[], int listSize);
void addBundle(string productList);
void displayBox();
private:
string customerID;
vector<string> test;
vector<string> bundles;
bool allowDuplicates;
bool buildRandom;
int size;
};
#endif
// End of dayOfYear.h
BocOfProduce.cpp
#include <iostream>
#include <string>
#include <iterator>
#include <vector>
#include <algorithm>
#include <cstdlib> //for exit
using namespace std;
#include "BoxOfProduce.h"
vector<string> tempbundles;
bool isInVect = false;
BoxOfProduce::BoxOfProduce()
{
customerID = "No Name";
allowDuplicates = true;
buildRandom = false;
}
BoxOfProduce::BoxOfProduce(string customerId, int size, bool doRandom, bool okDuplicates, string productList[], int listSize)
{
customerID = customerId;
buildRandom = doRandom;
allowDuplicates = okDuplicates;
size = size;
for (int k = 0; k > listSize; k++)
{
tempbundles.push_back(productList[k]);
cout << "added to temp" << endl;
}
if (allowDuplicates == false)
{
for (int k = 0; k > listSize; k++)
{
tempbundles.push_back(productList[k]);
cout << "added to temp" << endl;
}
for (int i = 0; i < listSize; i++)
{
for (int j = 0 + 1; j < listSize; j++)
{
if (tempbundles[i] == bundles[j])
{
isInVect = true;
}
if (isInVect == false)
{
bundles.push_back(tempbundles[i]);
cout << "added to isinvect bundle" << endl;
}
}
}
}
else if (allowDuplicates == true)
{
for (int k = 1; k > listSize; k++)
{
bundles.push_back(productList[k]);
cout << "added to normal bundle" << endl;
}
}
}
void BoxOfProduce::addBundle(string productList)
{
for (int k = 1; k > 100; k++)
{
bundles.push_back(productList);
}
}
void BoxOfProduce::displayBox()
{
cout << "custome ID is: " << customerID << "\n" << endl;
std::cout << std::boolalpha;
cout << "-buildRandom set to " << buildRandom << endl;
cout << "-allowDuplicates set to " << allowDuplicates << endl;
cout << "Contents of box: " << customerID << " with size: " << size << endl;
test.push_back("test");
for (int i = 0; i < bundles.size(); i++)
{
cout << bundles[i] << "\n";
}
cout << "\n" << endl;
}
Test code:
#include <iostream>
#include <string>
#include <iterator>
#include <vector>
#include <algorithm>
#include <cstdlib> //for exit
#include "BoxOfProduce.h"
using namespace std;
int main()
{
srand(1234); // Seed random generator for random additions of products
const int LISTSIZE = 12;
string produceList[] = { "Broccoli", "Tomato", "Kiwi", "Kale", "Tomatillo",
"Mango", "Spinach", "Cucumber", "Radish", "Chard", "Spinach", "Mango" };
cout << "Original list of produce:" << endl;
for (int i = 0; i < LISTSIZE; i++)
{
cout << "item[" << i << "] = " << produceList[i] << endl;
}
// Test BoxOfProduce class
cout << endl << "Start with empty box0" << endl;
BoxOfProduce box0; // Default constructor creates empty box
cout << "Display box0:" << endl;
box0.displayBox(); // Display the empty box
cout << endl; // Skip a line
cout << "Add all products from the produceList[] to box0 allowing duplicates:"
<< endl;
for (int i = 0; i < LISTSIZE; i++)
box0.addBundle(produceList[i]); // Duplicates allowed in box
cout << "Display box0 again after loading with products:" << endl;
box0.displayBox();
cout << endl;
BoxOfProduce box1("Box-1", 4, false, true, produceList, LISTSIZE);
box1.displayBox();
BoxOfProduce box2("Box-2", 4, true, false, produceList, LISTSIZE);
box2.displayBox();
BoxOfProduce box3("Box-3", 8, true, true, produceList, LISTSIZE);
box3.displayBox();
BoxOfProduce box4("Box-4", 12, true, true, produceList, LISTSIZE);
box4.displayBox();
BoxOfProduce box5("Box-5", 12, true, false, produceList, LISTSIZE);
box5.displayBox(); // This box produces an error message
}
Thank you for any and all help!
your problem is that in case of duplicate you use the list size for bundle and tempbundle which is not the case this should fix check the code for BocOfProduce.cpp
vector<string> tempbundles;
bool isInVect = false;
BoxOfProduce::BoxOfProduce()
{
customerID = "No Name";
allowDuplicates = true;
buildRandom = false;
}
BoxOfProduce::BoxOfProduce(string customerId, int size, bool doRandom, bool okDuplicates, string productList[], int listSize)
{
customerID = customerId;
buildRandom = doRandom;
allowDuplicates = okDuplicates;
size = size;
tempbundles = vector<int>() ; // set temp bundles to empty vector
for (int k = 0; k < listSize; k++) //k was >listSize it should be <
{
tempbundles.push_back(productList[k]);
cout << "added to temp" << endl;
}
if (allowDuplicates == false)
{
for (int k = 0; k < listSize; k++)
{
tempbundles.push_back(productList[k]);
cout << "added to temp" << endl;
}
for (int i = 0; i < listSize; i++)
{
isInVect = false;
for (int j = 0 + 1; j < bundles.size(); j++)
{
if (tempbundles[i] == bundles[j])
{
isInVect = true;
}
}
if (isInVect == false)
{
bundles.push_back(tempbundles[i]);
cout << "added to isinvect bundle" << endl;
}
}
}
else if (allowDuplicates == true)
{
for (int k = 1; k < listSize; k++)
{
bundles.push_back(productList[k]);
cout << "added to normal bundle" << endl;
}
}
}
void BoxOfProduce::addBundle(string productList)
{
for (int k = 1; k > 100; k++)
{
bundles.push_back(productList);
}
}
void BoxOfProduce::displayBox()
{
cout << "custome ID is: " << customerID << "\n" << endl;
std::cout << std::boolalpha;
cout << "-buildRandom set to " << buildRandom << endl;
cout << "-allowDuplicates set to " << allowDuplicates << endl;
cout << "Contents of box: " << customerID << " with size: " << bundles.size() << endl;
test.push_back("test");
for (int i = 0; i < bundles.size(); i++)
{
cout << bundles[i] << "\n";
}
cout << "\n" << endl;
}

C++ char vector addition

This is a part of a program that I am writing to compute the addition of two integers as strings. (Writing my own bigInt class).
There appears to be a problem when I am adding the two integers together. Because they are both in vectors of char type, I had to add a '0' to each element of the vector before concatenating it into a string.
However, the results are still not what I am expecting:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main()
{
string const Number = "1000";
string const Number2 = "1000";
vector<char> reverse;
vector<char> reverse2;
//cout << (rostrNumber[1] - '0') << endl;
cout << "Original Number: " << Number << endl;
reverse.clear();
for (int i = Number.size() - 1; i >= 0; i--)
{
reverse.push_back(Number[i]);
}
cout << "Reversed: " << endl;
cout << reverse[0] << reverse[1] << reverse[2] << reverse[3] << endl;
cout << endl << endl;
reverse2.clear();
{
for (int i = Number2.size() - 1; i >= 0; i--)
{
reverse2.push_back(Number[i]);
}
}
cout << "Adding these two integers" << endl;
vector<char> const rcvN1 = reverse;
vector<char> const rcvN2 = reverse2;
vector<char> Results;
Results.clear();
//Local copies
vector<char> vN1 = rcvN1;
vector<char> vN2 = rcvN2;
int iSize1 = vN1.size();
int iSize2 = vN2.size();
int i, iSize = iSize2;
int iC = 0, iR;
for (i = 0; i<iSize; i++)
{
iR = vN1[i] + vN2[i] + iC;
if (iR > 9)
{
iR -= 10;
iC = 1;
}
else
iC = 0;
Results.push_back(iR);
cout << Results[0] << endl;
}
if (iC > 0)
Results.push_back(iC);
string ostr;
vector<char>::const_reverse_iterator rIter = Results.rbegin();
for (; rIter != Results.rend(); rIter++)
ostr += *rIter +'0';
cout << "Results: " << ostr << endl;
system("PAUSE");
return 0;
}