priority queue and structs - c++

#include <iostream>
#include <queue>
using namespace std;
struct Call
{
Call( int callNum, long callTime, int callLength ) :
CallNum( callNum ), CallTime( callTime ), CallLength( callLength ) { }
int CallNum;
long CallTime;
int CallLength;
};
bool operator>( const Call& lhs, const Call& rhs ) {
return lhs.CallLength > rhs.CallLength;
}
ostream& operator<<( ostream& os, const Call& c ) {
os << c.CallNum << " " << c.CallTime << " " << c.CallLength;
return os;
}
int main()
{
priority_queue< Call, vector<Call>, greater<Call> > q;
q.push( Call( 1, 200, 150 ));
q.push( Call( 2, 300, 950 ));
q.push( Call( 3, 100, 450 ));
q.push( Call( 4, 150, 320 ));
unsigned i=0, n=q.size();
for ( i=0; i<n; ++i ) {
cout << q.top() << endl;
q.pop();
}
}
This is my code. My problem is, When I use q.top(); it prints to screen callNum, callTime, callLength. But I want to use them seperately.
I mean How can I print to screen just callTime? for ex: q.top(callTime); or something else? who can help me?

Are you just looking for:
cout << q.top().CallNum << endl;
and so on?

Related

Why is count_if giving me the total of texts

I was testing the following code, and a bit perplexed as to why count_if is returning me the total of texts?
Match function that takes string of Text as argument and returns true is the Text size is 4
bool Match(string Text)
{
if (Text.size() == 4)
return true;
}
numMatchwes produces the total number of Text in a vector
int numMatches(vector<string>Texts, bool (*Match)(string Text)) // Texts is an array
{
int count = 0;
for (int i = 0; i < Texts.size(); i++)
{
if (Match(Texts[i]) == 1)
// checking every string in vector and returns true
count++;
}
return count;
}
The main function
int main()
{
vector<string> texts;
texts.push_back("Bing");
texts.push_back("Pony");
texts.push_back("Mil");
texts.push_back("Sillty");
texts.push_back("Ballz");
texts.push_back("Mars");
cout << Match("Sind") << endl;
cout << "Matches are: " << numMatches(texts, Match) << endl;
cout << endl;
int num = count_if(texts.begin(), texts.end(), Match); // count_if is STL function
cout << num << endl;
}
Now I’m confused as to why count_if is giving me the total of texts?
The function Match has undefined behavior in case when the passed string does not have a length equal to 4.
Define it the following way
bool Match( const std::string &Text )
{
return Text.size() == 4;
}
Correspondingly the function numMatches can be defined the following way
auto numMatches( const std::vector<std::string> &Texts, bool Match(const std::string & ) )
{
std::vector<std::string>::size_type count = 0;
for ( const auto &s : Texts )
{
if ( Match( s ) ) ++count;
}
return count;
}
Here is your updated program.
#include <iostream>
#include <iomanip>
#include <string>
#include <vector>
#include <iterator>
#include <algorithm>
auto numMatches( const std::vector<std::string> &Texts, bool Match(const std::string & ) )
{
std::vector<std::string>::size_type count = 0;
for ( const auto &s : Texts )
{
if ( Match( s ) ) ++count;
}
return count;
}
bool Match( const std::string &Text )
{
return Text.size() == 4;
}
int main()
{
std::vector<std::string> texts;
texts.push_back( "Bing" );
texts.push_back( "Pony" );
texts.push_back( "Mil" );
texts.push_back( "Sillty" );
texts.push_back( "Ballz" );
texts.push_back( "Mars" );
std::cout << std::boolalpha << Match( "Sind" ) << '\n';
std::cout << "Matches are: " << numMatches( texts, Match ) << '\n';
std::cout << '\n';
auto num = std::count_if( std::begin( texts ), std::end( texts ), Match );
std::cout << num << std::endl;
return 0;
}
The program output is
true
Matches are: 3
3

C++ resize 2d vector where function is const

I create a 2D vector (0,0) and would like to resize it (n,m), however, my resize function must remain const
I have tried doing
void resize(int row, int col) const
{
array.resize(row, vector<int>(col));
}
but keep getting
passing ‘const std::vector<std::vector<int>, std::allocator<std::vector<int> > >’ as ‘this’ argument discards qualifiers
How can I do this?
Matrix.h
#pragma once
#include <vector>
using namespace std;
template <typename Object>
class matrix
{
public:
matrix(int rows, int cols) : array{ rows } {
for (auto& thisRow : array)
thisRow.resize(cols);
}
matrix( initializer_list<vector<Object>> lst ) : array( lst.size( ) )
{
int i = 0;
for( auto & v : lst )
array[ i++ ] = std::move( v );
}
matrix( const vector<vector<Object>> & v ) : array{ v } {}
matrix( vector<vector<Object>> && v ) : array{ std::move( v ) } {}
matrix() {}
const vector<Object> & operator[]( int row ) const
{
return array[ row ];
}
vector<Object> & operator[]( int row )
{
return array[ row ];
}
int numrows() const
{
return array.size( );
}
int numcols() const
{
return numrows( ) ? array[ 0 ].size( ) : 0;
}
void resize(int row, int col) const
{
array.resize(row, vector<int>(col));
}
private:
vector<vector<Object>> array;
};
main.cpp
matrix<int> mat = matrix<int>();
cout << "Zero-parameter matrix (rows,cols) = (" << mat.numrows() << "," << mat.numcols() << ")" << endl;
mat.resize(4, 3);
cout << "Resized matrix to 4x3" << endl;
cout << mat << endl;
mat[2][1] = 12;
cout << "Modified (2,1)" << endl;
cout << mat << endl;
When you put const on the end of the function there, you're saying the implicit this is const. That is, you're promising not to modify the state of the object this function is being called on.
But isn't the whole point of calling resize() to modify the state of the object? If I were you, I'd take the const off of there.
In other words, you have two options: either keep your promise to not change the state of the object (perhaps by returning a resized copy?), or lose the const.

How to find indexes of the n greatest elements

I have a container (Vector) of some arbitrary type and i want to get a vector with indices of the n greatest (or smallest) elements.
Is there a standard way to do so?
This is exactly the topic of one of the guru of the week http://www.gotw.ca/gotw/073.htm
I am reporting the preferred solution, however, I strongly recommend you to read the article (and the blog in general), it is really good.
#include <vector>
#include <map>
#include <algorithm>
namespace Solution3
{
template<class T>
struct CompareDeref
{
bool operator()( const T& a, const T& b ) const
{ return *a < *b; }
};
template<class T, class U>
struct Pair2nd
{
const U& operator()( const std::pair<T,U>& a ) const
{ return a.second; }
};
template<class IterIn, class IterOut>
void sort_idxtbl( IterIn first, IterIn last, IterOut out )
{
std::multimap<IterIn, int, CompareDeref<IterIn> > v;
for( int i=0; first != last; ++i, ++first )
v.insert( std::make_pair( first, i ) );
std::transform( v.begin(), v.end(), out,
Pair2nd<IterIn const,int>() );
}
}
#include <iostream>
int main()
{
int ai[10] = { 15,12,13,14,18,11,10,17,16,19 };
std::cout << "#################" << std::endl;
std::vector<int> aidxtbl( 10 );
// use another namespace name to test a different solution
Solution3::sort_idxtbl( ai, ai+10, aidxtbl.begin() );
for( int i=0; i<10; ++i )
std::cout << "i=" << i
<< ", aidxtbl[i]=" << aidxtbl[i]
<< ", ai[aidxtbl[i]]=" << ai[aidxtbl[i]]
<< std::endl;
std::cout << "#################" << std::endl;
}

HashTable... error: static assertion failed: std::hash is not specialized for this type

I posted earlier today and was able to work out a lot of my errors. However, I still have one error that I cannot figure out for the life of me. I'm basically just trying to insert a Symbol object into a HashTable and I'm constantly getting this message back:
In file included from /opt/local/include/gcc47/c++/bits/basic_string.h:3032:0,
from /opt/local/include/gcc47/c++/string:54,
from /opt/local/include/gcc47/c++/bits/locale_classes.h:42,
from /opt/local/include/gcc47/c++/bits/ios_base.h:43,
from /opt/local/include/gcc47/c++/ios:43,
from /opt/local/include/gcc47/c++/ostream:40,
from /opt/local/include/gcc47/c++/iostream:40,
from Driver.cpp:1:
/opt/local/include/gcc47/c++/bits/functional_hash.h: In instantiation of 'struct std::hash<Symbol>':
SeparateChaining.h:143:33: required from 'size_t HashTable<HashedObj>::myhash(const HashedObj&) const [with HashedObj = Symbol; size_t = long unsigned int]'
SeparateChaining.h:56:51: required from 'bool HashTable<HashedObj>::insert(HashedObj&) [with HashedObj = Symbol]'
Driver.cpp:135:26: required from here
/opt/local/include/gcc47/c++/bits/functional_hash.h:60:7: error: static assertion failed: std::hash is not specialized for this type
More specifically though.... The error:
error: static assertion failed: std::hash is not specialized for this type
Here is my Driver.cpp file:
#include <iostream>
#include <iomanip>
#include <cassert>
#include <fstream>
#include <string>
#include <vector>
#include <time.h>
#include <unistd.h>
#include <map>
#include <cstdlib>
#include <cmath>
#include "SeparateChaining.h"
using namespace std;
int TABLE_SIZE; //I know it's a global, but it allows the Table Size to be taken in within main() and used in hash()
size_t hash(const string & key);
class Symbol
{
private:
int key;
int type;
string data;
public:
const string & getData() const
{
return data;
}
int getType()
{
return type;
}
int getKey()
{
return labs(key);
}
void setType(int Type)
{
type = Type;
}
void setData(string Data)
{
data = Data;
}
void setKey(int Key)
{
key = Key;
}
bool operator== (const Symbol & rhs) const
{
return getData() == rhs.getData();
}
bool operator!= (const Symbol & rhs) const
{
return !(*this == rhs);
}
};
int main()
{
HashTable<Symbol> hashtable(TABLE_SIZE);
Symbol temp;
vector<Symbol> symbols;
string s;
int t;
int hash_key_array[TABLE_SIZE]; //array to hold hash key values
ifstream file;
file.open("symbols.txt");
if(!file)
{
cout << "System failed to open file.";
}
else
{
cout << "File successfully opened" << endl;
}
//for loop to read in the string name and the integer that follows the string name from symbols.txt
while(file >> s)
{
temp.setData(s);
file >> t;
temp.setType(t);
symbols.push_back(temp);
}
for(int i = 0; i < symbols.size(); i++)
{
cout << symbols[i].getData() << "\n";
cout << symbols[i].getType() << "\n";
}
cout << "What would you like the table size to be?" << endl;
cout << "Note: If the table size is greater than the number of objects" <<
" in the symbols.txt file, it will inevitably throw a segmentation fault" << endl;
cin >> TABLE_SIZE;
for(int j = 0; j < TABLE_SIZE; j++)
{
temp.setData(symbols[j].getData());
cout << temp.getData() << endl;
temp.setType(symbols[j].getType());
cout << temp.getType() << endl;
temp.setKey(::hash(symbols[j].getData()));
cout << "The key is: " << temp.getKey() << endl;
cout << endl;
hash_key_array[j] = temp.getKey();
for (int i = 0; i < TABLE_SIZE; i++)
{
if (i != j)
{
if (hash_key_array[i] == hash_key_array[j])
{
cout << endl;
cout << "Collision occurred at " << hash_key_array[i] << endl;
//rehash();
//cout << "The new key is: " << temp.getKey() << endl;
break;
}
}
}
hashtable.insert(temp);
}
}
size_t hash(const string & key)
{
size_t hashVal = 0;
for(char ch : key)
{
hashVal = 37 * hashVal + ch;
}
return labs(hashVal);
}
And my Header File.... SeperateChaining.h:
#ifndef SEPARATE_CHAINING_H
#define SEPARATE_CHAINING_H
#include <vector>
#include <list>
#include <string>
#include <algorithm>
#include <functional>
//#include "Hash.h"
using namespace std;
// SeparateChaining Hash table class
//
// CONSTRUCTION: an approximate initial size or default of 101
//
// ******************PUBLIC OPERATIONS*********************
// bool insert( x ) --> Insert x
// bool remove( x ) --> Remove x
// bool contains( x ) --> Return true if x is present
// void makeEmpty( ) --> Remove all items
int nextPrime( int n );
bool isPrime( int n );
template <typename HashedObj>
class HashTable
{
public:
//Uses the whatever value table_size has
//Otherwise, it will make a hash table of size 101
explicit HashTable( int TABLE_SIZE )
{
currentSize = 0;
theLists.resize(TABLE_SIZE);
}
bool contains( const HashedObj & x ) const
{
//represents the correct list in the hash table vector to start looking through
auto & whichList = theLists[ myhash( x ) ];
//returns whatever you wanted to search for in the table provided it is there
return find( begin( whichList ), end( whichList ), x ) != end( whichList );
}
void makeEmpty( )
{
for( auto & thisList : theLists )
thisList.clear( );
}
bool insert(HashedObj & temp )
{
//represents the correct list in the hash table vector to start looking through
auto & whichList = theLists[myhash( temp )];
//goes through the beginning and end of the list, and if it
//doesn't get to the end, then it found the object you wanted to insert in the hash table already
//prevents duplicate insertions
if( find( begin( whichList ), end( whichList ), temp ) != end( whichList) )
return false;
//otherwise, it has gotten to the end of the list without finding a duplicate
//and puts what you want to insert in the list
whichList.push_back( temp );
// Rehash; see Section 5.5
if( ++currentSize > theLists.size( ) )
rehash( );
return true;
}
bool insert(const HashedObj && x )
{
auto & whichList = theLists[ myhash( x ) ];
if( find( begin( whichList ), end( whichList ), x ) != end( whichList ) )
return false;
whichList.push_back( std::move( x ) );
// Rehash; see Section 5.5
if( ++currentSize > theLists.size( ) )
rehash( );
return true;
}
bool remove( const HashedObj & x )
{
//represents the correct list in the hash table vector to start looking through
auto & whichList = theLists[ myhash( x ) ];
//trying to find x within the list
//the iterator points to the slot in the list that contains x
auto itr = find( begin( whichList ), end( whichList ), x );
//if it gets to the end of the list without finding what you want to remove, then it returns false
if( itr == end( whichList ) )
{
return false;
}
//if it finds x, it removes it from the list
whichList.erase( itr );
--currentSize;
return true;
}
/*
void printTable()
{
for(int i=0; i < symbols.size(); i++)
{
cout << "The hash table contains: " << symbols[i] << endl;
}
}
*/
private:
vector<list<HashedObj>> theLists; // The array of Lists
int currentSize;
void rehash( )
{
vector<list<HashedObj>> oldLists = theLists;
// Creates new double-sized, empty table
theLists.resize( nextPrime( 2 * theLists.size( ) ) );
for( auto & thisList : theLists )
thisList.clear( );
// Copies the old table into the new table
currentSize = 0;
for( auto & thisList : oldLists )
for( auto & x : thisList )
insert( std::move( x ) );
}
size_t myhash( const HashedObj & x ) const
{
static hash<HashedObj> hf;
return hf( x ) % theLists.size( );
}
};
int nextPrime( int n )
{
if( n % 2 == 0 )
{
++n;
}
for( ; !isPrime( n ); n += 2 )
{
}
return n;
}
bool isPrime( int n )
{
if( n == 2 || n == 3 )
return true;
if( n == 1 || n % 2 == 0 )
return false;
for( int i = 3; i * i <= n; i += 2 )
if( n % i == 0 )
return false;
return true;
}
#endif
I would really appreciate you guys helping me out!
You are doing this:
static hash<HashedObj> hf;
but you have not provided a hash template, or have not specialized std::hash for HashedObj.
You should avoid using namespace std;. Amongst other things, it is difficult to figure out which hash you want to get.

std::Threads of non-void functions ( C++11 )

How can i get the return of the functions sent to the std::threads?
I'm working ina function that apllies a filter, created to 2d Images, in each channel of an color/multispectral image. But many of the functions previously implemented in this library have an image as return, i tried to create a function that takes the return image as a parameter, but it didn't work. Here's a copy of the code:
template< class D, class A >
template < typename... Args>
void Image < D, A >::VoidFunction( Image< D, A > &out, Image < D, A > function ( const Image< D, A >& , Args ... ),
const Image <D, A > &in, Args... args ) {
out = ( function ) ( in, args... );
return ;
}
template< class D, class A >
template < typename... Args>
Image < D, A > Image < D, A >::multiSpecImgFilter( Image < D, A > function ( const Image<D, A>& , Args ... ),
const Image <D, A > &img, Args... args ) {
if ( img.Dims() != 3 ) {
std::string msg( std::string( __FILE__ ) + ": " + std::to_string( __LINE__ ) + ": Image<D,A> " + "::" +
std::string( __FUNCTION__ ) + ": error: Image channels must have 2 dimensions" );
throw( std::logic_error( msg ) );
}
std::vector< Image < D, A > > channel = img.Split( );
// std::vector< std::thread > threads ;
// for( size_t thd = 0; thd < channel.size(); ++thd )
// threads[ thd ].join( );
try {
for ( int ch = 0; ch < channel.size() ; ch++ )
std::thread thd ( &VoidFunction, channel[ch], function, channel[ch], args... );
}
catch( ... ) {
for ( int ch = 0; ch < img.size(2) ; ch++ )
channel[ ch ] = ( function ) ( channel [ ch ], args... );
}
return ( Image< D, A >::Merge( channel, img.PixelSize().back(), img.Channel().back() ) );
}
You can use a lambda and store the result in it.
#include <iostream>
#include <thread>
int threadFunction()
{
return 8;
}
int main()
{
int retCode;
//retCode is captured by ref to be sure the modifs are also in the main thread
std::thread t([&retCode](){
std::cout << "thread function\n";
retCode=threadFunction();
});
std::cout << "main thread\n";//this will display 8
t.join();//to avoid a crash
return 0;
}
or pass by std::ref. This is an example from :
https://www.acodersjourney.com/c11-multithreading-tutorial-via-faq-thread-management-basics/
#include <string>
#include <thread>
#include <iostream>
#include <functional>
using namespace std;
void ChangeCurrentMissileTarget(string& targetCity)
{
targetCity = "Metropolis";
cout << " Changing The Target City To " << targetCity << endl;
}
int main()
{
string targetCity = "Star City";
thread t1(ChangeCurrentMissileTarget, std::ref(targetCity));
t1.join();
cout << "Current Target City is " << targetCity << endl;
return 0;
}
The canonical way of doing this, I suppose, is to use async.
#include <functional>
#include <future>
#include <iostream>
int main()
{
auto result = std::async(std::launch::async, std::plus<>{}, 42, 42);
std::cout << result.get() << "\n"; // outputs 84
}
(live demo)
I'd say this looks better than using an output parameter.
You can also directly use a packaged_task:
#include <functional>
#include <future>
#include <iostream>
int main()
{
std::packaged_task<int(int, int)> task{std::plus<>{}};
auto result = task.get_future();
std::thread t{std::move(task), 42, 42};
std::cout << result.get() << "\n"; // outputs 84
t.join();
}
(live demo)