vector<int> l;
for(int i=0;i<10;i++){
l.push_back(i);
}
I want the vector to only be able to store numbers from a specified range (or set).
How can that be done, in general?
In particular, I want to restrict the vector to beonly be able to store single digits.
So, if I do a l[9]++ (in this case l[9] is 9), it should give me an error or warn me. (because 10 is not a single digit number). Similarly, l[0]-- should warn me.
Is there a way to do this using C++ STL vector?
An alternative solution would be to create your own datatype that provides this restrictions. As i read your question I think the restrictions do not really belong to the container itself but to the datatype you want to store. An example (start of) such an implementation can be as follows, possibly such a datatype is already provided in an existing library.
class Digit
{
private:
unsigned int d;
public:
Digit() : d(0) {}
Digit(unsigned int d)
{
if(d > 10) throw std::overflow_error();
else this->d=d;
}
Digit& operator++() { if(d<9) d++; return *this; }
...
};
Wrap it with another class:
class RestrictedVector{
private:
std::vector<int> things;
public:
// Other things
bool push_back(int data){
if(data >= 0 && data < 10){
things.push_back(data);
return true;
}
return false
}
}
Related
Our teacher told us to create a vector of objects and perform operations on it, but I couldn't understand how to properly do that: I tried to make a simple project with minimum data so that I could know what I was doing.
I have this class
class Obj {
private:
int num;
public:
Obj();
void setNum(int nuovo_num);
int getNum();
};
And then this one, with a vector of Obj
class VettObj{
private:
vector<Obj> vett;
public:
VettObj();
void setVett();
void stampaVett();
};
My initial thought was to use an iterator but I was just making a total mess and, with almost useless research, I decided to use a common integer counter.
I found that I shouldn't write anything in the VettObj costructor, as it automatically initialize stuff, so I left it blank.
The method that adds elements is this
void VettObj::setVett(){
Obj temp;
int i;
i = 0;
while(i < 5){
temp.setNum(10);
vett.push_back(temp);
i++;
}
}
And the one that prints elements
void VettObj::stampaVett(){
int i;
i = 0;
while(i < 5){
vett[i].getNum();
i++;
}
}
When I compile, everything goes well, but when I run the program I get nothing on the screen. I don't want to use mostly vector functions(if not necessary) as I saw that a lot of people can do it like this. I would really like to know how to do it with iterators too. Help pls ????
You are not actually printing anything in the stampaVett() method.
You could try with:
void VettObj::stampaVett(){
int i = 0;
while (i < 5){
std::cout << vett[i].getNum();
i++;
}
}
I'd also suggest using English for method or variable instead of Italian, since SO is an international community.
I have a structure that contains x amount of integers, It is required that every last one of them be non-zero. Here's my structure:
struct thingy_t{
int a, b, c /* and so on */;
bool init();
};
Over time I will be adding many other members to the structure, which makes it an issue if I forget to check if it's non-zero. That's why I wanted to automate it for every member.
In my init function, it attempts to get values for the members, and return false if any of them are 0.
So far I have this:
bool thingy_t::init(){
a = GetValue(/* blah blah */); // Will return 0 if it can't find anything
b = GetValue(/* other blah */);
/* and so on */
// Check if any value is zero
for(int* i = (int*)this
; i < (int*)((char*)this + sizeof(interfaces_t))
; i++){
if(!*i) return false;
}
return true;
}
I am looking for a better way of doing this that would be more readable and more memory safe, as I am playing with fire(pointers) in a way they probably aren't intended.
Also, sorry for the for loop, I tried to make it more readable by wrapping it, but I probably made it worse.
There isn't a natural way to iterate over the struct and check for certain values of the members you have, so the better option for you, in my opinion, should be either make a better design for your task or make sure that you check for incorrect values on each access to that struct.
I'd simple implement the type to contain an array of int or (possibly better) a standard container.
If the number of values is specified at compile time ....
struct thingy_t
{
int x[number];
bool all_non_zero() const;
};
bool thingy_t::all_non_zero() const
{
for (int i = 0; i < number; ++i)
if (!number[i]) return false;
return true;
}
If the number is not specified at compile time, I'd use a standard container
struct thingy_t
{
std::vector<int> x;
thingy_t(std::size_t size) : x(size) {};
bool all_non_zero() const;
};
bool thingy_t::all_non_zero() const
{
for (std::vector<int>::const_iterator it = x.begin(), end = x.end();
it != end number; ++it)
if (!(*it)) return false;
return true;
}
The above works for all versions of C++, but may be simplified in C++11 or later.
bool thingy_t::all_non_zero() const
{
for (const auto &element : x)
if (!element) return false;
return true;
}
Naturally, you will need other functions to actually store values in the array or vector.
The code won't change if the number of integers changes. You will need to somehow track separately the meaning of each element.
I solved my own question while enjoying a nice breakfast.
Here's how I solved it:
struct thingy_t{
union{
struct{
int a, b, c;
}
int arr[3];
}
}
That way I can access variables via. their name and also their index in an array so I can check if each value is non-zero easier (creds: James Root for the array inspiration)
i want to implement a container, which contains maximal 20 Solutions.
If the container contains 20 Solutions any Solution that is added is only accepted if its
1) new_value < worst value in the Container
2) if new_value is already in the container (and 1) holds) then memcmp(new_assignment, assigment, assignment_size) != 0
Then the worst solutions is deleted. (Including the int array)
the assignment_size is for all Solutions the same.
struct Solution {
double value;
int *assignment;
int assigment_size;
};
What is the easiest way to implement this structure? Can you use some container of the STL?
Ok Thank you.
I hope it is correct. It tried to keep the list trough insert sorted so it is easier to check and then you can remove the last element.
struct Solution {
double power_peak;
int *assignment;
int size;
~Solution() { delete[] assignment; }
};
class Container {
list<Solution> Solutions;
uint max_size;
double worst_solution;
public:
Container (uint size)
{
max_size = size;
}
void addSolution(Solution s)
{
list<Solution>::iterator insert_position = Solutions.begin();
while (insert_position != Solutions.end() && (*insert_position).power_peak < s.power_peak)
{
if ((*insert_position).power_peak == s.power_peak && memcmp((*insert_position).assignment, s.assignment, s.size) == 0)
{
return;
}
++insert_position;
}
Solutions.insert(insert_position, s);
if (Solutions.size() > max_size)
{
Solutions.pop_back();
}
worst_solution = (*(--(Solutions.end())))->power_peak;
}
double getWorst()
{
return worst_solution;
}
};
Note: I assumed that your solution is described by the Solution structure you posted.
The easiest solution would be a std::array<Solution, 20>, wrapped in a custom container wrapper.
You should have something like this:
class SolutionsSequence
{
public:
// in a function to add a solution to the sequence, you should
// implement the criteria to decide which solution is worse
private:
std::array<Solution, 20> solutions_;
};
Other than that, you should not use memcpy in C++. Consider using std::copy, or std::copy_n instead.
Also consider using a std::vector for assignments, and then you can get rid of the assignment_size.
A little hard to phrase in a question so I will use an example. Lets say I do:
generate(myvec.begin(), myvec.end(), func())
Can I have it so that func() can read the index that generate is up to such that:
int func()
{
if(index<2)
return 1;
else
return 2;
}
such that myvec[0]=1, myvec[1]=1, myvec[2]=2, myvec[3]=2,..., myvec[N]=2?
The short answer is "no, not directly". It can create its own variable that should track with the index, but (in a case like this) there's simply no access to the index itself.
Under the circumstances, I'd almost certainly just use std::fill twice:
std::fill_n(myVec.begin(), 2, 1);
std::fill(myVec.begin()+2, myVec.end(), 2);
Shorter, and simpler.
Yes, if you use a function object as the generator (as juan points out, it is questionable whether this solution is guaranteed to work by the standard! Exercise caution and use Jerry's method.):
class mygenerator {
public:
mygenerator() : hits(0) {}
int operator()() {
hits++;
return (hits <= 2 ? 1 : 2);
}
private:
int hits;
}
...
mygenerator mg1;
std::generate(myvec.begin(), myvec.end(), mg1);
class funkygen
{
int index;
public:
funkygen()
: index(0)
{ }
int operator()()
{
if(t < 2)
t++;
return t;
}
};
/* other code */
funkygen f;
std::generate(myvec.begin(), myvec.end(), f);
As juanchopanza pointed out in a comment on another answer, the elements of vec are not guaranteed to be accessed in a particular sequential order. The only guarantee is that every item will be accessed exactly once.
This is my first time using this site so sorry for any bad formatting or weird formulations, I'll try my best to conform to the rules on this site but I might do some misstakes in the beginning.
I'm right now working on an implementation of some different bin packing algorithms in C++ using the STL containers. In the current code I still have some logical faults that needs to be fixed but this question is more about the structure of the program. I would wan't some second opinion on how you should structure the program to minimize the number of logical faults and make it as easy to read as possible. In it's current state I just feel that this isn't the best way to do it but I don't really see any other way to write my code right now.
The problem is a dynamic online bin packing problem. It is dynamic in the sense that items have an arbitrary time before they will leave the bin they've been assigned to.
In short my questions are:
How would the structure of a Bin packing algorithm look in C++?
Is STL containers a good tool to make the implementation be able to handle inputs of arbitrary lenght?
How should I handle the containers in a good, easy to read and implement way?
Some thoughts about my own code:
Using classes to make a good distinction between handling the list of the different bins and the list of items in those bins.
Getting the implementation as effective as possible.
Being easy to run with a lot of different data lengths and files for benchmarking.
#include <iostream>
#include <fstream>
#include <list>
#include <queue>
#include <string>
#include <vector>
using namespace std;
struct type_item {
int size;
int life;
bool operator < (const type_item& input)
{
return size < input.size;
}
};
class Class_bin {
double load;
list<type_item> contents;
list<type_item>::iterator i;
public:
Class_bin ();
bool operator < (Class_bin);
bool full (type_item);
void push_bin (type_item);
double check_load ();
void check_dead ();
void print_bin ();
};
Class_bin::Class_bin () {
load=0.0;
}
bool Class_bin::operator < (Class_bin input){
return load < input.load;
}
bool Class_bin::full (type_item input) {
if (load+(1.0/(double) input.size)>1) {
return false;
}
else {
return true;
}
}
void Class_bin::push_bin (type_item input) {
int sum=0;
contents.push_back(input);
for (i=contents.begin(); i!=contents.end(); ++i) {
sum+=i->size;
}
load+=1.0/(double) sum;
}
double Class_bin::check_load () {
return load;
}
void Class_bin::check_dead () {
for (i=contents.begin(); i!=contents.end(); ++i) {
i->life--;
if (i->life==0) {
contents.erase(i);
}
}
}
void Class_bin::print_bin () {
for (i=contents.begin (); i!=contents.end (); ++i) {
cout << i->size << " ";
}
}
class Class_list_of_bins {
list<Class_bin> list_of_bins;
list<Class_bin>::iterator i;
public:
void push_list (type_item);
void sort_list ();
void check_dead ();
void print_list ();
private:
Class_bin new_bin (type_item);
bool comparator (type_item, type_item);
};
Class_bin Class_list_of_bins::new_bin (type_item input) {
Class_bin temp;
temp.push_bin (input);
return temp;
}
void Class_list_of_bins::push_list (type_item input) {
if (list_of_bins.empty ()) {
list_of_bins.push_front (new_bin(input));
return;
}
for (i=list_of_bins.begin (); i!=list_of_bins.end (); ++i) {
if (!i->full (input)) {
i->push_bin (input);
return;
}
}
list_of_bins.push_front (new_bin(input));
}
void Class_list_of_bins::sort_list () {
list_of_bins.sort();
}
void Class_list_of_bins::check_dead () {
for (i=list_of_bins.begin (); i !=list_of_bins.end (); ++i) {
i->check_dead ();
}
}
void Class_list_of_bins::print_list () {
for (i=list_of_bins.begin (); i!=list_of_bins.end (); ++i) {
i->print_bin ();
cout << "\n";
}
}
int main () {
int i, number_of_items;
type_item buffer;
Class_list_of_bins bins;
queue<type_item> input;
string filename;
fstream file;
cout << "Input file name: ";
cin >> filename;
cout << endl;
file.open (filename.c_str(), ios::in);
file >> number_of_items;
for (i=0; i<number_of_items; ++i) {
file >> buffer.size;
file >> buffer.life;
input.push (buffer);
}
file.close ();
while (!input.empty ()) {
buffer=input.front ();
input.pop ();
bins.push_list (buffer);
}
bins.print_list ();
return 0;
}
Note that this is just a snapshot of my code and is not yet running properly
Don't wan't to clutter this with unrelated chatter just want to thank the people who contributed, I will review my code and hopefully be able to structure my programming a bit better
How would the structure of a Bin packing algorithm look in C++?
Well, ideally you would have several bin-packing algorithms, separated into different functions, which differ only by the logic of the algorithm. That algorithm should be largely independent from the representation of your data, so you can change your algorithm with only a single function call.
You can look at what the STL Algorithms have in common. Mainly, they operate on iterators instead of containers, but as I detail below, I wouldn't suggest this for you initially. You should get a feel for what algorithms are available and leverage them in your implementation.
Is STL containers a good tool to make the implementation be able to handle inputs of arbitrary length?
It usually works like this: create a container, fill the container, apply an algorithm to the container.
Judging from the description of your requirements, that is how you'll use this, so I think it'll be fine. There's one important difference between your bin packing algorithm and most STL algorithms.
The STL algorithms are either non-modifying or are inserting elements to a destination. bin-packing, on the other hand, is "here's a list of bins, use them or add a new bin". It's not impossible to do this with iterators, but probably not worth the effort. I'd start by operating on the container, get a working program, back it up, then see if you can make it work for only iterators.
How should I handle the containers in a good, easy to read and implement way?
I'd take this approach, characterize your inputs and outputs:
Input: Collection of items, arbitrary length, arbitrary order.
Output: Collection of bins determined by algorithm. Each bin contains a collection of items.
Then I'd worry about "what does my algorithm need to do?"
Constantly check bins for "does this item fit?"
Your Class_bin is a good encapsulation of what is needed.
Avoid cluttering your code with unrelated stuff like "print()" - use non-member help functions.
type_item
struct type_item {
int size;
int life;
bool operator < (const type_item& input)
{
return size < input.size;
}
};
It's unclear what life (or death) is used for. I can't imagine that concept being relevant to implementing a bin-packing algorithm. Maybe it should be left out?
This is personal preference, but I don't like giving operator< to my objects. Objects are usually non-trivial and have many meanings of less-than. For example, one algorithm might want all the alive items sorted before the dead items. I typically wrap that in another struct for clarity:
struct type_item {
int size;
int life;
struct SizeIsLess {
// Note this becomes a function object, which makes it easy to use with
// STL algorithms.
bool operator() (const type_item& lhs, const type_item& rhs)
{
return lhs.size < rhs.size;
}
}
};
vector<type_item> items;
std::sort(items.begin, items.end(), type_item::SizeIsLess);
Class_bin
class Class_bin {
double load;
list<type_item> contents;
list<type_item>::iterator i;
public:
Class_bin ();
bool operator < (Class_bin);
bool full (type_item);
void push_bin (type_item);
double check_load ();
void check_dead ();
void print_bin ();
};
I would skip the Class_ prefix on all your types - it's just a bit excessive, and it should be clear from the code. (This is a variant of hungarian notation. Programmers tend to be hostile towards it.)
You should not have a class member i (the iterator). It's not part of class state. If you need it in all the members, that's ok, just redeclare it there. If it's too long to type, use a typedef.
It's difficult to quantify "bin1 is less than bin2", so I'd suggest removing the operator<.
bool full(type_item) is a little misleading. I'd probably use bool can_hold(type_item). To me, bool full() would return true if there is zero space remaining.
check_load() would seem more clearly named load().
Again, it's unclear what check_dead() is supposed to accomplish.
I think you can remove print_bin and write that as a non-member function, to keep your objects cleaner.
Some people on StackOverflow would shoot me, but I'd consider just making this a struct, and leaving load and item list public. It doesn't seem like you care much about encapsulation here (you're only need to create this object so you don't need do recalculate load each time).
Class_list_of_bins
class Class_list_of_bins {
list<Class_bin> list_of_bins;
list<Class_bin>::iterator i;
public:
void push_list (type_item);
void sort_list ();
void check_dead ();
void print_list ();
private:
Class_bin new_bin (type_item);
bool comparator (type_item, type_item);
};
I think you can do without this class entirely.
Conceptually, it represents a container, so just use an STL container. You can implement the methods as non-member functions. Note that sort_list can be replaced with std::sort.
comparator is too generic a name, it gives no indication of what it compares or why, so consider being more clear.
Overall Comments
Overall, I think the classes you've picked adequately model the space you're trying to represent, so you'll be fine.
I might structure my project like this:
struct bin {
double load; // sum of item sizes.
std::list<type_item> items;
bin() : load(0) { }
};
// Returns true if the bin can fit the item passed to the constructor.
struct bin_can_fit {
bin_can_fit(type_item &item) : item_(item) { }
bool operator()(const bin &b) {
return item_.size < b.free_space;
}
private:
type_item item_;
};
// ItemIter is an iterator over the items.
// BinOutputIter is an output iterator we can use to put bins.
template <ItemIter, BinOutputIter>
void bin_pack_first_fit(ItemIter curr, ItemIter end, BinOutputIter output_bins) {
std::vector<bin> bins; // Create a local bin container, to simplify life.
for (; curr != end; ++curr) {
// Use a helper predicate to check whether the bin can fit this item.
// This is untested, but just for an idea.
std::vector<bin>::iterator bin_it =
std::find_if(bins.begin(), bins.end(), bin_can_fit(*curr));
if (bin_it == bins.end()) {
// Did not find a bin with enough space, add a new bin.
bins.push_back(bin);
// push_back invalidates iterators, so reassign bin_it to the last item.
bin_it = std::advance(bins.begin(), bins.size() - 1);
}
// bin_it now points to the bin to put the item in.
bin_it->items.push_back(*curr);
bin_it->load += curr.size();
}
std::copy(bins.begin(), bins.end(), output_bins); // Apply our bins to the destination.
}
void main(int argc, char** argv) {
std::vector<type_item> items;
// ... fill items
std::vector<bin> bins;
bin_pack_first_fit(items.begin(), items.end(), std::back_inserter(bins));
}
Some thoughts:
Your names are kinda messed up in places.
You have a lot of parameters named input, thats just meaningless
I'd expect full() to check whether it is full, not whether it can fit something else
I don't think push_bin pushes a bin
check_dead modifies the object (I'd expect something named check_*, to just tell me something about the object)
Don't put things like Class and type in the names of classes and types.
class_list_of_bins seems to describe what's inside rather then what the object is.
push_list doesn't push a list
Don't append stuff like _list to every method in a list class, if its a list object, we already know its a list method
I'm confused given the parameters of life and load as to what you are doing. The bin packing problem I'm familiar with just has sizes. I'm guessing that overtime some of the objects are taken out of bins and thus go away?
Some further thoughts on your classes
Class_list_of_bins is exposing too much of itself to the outside world. Why would the outside world want to check_dead or sort_list? That's nobodies business but the object itself. The public method you should have on that class really should be something like
* Add an item to the collection of bins
* Print solution
* Step one timestep into the future
list<Class_bin>::iterator i;
Bad, bad, bad! Don't put member variables on your unless they are actually member states. You should define that iterator where it is used. If you want to save some typing add this: typedef list::iterator bin_iterator and then you use bin_iterator as the type instead.
EXPANDED ANSWER
Here is my psuedocode:
class Item
{
Item(Istream & input)
{
read input description of item
}
double size_needed() { return actual size required (out of 1) for this item)
bool alive() { return true if object is still alive}
void do_timestep() { decrement life }
void print() { print something }
}
class Bin
{
vector of Items
double remaining_space
bool can_add(Item item) { return true if we have enough space}
void add(Item item) {add item to vector of items, update remaining space}
void do_timestep() {call do_timestep() and all Items, remove all items which indicate they are dead, updating remaining_space as you go}
void print { print all the contents }
}
class BinCollection
{
void do_timestep { call do_timestep on all of the bins }
void add(item item) { find first bin for which can_add return true, then add it, create a new bin if neccessary }
void print() { print all the bins }
}
Some quick notes:
In your code, you converted the int size to a float repeatedly, that's not a good idea. In my design that is localized to one place
You'll note that the logic relating to a single item is now contained inside the item itself. Other objects only can see whats important to them, size_required and whether the object is still alive
I've not included anything about sorting stuff because I'm not clear what that is for in a first-fit algorithm.
This interview gives some great insight into the rationale behind the STL. This may give you some inspiration on how to implement your algorithms the STL-way.