The problem lies within the block:
check_sort(l.begin(), l.end(), "list");
time_insert(insert_list, data);
check_sort(s.begin(), s.end(), "set");
time_insert(insert_set, data);
check_sort(v.begin(), v.end(), "vector");
time_insert(insert_vector, data);
The error states that the variables are not declared in the scope, but shouldn't l,s,v be universal variables here? What am I doing wrong.
#include <cmath>
#include <iterator>
#include <iostream>
#include <iomanip>
#include <vector>
#include <ctime>
#include <list>
#include <set>
#include <algorithm>
#include <cstdlib>
using namespace std;
typedef void Inserter(vector<double>);
vector<double> gen_data(int num_elts);
void insert_list(vector<double> data);
void insert_set(vector<double> data);
void insert_vector(vector<double> data);
void time_insert( Inserter inserter, vector<double> data);
template <class Iter> bool is_sorted(Iter first, Iter last);
template <class Iter> void check_sort(Iter first, Iter last, string cont_kind);
int main() {
srand(time(0));// initialize random number generator
cout << "How many elements for container? ";
int num_elts = 0;
while (cin >> num_elts) {
if (num_elts <= 0)
cout << "Error, should be > 1";
else {
vector<double> data = gen_data(num_elts);
check_sort(l.begin(), l.end(), "list");
time_insert(insert_list, data);
check_sort(s.begin(), s.end(), "set");
time_insert(insert_set, data);
check_sort(v.begin(), v.end(), "vector");
time_insert(insert_vector, data);
}
cout << "\nHow many elements for next container? ";
}
return 0;
}
void time_insert( Inserter inserter, vector<double> data) {
clock_t t1 = clock();
if (t1 == clock_t(-1)) { //if clock() doesn’t work
cerr << "sorry, no clock\n";
exit(1);
}
inserter(data);
clock_t t2 = clock();
if (t2 == clock_t(-1)) {
cerr << "sorry, clock overflow\n";
exit(2);
}
cout << "Elapsed time: " << fixed << setprecision(2)
<< double(t2-t1)/CLOCKS_PER_SEC << " seconds\n";
}
class Larger_than {
double v;
public:
Larger_than(double vv) : v(vv){}
bool operator()(double x) const {return x>v;}
};
// Sorts and then inserts data into a list
void insert_list(vector<double> data)
{
list<double> l;
for(int i=0; i < data.size(); i++){
list<double>::iterator p = find_if(l.begin(),l.end(), Larger_than(data[i]));
l.insert(p, data[i]);
}
}
// Sorts and then inserts data into a list
void insert_set(vector<double> data)
{
set<double> s;
for(int i=0; i < data.size(); i++){
set<double>::iterator p = find_if(s.begin(),s.end(), Larger_than(data[i]
));
s.insert(p, data[i]);
}
}
// Sorts and then inserts data into a list
void insert_vector(vector<double> data)
{
vector<double> v;
for(int i=0; i < data.size(); i++){
vector<double>::iterator p = find_if(v.begin(),v.end(), Larger_than(data
[i]));
v.insert(p, data[i]);
}
}
// generate num_elts random numbers in the range [0.0, 1.0),
// which are returned in a vector
vector<double> gen_data (int num_elts)
{
vector<double> result;
for (int i = 0; i < num_elts; i++) {
double datum = 1.0*rand()/RAND_MAX;
result.push_back(datum);
}
return result;
}
// is container spanned by [from, last) sorted?
template <class Iter> bool is_sorted(Iter first, Iter last)
{
Iter next = first; // next element
for (next++; next != last; next++, first++) {
if (*first > *next)
return false;
}
return true;
}
// prints a msg describing container kind, as well as whether container
// spanned by [from, last) is sorted
template <class Iter> void check_sort(Iter first, Iter last, string cont_kind)
{
cout << "Check: " << cont_kind << " is ";
if (!is_sorted(first, last)) cout << "not ";
cout << "sorted\n";
}
How should main know about s, l and v at all? They're local variables of completely unrelated functions (the insert_xxx ones), there's no way main could know about them. If you want to make them globally accessible, just make them global variables, i.e., put their definition before main:
// ...
list<double> l;
set<double> s;
vector<double> v;
int main(){
// ....
}
// ...
It looks like l is defined in the 'insert_list' function and would not available in main. Only variables defined insider your function are available.
You don't appear to have declared the variables at all. Why do you think they should exist in main? There are no globals or locals with those names anywhere that I can see. Try declaring them before using them.
Related
I want to write a program which reads names in a vector. After that it should read ages into another vector. (that's done)
The first element of the name-vector should be connected to the first element of the age-vector, so if I use any kind of sort() function on the name-vector the age-vector gets sorted as well.
Is there any way to realize this in an easy way?
class Name_pairs {
public:
//member functions
int read_names();
int read_ages();
int print();
private:
vector<double> age;
vector<string> name;
};
int Name_pairs::read_names() {
cout << "Please enter different names, you want to store in a vector:\n";
for (string names; cin >> names;) {
name.push_back(names);
}
cin.clear();
cout << "You entered following names:\n\t";
for (int i = 0; i < name.size(); i++) {
cout << name[i] << " \n\t";
}
return 0;
}
int Name_pairs::read_ages() {
cout << "\nPlease enter an age for every name in the vector.\n";
for (double ages; cin >> ages;) {
age.push_back(ages);
}
return 0;
}
I think you need a std::vector of a coupled type.
struct Name_pair {
double age;
string name;
};
Than you can use std::vector<Name_pair> and use a lambda
auto comparator = [](const Name_pair& first, const Name_pair& second){return first.age <second.age;};
to sort your vector with std::sort.
Name_pairs = std::vector<Name_pair>;
// fill vector
std::sort(Name_pairs.begin(), Name_pairs.end(), comparator);
Here is a working example.
#include <vector>
#include <algorithm>
#include <string>
#include <iostream>
struct Name_pair {
double age;
std::string name;
};
int main() {
std::vector<Name_pair> Name_pairs{{13, "Hallo"}, {32, "Welt"}, {1, "Georg"}};
auto comparator = [](const Name_pair& first, const Name_pair& second) { return first.age < second.age; };
std::sort(Name_pairs.begin(), Name_pairs.end(), comparator);
for (const auto np : Name_pairs) {
std::cout << np.name << "\n";
}
}
It prints
Georg
Hallo
Welt
If you want to implement a data-oriented design by using separate vectors instead of a single vector of classes, you could use a vector of indeces and sort it.
The following is just an example:
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
class Customers
{
std::vector<double> ages_;
std::vector<std::string> names_;
template <typename Comparator>
auto make_indeces(Comparator &&comp)
{
std::vector<size_t> indeces(names_.size());
std::iota(indeces.begin(), indeces.end(), 0);
std::sort(indeces.begin(), indeces.end(), comp);
return indeces;
}
template <typename Type>
void reorder_vector(std::vector<Type> &src, std::vector<size_t> const &indeces)
{
std::vector<Type> tmp;
tmp.reserve(src.size());
std::generate_n(
std::back_inserter(tmp), src.size(),
[&src, idx = indeces.cbegin()] () mutable {
return src[*(idx++)];
});
src = std::move(tmp);
}
public:
void add(std::string const &name, double age)
{
names_.push_back(name);
ages_.push_back(age);
}
void sort_by_names()
{
auto indeces = make_indeces([this] (size_t i, size_t j) {
return names_[i] < names_[j];
});
reorder_vector(names_, indeces);
reorder_vector(ages_, indeces);
}
void show_sorted_by_ages()
{
auto indeces = make_indeces([this] (size_t i, size_t j) {
return ages_[i] < ages_[j];
});
for (auto i : indeces)
std::cout << names_[i] << ' ' << ages_[i] << '\n';
}
void show()
{
for (size_t i = 0; i < names_.size(); ++i)
std::cout << names_[i] << ' ' << ages_[i] << '\n';
}
};
int main(void)
{
Customers c;
c.add("Adam", 23);
c.add("Eve", 21);
c.add("Snake", 66.6);
c.add("Apple", 3.14);
std::cout << "Sorted by ages (doesn't modify the internal order):\n";
c.show_sorted_by_ages();
std::cout << "\nInternal order:\n";
c.show();
c.sort_by_names();
std::cout << "\nInternal order after sorting by names:\n";
c.show();
}
Testable HERE.
I have a question about iterators on lists. In function I have to compare the doubles, but I don't know how to get the elements from the second level, with only iterators to the first level.
void function (std::list<std::list <double>>::iterator *begin, std::list<std::list <double>>::iterator *end)
{
//do something
}
int main()
{
std::list <std::list <double>> a_list;
function (a_list.begin(), a_list.end());
}
void function (list<list <double> >::iterator begin, list<list <double> >::iterator end)
{
for(std::list<std::list <double> >::iterator it =begin;it!= end;it++)
{
for(std::list <double>:: iterator it_inner = (*it).begin(); it_inner != (*it).end();it_inner++)
{
printf("%f ",*it_inner );
}
printf("\n");
}
}
int main()
{
std::list <std::list <double> > a_list;
for(int i=0;i<=3;i++)
{
std::list <double> inner_list;
for(double j=0;j<=8;j+=2.2)
{
inner_list.push_back(j);
}
a_list.push_back(inner_list);
}
function (a_list.begin(), a_list.end());
}
You can pass the iterators as parameters or just the entire list, like this:
#include <iostream>
#include <list>
using namespace std;
void funcA (list<list<double>>::iterator begin, list<list<double>>::iterator end) {
//do something
list<double>::iterator sublist1 = begin->begin();
cout << *sublist1 + 1 << endl;
}
void funcB (list<list<double>> list) {
for (auto&& sublist: list) {
for (auto&& value: sublist) {
cout << value << ' ';
}
}
cout << endl;
}
int main() {
list <list<double>> a_list = {{1,2,3},{4,5,6}};
// list<list<double>>::iterator a = a_list.begin();
// list<double>::iterator b = a->begin();
//
// cout << *b + 2 << endl;
funcA(a_list.begin() , a_list.end());
funcB(a_list);
}
I've just started to code in C++, so i'm new to STL .
Here i'm trying to iterate over a graph stored as vector of vectors.
#include <iostream>
#include <vector>
#include <iostream>
using namespace std;
int reach(vector<vector<int> > &adj, int x, int y) {
vector<vector<int> >::iterator it;
vector<int>::iterator i;
for (it = adj.begin(); it != adj.end(); it++)
{
cout << (*it) << endl;
if ((*it) == x)
for (i = (*it).begin(); i != (*it).end(); i++)
{
cout << (*i) << endl;
if ((*i) == y)
return 1;
}
}
return 0;
}
int main()
{
}
I'm getting an error std::vector<int> is not derived from const gnu cxx. Can someone point me in the right direction ?
*it pointing to vector not int that is why you are getting error
following code may work for you
#include <vector>
#include <iostream>
using namespace std;
int reach(vector<vector<int> > &adj, int x, int y) {
vector<vector<int> >::iterator it;
vector<int>::iterator i;
for (it = adj.begin(); it != adj.end(); it++)
{
cout << (*(*it).begin()) << endl;
if (( (*(*it).begin())) == x)
for (i = (*it).begin(); i != (*it).end(); i++)
{
cout << (*i) << endl;
if ((*i) == y)
return 1;
}
}
return 0;
}
int main()
{
}
for accessing first element of the vector of the use
(*(*it).begin()) in place of (*it)
if you are studying graph then use array of vector. for more details please go through following url
C++ Depth First Search (DFS) Implementation
cout << (*it) << endl;
Here, you declared it as a:
vector<vector<int> >::iterator it;
Therefore, *it is a:
vector<int>
So you are attempting to use operator<< to send it to std::cout. This, obviously, will not work. This is equivalent to:
vector<int> v;
cout << v;
There is no operator<< overload that's defined for what cout is, and a vector<int>. As you know, in order to print the contents of a vector, you have to iterate over its individual values, and print its individual values.
So, whatever your intentions were, when you wrote:
cout << (*it) << endl;
you will need to do something else, keeping in mind that *it here is an entire vector<int>. Perhaps your intent is to iterate over the vector and print each int in the vector, but you're already doing it later.
Similarly:
if ((*it) == x)
This won't work either. As explained, *it is a vector<int>, which cannot be compared to a plain int.
It is not clear what your intentions are here. "Graph stored as a vector or vectors" is too vague.
The following code compiles with the option std=c++11. But x is missing in vector<vector<int>>. If adj had type vector<pair<int, vector<int>>> it would better match.
The following code compiles for vector<vector<int>> but it doesn't use x.
using std::vector;
using std::pair;
using std::cout;
using std::endl;
int reach(vector<vector<int> > &adj, int x, int y) {
vector<vector<int> >::iterator it;
vector<int>::iterator i;
for(it=adj.begin();it!=adj.end();it++)
{
// cout << (*it) << endl;
for (const auto& nexts: *it)
cout << nexts << ' ';
cout << endl;
for(i=(*it).begin();i!=(*it).end();i++)
{
cout << (*i) << endl;
if((*i)==y)
return 1;
}
}
return 0;
}
This code compiles with <vector<pair<int, vector<int>>> and uses x.
using std::vector;
using std::pair;
using std::cout;
using std::endl;
int reach(vector<pair<int, vector<int> > > &adj, int x, int y) {
vector<pair<int, vector<int> > >::iterator it;
vector<int>::iterator i;
for(it=adj.begin();it!=adj.end();it++)
{
cout << it->first << endl;
if (it->first == x)
for(i=it->second.begin();i!=it->second.end();i++)
{
cout << (*i) << endl;
if((*i)==y)
return 1;
}
}
return 0;
}
Wrap it up in an iterator.
This can be templated for reuse.
Here is a minimal working example for the std::vector<T> container:
#include <iostream>
#include <utility>
#include <vector>
/// Iterable vector of vectors
/// (This just provides `begin` and `end for `Vector2Iterable<T>::Iterator`).
template<typename T>
class VovIterable
{
public:
static const std::vector<T> EMPTY_VECTOR;
/// Actual iterator
class Iterator
{
typename std::vector<std::vector<T>>::const_iterator _a1;
typename std::vector<T>::const_iterator _a2;
typename std::vector<std::vector<T>>::const_iterator _end;
public:
/// \param a1 Outer iterator
/// \param a2 Inner iterator
/// \param end End of outer iterator
explicit Iterator(typename std::vector<std::vector<T>>::const_iterator a1, typename std::vector<T>::const_iterator a2, typename std::vector<std::vector<T>>::const_iterator end)
: _a1(a1)
, _a2(a2)
, _end(end)
{
Check();
}
bool operator!=(const Iterator &b) const
{
return _a1 != b._a1 || _a2 != b._a2;
}
Iterator &operator++()
{
++_a2; // Increment secondary
Check();
return *this;
}
const T &operator*() const
{
return *_a2;
}
private:
void Check()
{
while (true)
{
if (_a2 != _a1->end()) // Is secondary live?
{
break;
}
// Increment primary
_a1++;
if (_a1 == _end) // Is primary dead?
{
_a2 = EMPTY_VECTOR.end();
break;
}
_a2 = _a1->begin(); // Reset secondary
}
}
};
private:
std::vector<std::vector<T>> _source;
public:
explicit VovIterable(std::vector<std::vector<T>> source)
: _source(std::move(source))
{
}
/// Start of vector of vectors
[[nodiscard]] Iterator begin() const
{
if (this->_source.empty())
{
return end();
}
return Iterator(this->_source.cbegin(), this->_source.cbegin()->cbegin(), this->_source.cend());
}
/// End of vector of vectors
[[nodiscard]] Iterator end() const
{
return Iterator(this->_source.cend(), EMPTY_VECTOR.end(), this->_source.cend());
}
};
template<typename T>
const std::vector<T> VovIterable<T>::EMPTY_VECTOR = {0};
/// Sample usage
int main()
{
std::vector<std::vector<int>> myVov{{1, 2, 3},
{4, 5, 6},
{7, 8, 9}};
for (int i: VovIterable(myVov))
{
std::cout << i << std::endl;
}
return 0;
}
So here is my program with the error:
// ConsoleApplication42.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <list>
#include <cstdlib>
#include <time.h>
#include <algorithm>
#include <string>
#include <vector>
using namespace std;
const int numberOfStudents = 9;
string names[numberOfStudents] = {"Abe","Billy","Carl","Dillan","Eddie","Felix","Gill","Herald","Isaac"};
struct StudentInfo {
string name;
int grade;
bool operator< (int grade){
return grade < grade;
}
bool operator< (string name){
return name < name;
}
};
void populateStudentRecords(vector<StudentInfo>Students,vector<int>::iterator iter, int x){
for(auto iter = Students.begin(); iter != Students.end(); ++iter){
iter->name = names[x];
iter->name.push_back(x);
iter->grade = x++;
x = x++;
}
}
bool sortByName(const StudentInfo x, const StudentInfo y){
return x.name < y.name;
}
bool sortByGrade(const StudentInfo x, const StudentInfo y){
return x.grade < y.grade;
}
void displayRecords(vector<StudentInfo>Records,vector<int>::iterator iter){
for(auto iter = Records.begin(); iter != Records.end(); ++iter){
cout<<*iter->name<<" -"<<*iter->grade<<endl;
}
}
void displayMaxAndMinGrade(vector<StudentInfo>Records,vector<int>::iterator iter){
for(auto iter = Records.begin(); iter != Records.end(); ++iter){
cout<<*iter->name<<" - " <<*iter->grade<<endl;
iter = Records.end();
cout<<*iter->name<<" - " <<*iter->grade<<endl;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
vector<StudentInfo>Records (numberOfStudents);
vector<int>::iterator iter;
populateStudentRecords(Records,iter,0);
sort(Records.begin(),Records.end(),sortByName);
displayRecords(Records,iter);
sort(Records.begin(),Records.end(),sortByGrade);
cout<<" "<<endl;
displayMaxAndMinGrade(Records, iter);
return 0;
}
In the displayRecords function and the displayMaxAndMin function, I have the * symbol next to the iterator. I want the computer to display the value of these variables within each occurrence of the structure in the vector. However, I get an error c2100 when I try to build the program. I have tried to run the program without including the * symbol, but that displays the address of each variable and also leads to a crash. How do I fix this? Thank you.
You need to read an introductory book on programming with C++. This code is full of errors. You don't know how to use pointers/references/iterators.
Learn about copying, references, and pointers from a good book. Follow the link at the end of this answer.
Variables should be limited to the scope in which they are used. Stop passing so many arguments to your function when they don't really need them.
You are using both the indirection and dereference operators at the same time when you only need one for the type you are applying the operators to. This is the reason for your error.
You are incrementing an array index twice per loop, which makes it go out of bounds.
You are using your container's end() member function with the assumption that it returns an iterator to the last element in the container.
You want to print the lowest and highest grades but loop through the whole container.
For your sake, I've fixed the most glaring errors:
#include <iostream>
#include <list>
#include <cstdlib>
#include <time.h>
#include <algorithm>
#include <string>
#include <vector>
using namespace std;
const int numberOfStudents = 9;
string names[numberOfStudents] = { "Billy", "Abe","Carl","Dillan","Eddie","Felix","Gill","Herald","Isaac" };
struct StudentInfo
{
string name;
int grade;
};
void populateStudentRecords(vector<StudentInfo>& Students)
{
int x{ 0 };
for (auto iter = Students.begin(); iter != Students.end(); ++iter)
{
iter->name = names[x];
iter->name.push_back(x);
iter->grade = ++x;
}
}
bool sortByName(const StudentInfo x, const StudentInfo y)
{
return x.name < y.name;
}
bool sortByGrade(const StudentInfo x, const StudentInfo y)
{
return x.grade < y.grade;
}
void displayRecords(vector<StudentInfo>Records)
{
for (auto iter = Records.begin(); iter != Records.end(); ++iter)
{
cout << iter->name << " -" << iter->grade << endl;
}
}
void displayMaxAndMinGrade(vector<StudentInfo>Records)
{
auto iter = Records.begin();
cout << iter->name << " - " << iter->grade << endl;
iter = Records.end() - 1;
cout << iter->name << " - " << iter->grade << endl;
}
int main()
{
vector<StudentInfo>Records(numberOfStudents);
populateStudentRecords(Records);
sort(Records.begin(), Records.end(), sortByName);
displayRecords(Records);
sort(Records.begin(), Records.end(), sortByGrade);
cout << " " << endl;
displayMaxAndMinGrade(Records);
return 0;
}
Please do yourself a favor and visit the following link:
The Definitive C++ Book Guide and List
For some reason the check_sort function can only be called once within the main function otherwise the workflow freezes after it's first executed.
For example. The output ends at:
How many elements for container? 5000
Check: list is sorted
Elapsed time: 0.32 seconds
Instead of continuing like:
How many elements for next container? 5000
Check: list is sorted
Elapsed time: 0.30 seconds
Check: set is sorted
Elapsed time: 0.01 seconds
Check: vector is sorted
Elapsed time: 0.25 seconds
Full program below:
#include <cmath>
#include <iterator>
#include <iostream>
#include <iomanip>
#include <vector>
#include <ctime>
#include <list>
#include <set>
#include <algorithm>
#include <cstdlib>
using namespace std;
typedef void Inserter(vector<double>);
vector<double> gen_data(int num_elts);
void insert_list(vector<double> data);
void insert_set(vector<double> data);
void insert_vector(vector<double> data);
void time_insert( Inserter inserter, vector<double> data);
template <class Iter> bool is_sorted(Iter first, Iter last);
template <class Iter> void check_sort(Iter first, Iter last, string cont_kind);
list<double> l;
set<double> s;
vector<double> v;
int main() {
srand(time(0));// initialize random number generator
cout << "How many elements for container? ";
int num_elts = 0;
while (cin >> num_elts) {
if (num_elts <= 0)
cout << "Error, should be > 1";
else {
vector<double> data = gen_data(num_elts);
check_sort(l.begin(), l.end(), "list");
time_insert(insert_list, data);
check_sort(s.begin(), s.end(), "set");
time_insert(insert_set, data);
check_sort(v.begin(), v.end(), "vector");
time_insert(insert_vector, data);
}
cout << "\nHow many elements for next container? ";
}
return 0;
}
void time_insert( Inserter inserter, vector<double> data) {
clock_t t1 = clock();
if (t1 == clock_t(-1)) { //if clock() doesn’t work
cerr << "sorry, no clock\n";
exit(1);
}
inserter(data);
clock_t t2 = clock();
if (t2 == clock_t(-1)) {
cerr << "sorry, clock overflow\n";
exit(2);
}
cout << "Elapsed time: " << fixed << setprecision(2)
<< double(t2-t1)/CLOCKS_PER_SEC << " seconds\n";
}
class Larger_than {
double v;
public:
Larger_than(double vv) : v(vv){}
bool operator()(double x) const {return x>v;}
};
// Sorts and then inserts data into a list
void insert_list(vector<double> data)
{
list<double> l;
for(int i=0; i < data.size(); i++){
list<double>::iterator p = find_if(l.begin(),l.end(), Larger_than(data[i]));
l.insert(p, data[i]);
}
}
// Sorts and then inserts data into a list
void insert_set(vector<double> data)
{
set<double> s;
for(int i=0; i < data.size(); i++){
set<double>::iterator p = find_if(s.begin(),s.end(), Larger_than(data[i]
));
s.insert(p, data[i]);
}
}
// Sorts and then inserts data into a list
void insert_vector(vector<double> data)
{
vector<double> v;
for(int i=0; i < data.size(); i++){
vector<double>::iterator p = find_if(v.begin(),v.end(), Larger_than(data
[i]));
v.insert(p, data[i]);
}
}
// generate num_elts random numbers in the range [0.0, 1.0),
// which are returned in a vector
vector<double> gen_data (int num_elts)
{
vector<double> result;
for (int i = 0; i < num_elts; i++) {
double datum = 1.0*rand()/RAND_MAX;
result.push_back(datum);
}
return result;
}
// is container spanned by [from, last) sorted?
template <class Iter> bool is_sorted(Iter first, Iter last)
{
Iter next = first; // next element
for (next++; next != last; next++, first++) {
if (*first > *next)
return false;
}
return true;
}
// prints a msg describing container kind, as well as whether container
// spanned by [from, last) is sorted
template <class Iter> void check_sort(Iter first, Iter last, string cont_kind)
{
cout << "Check: " << cont_kind << " is ";
if (!is_sorted(first, last)) cout << "not ";
cout << "sorted\n";
}
I don't know if this is part of your problem, but is_sorted doesn't work right if first is the end of the container. next gets incremented past end and undefined behavior is encountered.
EDIT: Actually this is definitely it: You don't populate the vector/list/set containers prior to calling the check function on them. Even if you called the insert functions before calling the check function it still wouldn't work because each insert_* function declares a local to populate which shadows the global variable you're trying to fill.
EDIT2: In insert_set the find_if is actually making your code less performant than it should be. You should just use std::set::insert and let it use its built-in sorting, which will be more efficient than find_if because it knows the implementation of the underlying set.
Your template function is_sorted() doesn't check properly whether first is equal to last before incrementing next which is a copy of first:
template <class Iter> bool is_sorted(Iter first, Iter last)
{
Iter next = first; // next element
for (next++; next != last; next++, first++) {
if (*first > *next)
return false;
}
return true;
}
This could lead to problems if you get to iterate over an empty range, I believe.
template <class Iter> bool is_sorted(Iter first, Iter last)
{
if (first == last)
return false;
for (Iter next = first+1; next != last; next++, first++)
{
if (*first > *next)
return false;
}
return true;
}
I'm not certain you get empty ranges...so this may be a red herring.
Since you don't set the list before checking that it is sorted (and you don't check that it is sorted after inserting the data), you do run into issues with empty ranges. You need to reverse the sequence of your insert and check operations:
vector<double> data = gen_data(num_elts);
time_insert(insert_list, data);
check_sort(l.begin(), l.end(), "list");
time_insert(insert_set, data);
check_sort(s.begin(), s.end(), "set");
time_insert(insert_vector, data);
check_sort(v.begin(), v.end(), "vector");
You should avoid duplicated code in your main loop by calling a function to get the number of elements to process. Also, it is conventional to report errors on cerr.
static int get_num_elts()
{
int num_elts;
cout << "How many elements for container? ";
cin >> num_elts;
if (num_elts < 1)
cerr << "Error: number should be >= 1" << endl;
return num_elts;
}
...
int num_elts;
while ((num_elts = get_num_elts()) > 0)
{
vector<double> data = gen_data(num_elts);
time_insert(insert_list, data);
check_sort(l.begin(), l.end(), "list");
time_insert(insert_set, data);
check_sort(s.begin(), s.end(), "set");
time_insert(insert_vector, data);
check_sort(v.begin(), v.end(), "vector");
}
Your code does not enter the body of the loop in the is_sorted function
instead for (next++; next != last; next++, first++) do for (next; next != last; next++, first++) . Because if first == last, then it would be a problem and that is what you are facing. But not incrementing the next pointer will do no harm as the first comparison will compare the first element with itself which will always be evaluated as false in a greater than comparison with itself.