Can i use nested loops with vectors in cpp? - c++

i have a cpp problem and i don't know whats wrong.. maybe you can help me :).
I'm trying to implement a data structure for a graph. In this graph i will connect some nodes, which have a small euclidean distance, but at the second iteration, my iterator will point to 0x0. This case appears only, if i give the distance of those two nodes to std::cout. Here is my code:
for(vector<Node*>::iterator n1 = g->getNodes().begin(); n1 != g->getNodes().end(); ++n1)
{
for(vector<Node*>::iterator n2 = g->getNodes().begin(); n2 != g->getNodes().end(); ++n2)
{
if(*n2 == 0)
{
// This will be entered after the first iteration of n2.
cout << "n2 null" << endl;
continue;
}
double distance = (*n1)->getDistance(*n2); // just euclidean distance
if(distance <= minDistance)
{
// This works fine:
cout << "(" << *n1 << "," << *n2 << ") << endl;
// This brings me a "Segmentation fault"
cout << "(" << *n1 << " , " << *n2 << ") -> " << distance << endl;
}
}
}
Is this owed by the nested loops? Can any body tell me my fault? Thanks a lot!
EDIT: Here is some more code:
node.h
#ifndef NODE_H_
#define NODE_H_
#include <vector>
#include <iostream>
#include <limits>
#include <math.h>
using namespace std;
class Node
{
private:
int x, y, z;
public:
Node(int x, int y, int z) : x(x), y(y), z(z)
{
}
inline int getX() { return x; }
inline int getY() { return y; }
inline int getZ() { return z; }
inline double getDistance(Node* other)
{
return sqrt(pow(x-other->getX(), 2) + pow(y-other->getY(), 2) + pow(z-other->getZ(), 2));
}
};
#endif
graph.h
#ifndef GRAPH_H_
#define GRAPH_H_
#include <vector>
#include "node.h"
using namespace std;
class Graph
{
private:
vector<Node*> nodes;
public:
~Graph()
{
while(!nodes.empty())
{
delete nodes.back(), nodes.pop_back();
}
}
inline vector<Node*> getNodes() { return nodes; }
inline int getCountNodes() { return nodes.size(); }
bool createNode(int x, int y, int z)
{
nodes.push_back(new Node(x, y, z));
return true;
};
#endif
main.cc
#include <iostream>
#include <vector>
#include <algorithm>
#include <math.h>
#include "model/graph.h"
using namespace std;
int main()
{
Graph *g = new Graph();
int nodeDistance = 100;
for(int z = 0; z <= 300; z += nodeDistance)
{
for(int x = 0; x <= 500; x += nodeDistance)
{
for(int y = 0; y <= 300; y += nodeDistance)
{
g->createNode(x, y, z);
}
}
}
for(vector<Node*>::iterator n1 = g->getNodes().begin(); n1 != g->getNodes().end(); ++n1)
{
for(vector<Node*>::iterator n2 = g->getNodes().begin(); n2 != g->getNodes().end(); ++n2)
{
if(*n2 == 0)
{
// This will be entered after the first iteration of n2.
cout << "n2 null" << endl;
continue;
}
double distance = (*n1)->getDistance(*n2); // just euclidean distance
if(distance <= nodeDistance)
{
// This works fine:
cout << "(" << *n1 << "," << *n2 << ") << endl;
// This brings me a "Segmentation fault"
cout << "(" << *n1 << " , " << *n2 << ") -> " << distance << endl;
}
}
}
delete g;
return 0;
}

One major issue is that your getNodes function returns a copy of a vector, not the original vector. Therefore your iterators you use in the loops are not iterating over the same vector.
Instead, the iterators you're using in the nested loops are iterating over 4 different (but equivalent) vectors instead of the actual vector from the object in question.
There is nothing wrong in returning a copy of a vector in general. However when you do this, you have to make sure you call such a function if you really want a copy, and not the same vector. Using the getNodes function as you used it is not a valid usage in terms of what you are trying to accomplish.
The error is here:
inline vector<Node*> getNodes() { return nodes; }
The fix:
inline vector<Node*>& getNodes() { return nodes; }
The latter ensures that a reference to the actual vector in question is returned, not a copy of the actual vector. You can add an additional function that returns the vector as a copy if you want to still have the functionality available.

Related

How to use overload operator as condition in a if statment?

Here is the class
#include <fstream>
#include <cstdlib>
#include <math.h>
#include <iomanip>
#include <iostream>
using namespace std;
class Point {
protected:
int x, y;
double operator-(const Point &def){
return sqrt(pow((x-def.x),2.0)+
pow((y-def.y),2.0));
}
};
class Circle: public Point {
private:
int radius;
public:
Circle(){
this->x=x;
this->y=y;
this->radius=radius;
}
Circle(int x, int y, int radius){
this->x=x;
this->y=y;
this->radius=radius;
}
void printCircleInfo() {
cout << x << " " << y << " " << radius << " " ;
}
This is the operator I want to be the condition in my if statement.
bool operator==(const Circle &def){
return (x==def.x) & (y==def.y) & (radius==def.radius);
}
bool doIBumpIntoAnotherCircle(Circle anotherCircle){
if (anotherCircle.radius + radius >= *this - anotherCircle )
return true;
return false;
}
};
Here is main
int main(){
int x,y,radius;
const int SIZE = 13;
Circle myCircleArry[SIZE];
myCircleArry[0] = Circle(5,3,9);
cout << endl;
myCircleArry[0].printCircleInfo(); cout << " ; ";
ifstream Lab6DataFileHandle;
Lab6DataFileHandle.open("Lab6Data.txt");
while (!Lab6DataFileHandle.eof( )) {
for (int i = 1; i < SIZE; i++) {
Lab6DataFileHandle>>x;
Lab6DataFileHandle>>y;
Lab6DataFileHandle>>radius;
myCircleArry[i] = Circle(x,y,radius);
if (myCircleArry[0].doIBumpIntoAnotherCircle(myCircleArry[i])) {
myCircleArry[i].printCircleInfo(); cout << " ; ";
Here is the If statement
if ( operator==( Circle &def))
{cout <<"*";
}
}
}
}
Lab6DataFileHandle.close();
}
How do I use the overloaded operator as the condition of the if statement? If you need any clarification just ask other wise please leave an example in your answer.
Thank you for your time.
A == needs two arguments (even if the overload is a member), you would write the if as any other if statement:
if(circle1 == circle2) { ... }
and if there's a matching overload the compiler would transform that into something like:
if(circle1.operator ==(circle2)) { ... }

c++ segmentation fault trying to access vector

Im trying to create a adjacency representation of a graph.
I wrote a small program using vectors of vectors , however I keep getting "segmentation fault" but the compiler(clang++ version 5.0.1 on Windows) it seems wereever I try to access the vector vertex_matrix its giving a segmentation fault, why is it not being instantiated?
Here is the header:
#ifndef GRAPH_MATRIX
#define GRAPH_MATRIX
#include <vector>
//header for graph represented via adjacency matrix with minimal functionality
class graph
{
public:
graph(int);
~graph();
void add_edge(int v1, int v2, int weight);
void print_graph();
private:
std::vector<std::vector<int>> vertex_matrix;
int num_of_vertices;
int num_of_edges;
};
#endif
Here is the cpp implementation:
#include <iostream>
#include "graph_matrix.h"
#include <climits>
using namespace std;
//header for graph represented via adjacency matrix with minimal functionality
graph::graph(int _num_of_vertices) : num_of_vertices(_num_of_vertices)
{
if (_num_of_vertices==0)
{
_num_of_vertices=10;
}
for (int i = 0; i < _num_of_vertices; i++)
{
vertex_matrix[i]=(vector<int> (_num_of_vertices,INT_MAX));
}
}
graph::~graph()
{
vertex_matrix.clear();
}
void graph::add_edge(int v1, int v2, int weight)
{
//vertex_matrix[v1-1][v2-1] == INT_MAX
vector<int> columnVector = vertex_matrix[v1-1];
if (columnVector[v2-1] == INT_MAX)
{
columnVector[v2-1] = weight;
}
}
void graph::print_graph()
{
cout << "vertex_matrix size:" << vertex_matrix.size() << endl;
for (int i=0; i< num_of_vertices; i++)
{
for (int j = 0; j < num_of_vertices; j++)
{
//vertex_matrix[i][j]
std::vector<int> columnVector = vertex_matrix[i];
if (columnVector[j] != INT_MAX)
{
std::cout << columnVector[j] ;
}
else
{
std::cout << "0";
}
}
std::cout << endl;
}//end for printing
}
Here is the main entry:
#include <iostream>
#include "graph_matrix.h"
using namespace std;
int main ()
{
std::cout << " Matrix representation of graph" << std::endl;
graph _graph(4);
_graph.add_edge(1,2,1);
_graph.add_edge(2,3,1);
_graph.add_edge(3,1,1);
_graph.add_edge(3,3,1);
_graph.add_edge(3,4,1);
_graph.add_edge(4,0,0);
_graph.print_graph();
}
I edited the above code to use pass by reference, however the matrix still prints as 0's.
Please help with pass by reference, updates below:
Header:
#ifndef GRAPH_MATRIX
#define GRAPH_MATRIX
#include <vector>
//header for graph represented via adjacency matrix with minimal functionality
class graph
{
public:
graph(int);
~graph();
void add_edge(int v1, int v2, int weight,std::vector<std::vector<int>> & matrix);
void print_graph();
std::vector<std::vector<int>> vertex_matrix;
private:
int num_of_vertices;
int num_of_edges;
};
#endif
Cpp file:
#include <iostream>
#include "graph_matrix.h"
#include <climits>
using namespace std;
//header for graph represented via adjacency matrix with minimal functionality
graph::graph(int _num_of_vertices) : num_of_vertices(_num_of_vertices) {
if (num_of_vertices == 0) {
num_of_vertices = 10;
}
for (int i = 0; i < num_of_vertices; i++) {
std::vector<std::vector<int>>& matrix = vertex_matrix;
matrix.push_back(vector<int> (num_of_vertices, INT_MAX));
}
}
graph::~graph() {
std::vector<std::vector<int>>& matrix = vertex_matrix;
matrix.clear();
}
void graph::add_edge(int v1, int v2, int weight,std::vector<std::vector<int>> & _matrix) {
//vertex_matrix[v1-1][v2-1] == INT_MAX
vector<int> columnVector = _matrix[v1 - 1];
if (columnVector[v2 - 1] == INT_MAX) {
columnVector[v2 - 1] = weight;
}
}
void graph::print_graph() {
std::vector<std::vector<int>>& matrix = vertex_matrix;
for (int i = 0; i < matrix.size(); i++) {
for (int j = 0; j < matrix.size(); j++) {
//vertex_matrix[i][j]
std::vector<int> columnVector = matrix[i];
if (columnVector[j] != INT_MAX) {
std::cout << columnVector[j];
} else {
std::cout << "0";
}
}
std::cout << endl;
}//end for printing
}
main:
#include <iostream>
#include "graph_matrix.h"
using namespace std;
int main ()
{
std::cout << " Matrix representation of graph" << std::endl;
graph _graph(4);
std::vector<std::vector<int>>& m = _graph.vertex_matrix;
_graph.add_edge(1,2,1,m);
_graph.add_edge(2,3,1,m);
_graph.add_edge(3,1,1,m);
_graph.add_edge(3,3,1,m);
_graph.add_edge(3,4,1,m);
_graph.add_edge(4,0,0,m);
_graph.print_graph();
}
Any help will be appreciated.
Thanks
You create an empty vector and then try to access elements in it. Change your constructor to
graph::graph(size_t _num_of_vertices) :
vertex_matrix(
std::vector<std::vector<int>>(
_num_of_vertices,std::vector<int>(_num_of_vertices)
)
)
{}
to create a correctly sized vector.
Also in case _num_vertices == 0 you set it to 10 but thats after you initialized the member num_vertices so you leave the object in an inconsistent state. There are different ways to fix that, I would probably just throw an exception when the number of vertices passed is zero, or just ignore it. User wants a zero sized matrix? Why not?
Moreover the size should be unsigned not signed, there is size_t for container sizes. Even better you shouldnt have that member at all, because a vector already knows its size, the only reason to repeat that information is to introduce mistakes ;)

C++ error expected primary-expression before '(' token

I am trying to create a program that takes N random nodes from user input and creates a random integer that is put into a binary tree and then copied into a priority queue. The integer becomes the key for each node and another integer counts the frequency of the key. I run into issues when I copy into the priority queue because I get duplicates and I need to remove them. I tried to create a set through the node constructor but I get the error above in the .cpp file.
#include <iostream>
#include <random>
#include <ctime>
#include <queue>
#include <set>
#include <functional>
#include <algorithm>
#include<list>
#include "Q7.h"
using namespace std;
int main()
{
node * root=NULL;
node z;
int n,v;
vector<int> first;
vector<int>::iterator fi;
default_random_engine gen(time(NULL));
cout<<"how many values? "; cin>>n;
for(int i=0; i<n; i++)
{ (v=gen()%n);
first.push_back(v);
if(root==NULL){root = node(set(v));}///This is where I get the error!!
else{
root->addnode(v);
}
}
z.unsortedRemoveDuplicates(first);
cout<<"Binary Tree in a depth first manner with Duplicates removed!"<<endl;
for ( fi = first.begin() ; fi != first.end(); ++fi{cout<<"Node "<<*fi<<endl;}
cout<<"-------------------"<<endl;
root->display();
cout<<"-------------------"<<endl;
cout<<"-------------------"<<endl;
root->display_Queue1();
cout<<"-------------------"<<endl;
return 0;
}
my .h file
class node
{
public:
node(){left=NULL; right=NULL; ct = 1;}
node set(int v) {val = v; left=NULL; right=NULL; ct=1;}
node (int Pri, int cat)
: val(Pri), ct(cat) {}
friend bool operator<(//sorts queue by lowest Priority
const node& x, const node& y) {
return x.val < y.val;
}
friend bool operator>(//sorts queue by greatest Priority
const node& x, const node& y) {
return x.ct > y.ct;
}
friend ostream&//prints out queue later
operator<<(ostream& os, const node& Pri) {
return os <<"my value = "<<Pri.val<<" occured "<<Pri.ct<<" times";
}
int unsortedRemoveDuplicates(vector<int>& numbers)
{
node set<int> seenNums; //log(n) existence check
auto itr = begin(numbers);
while(itr != end(numbers))
{
if(seenNums.find(*itr) != end(seenNums)) //seen? erase it
itr = numbers.erase(itr); //itr now points to next element
else
{
seenNums.insert(*itr);
itr++;
}
}
return seenNums.size();
}
priority_queue<node, vector<node>, greater<node> > pq;
priority_queue<node, vector<node>, less<node> > pq1;
void addnode(int v)
{
if(v==val){ct++;}
pq.emplace(node (set (v)));///No error here for set with constructor why??
pq.emplace(node (set (v)));
if(v<val)
{
if(left==NULL){left=new node(set(v));
}
else{left->addnode(v);
}
}
else
{
if(right==NULL){right = new node (set(v));
}
else{right->addnode(v);
}
}
}
int display()
{
if(left!=NULL){left->display();}
cout<<"frequency "<<ct<<" value"<<val<<endl;
if(right!=NULL){right->display();}
}
void display_Queue()
{
cout << "0. size: " << pq.size() << '\n';
cout << "Popping out elements from Pqueue..."<<'\n';
while (!pq.empty())
{
cout << pq.top() << endl;
pq.pop();
}
cout << '\n';
}
void display_Queue1()
{
cout << "0. size: " << pq1.size() << '\n';
cout << "Popping out elements from Pqueue..."<<'\n';
while (!pq1.empty())
{
cout << pq1.top() << endl;
pq1.pop();
}
cout << '\n';
}
private:
int val; ///value in that node
int ct;
///ct = count of that value
node * left;
node * right;
};
Congratulations, with this line:
root = node(set(v));
You have discovered why people here often say to avoid using using namespace std;. This is being interpreted as:
root = static_cast<node>(std::set(v));
Instead of what you want, which might be:
root = new node();
root->set(v);
First, note that we need to use new as we are creating a new node, not trying to cast a node to a node, which would have also given another compiler error about trying to assign a value to a pointer.
Next, note that you don't get the error in the header file as there is no using namespace std; there, and since it is in a member function, the line:
void node::addnode(int v)
{
//...
pq.emplace(node (set (v)));///No error here for set with constructor why??
//...
}
Is interpreted as:
pq.emplace(static_cast<node>(this->set(v)));
However, is this what you really want to do?
Furthermore, I would change the constructors to be:
public:
node (int Pri = 0, int cat = 1)
: val(Pri), ct(cat), left(NULL), right(NULL) {}
// DELETED node (int Pri, int cat)
Thus you can do:
root = new node(v);
And it will work as I think you expect it to.

hash_multimap find not working the way it should

I've been trying to use a hash_multimap for sometime now, but the find method keeps giving me a iterator to the end of the container even though I know it found a matching key. What has me confused is that I've used the same code before for a different project with it working perfectly but now its playing up. The reason I know its finding something is because I've put a few cout in the hash function and hash compare, which is telling me that a key is found and that it matches what I gave the hash_multimap::find meathod, yet still it gives me an iterator.
first the header file
//
// HashGrid.h
// Planetarium
//
// Created by Taura J Greig on 24/08/12.
// Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//
#ifndef _HASHGRID_
#define _HASHGRID_
#include <iostream>
#include <hash_map>
#include <deque>
#include "..//hashKey.h"
struct myTraits
{
static const size_t bucket_size = 4;
static const size_t min_buckets = 8;
myTraits() { };
myHash hashfunction;
myEqualTo equal_to;
size_t operator() (const hashKey& key) const
{
size_t hashval = 0;
hashval = ((key.y * globalGridWidth) + key.x);
cout << "x : " << key.x << " y : " << key.y << endl;
cout << "hashVal : " << hashval << endl;
return hashval;
}
bool operator() (const hashKey& key1, const hashKey& key2) const
{
bool test = (key1.x == key2.x && key1.y == key2.y);
cout << "equal_to = " << test << endl;
return test;
}
};
using namespace std;
//using namespace stdext;
using namespace stdext;
template <class T>
class HashGrid
{
public:
typedef deque<T *> localObjects;
typedef pair<hashKey, T *> addingPair;
typedef hash_multimap <hashKey, T *, myTraits> hashmMap;
typedef typename hash_multimap <hashKey, T *, myTraits> :: iterator hashmMapItor;
typedef pair<hashmMapItor, hashmMapItor> valueRange;
private:
hashKey keyOffsets[9];
int gridSize;
hash_multimap<hashKey, T*, myTraits> theMap;
inline bool exists(hashKey & theKey);
inline bool exists(hashKey & theKey, hashmMapItor & it);
public:
HashGrid();
void setup(int gridSize);
void update();
void draw(); // this is used for viusal debug,
void resize();
void addObject(T * object);
void getLocalObjects(float & x, float & y, int range, localObjects & p1);
};
template <class T>
inline bool HashGrid<T>::exists(hashKey & theKey)
{
hashmMapItor it;
it = theMap.find(theKey);
if (it == theMap.end())
{
return false;
}
else
{
return true;
}
}
template <class T>
inline bool HashGrid<T>::exists(hashKey & theKey,
hashmMapItor & it)
{
it = theMap.find(theKey);
if (it == theMap.end())
{
return false;
}
else
{
return true;
}
}
#include "HashGrid.cpp"
#endif
and the source file
//
// HashGrid.cpp
// Planetarium
//
// Created by Taura J Greig on 26/08/12.
// Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//
#ifndef _HASHGRID_SOURCE_
#define _HASHGRID_SOURCE_
#include "HashGrid.h"
#include "ofMain.h"
template<class T>
void HashGrid<T>::update()
{
theMap.clear();
}
template <class T>
void HashGrid<T>::addObject(T *obj)
{
hashKey tempKey;
tempKey.x = int(obj -> getPos().x) / gridSize;
tempKey.y = int(obj -> getPos().y) / gridSize;
cout << "tempKey.x : " << tempKey.x << endl;
cout << "tempKey.y : " << tempKey.y << endl;
theMap.insert(addingPair(tempKey, obj));
}
template <class T>
void HashGrid<T>::getLocalObjects(float & x, float & y, int range, localObjects & p1)
{
cout << "you are gettin local objects" << endl;
int gridX = (int(x) / gridSize);
int gridY = (int(y) / gridSize);
cout << "player x : " << x << endl;
cout << "player y : " << y << endl;
cout << "girdX " << gridX << endl;
cout << "girdY " << gridY << endl;
for (int i = 0; i < 9; i++)
{
hashKey tempkey;
tempkey.x = gridX;
tempkey.y = gridY;
tempkey += keyOffsets[i];
cout << i << " tempKey : " << tempkey.x << " " << tempkey.y << endl;
cout << "exists " << exists(tempkey) << " ";
//this is where the problem lies, the exists function will always return
//false even when the key is found
if (exists(tempkey))
{
cout << "found" << endl;
hashmMapItor it;
valueRange elements;
elements = theMap.equal_range(tempkey);
for (it = elements.first; it != elements.second; it++)
{
p1.push_back(it->second);
}
}
else
{
cout << "not found" << endl;
}
}
}
#endif
Note that I've cut a lot of methods out of the block above to save space because they are unrelated to the problem at hand. However I've left their declarations in the header file. Also I am aware that there a few things that I'm doing with templates that are ugly. Just deal with it for now.
Now I'll go into detail about whats happening in the code and where the problem lies. In the getlocalobjects method, the method "exists(key)" is called to determine if the hash_multimap has an element with the key provided. I know that it does find something because as I mentioned above because I put cout in the equal_to function to tell me when its used an what its result are.
Consistently its telling me yes (via equal_to debug) it found something but the exist method will still return false. This leading me to believe that there may be a bug in hash_multimap::find since it means that even if it finds something its gives me an iterator to hash_multimap::end
So my question is am I doing horribly wrong regarding the use of the multimap? does my traits struct not have something required for the multimap to work correctly
EDIT and the implementation for the hashKey that i forgot it include
header
#ifndef _HASHKEY_
#define _HASHKEY_
#include <iostream>
using namespace std;
static int globalGridSize = 1;
static int globalGridWidth = 1;
static int globalGridHeight = 1;
struct hashKey
{
public:
int x;
int y;
hashKey();
hashKey(int x, int y);
void set(int x, int y);
void set(hashKey & key);
void printKey()
{
cout << x << " " << y << endl;
}
bool operator < (const hashKey & key1) const;
bool operator == (const hashKey & key1) const;
hashKey& operator += (hashKey & key1);
};
#endif
and source
#ifndef _HASHKEY_SOURCE_
#define _HASHKEY_SOURCE_
#include "hashKey.h"
hashKey::hashKey()
{
x = 0;
y = 0;
}
hashKey::hashKey(int x, int y)
{
hashKey::x = x;
hashKey::y = y;
}
void hashKey::set(int x, int y)
{
hashKey::x = x;
hashKey::y = y;
}
void hashKey::set(hashKey &key)
{
x = key.x;
y = key.y;
cout << "set: x = " << x << " y = " << y << endl;
}
bool hashKey::operator<(const hashKey &key1) const
{
if ( (this->x < key1.x) && (this->y < key1.y))
{
return true;
}
return false;
}
bool hashKey::operator == (const hashKey &key1) const
{
if ((this-> x == key1.x) && (this->y == key1.y))
{
return true;
}
return false;
}
hashKey& hashKey::operator+=(hashKey &key1)
{
this->x += key1.x;
this->y += key1.y;
return *this;
}
#endif
EDIT [SOVLED] I changed the hash_multimap tp an unordered_multimap and now it works, so initial suspicion was right, that at this time the hash_multimap is bugged an its find method will always give an iterator to the the end. Note that i'm using visual studio c++ 2010, it may not be bugged on other platforms or other compilers, however it defiantly was bugged in my case
The content below is speculation as not all the relevant code is visible.
It seems that you have:
A hash which is of type size_t (as created from the first operator() of myTraits)
A key of type hashKey (which is not a hash from the hash_multimap's perspective)
You did not provide the implementation of hashKey, so my immediate question is:
Did you provide the equality operator for hashKey?
Or alternatively, did you override equal_to<haskHey>?
The potential problem (and reason for the above questions) that I see is that you defined your hashmMap as hash_multimap <hashKey, T *, myTraits> which overrides the hashing function, but it does not override the key equality (which is of type hashKey). So, I presume that the default comparator of hashKey (and not the one defined in myTraits) might be used.
Perhaps hash_multimap <hashKey, T *, myTraits, myTraits> would suffice?
Update: I just notice that VS's hash_multimap has a different signature, than the one coming from STL. Compare:
Visual Studio version
STL version
The latter has hashing function and key comparator separated. This is just asking for terrible problems once you switch compilers!

C++ Insertion Sort a vector

I'm trying to do an insertion sort on a vector of baseball pitchers I created yesterday with help from a previous post. I want to sort the pitchers in ascending order by ERA1. I have gotten the insertion sort to work in the past for a set of integers. I think I have a syntax error in my code for the insertion sort. Up until trying to add the insertion sort this program was working well. I get an error - expected unqualified id before [ token. Thanks in advance for any help.
#ifndef Pitcher_H
#define Pitcher_H
#include <string>
#include <vector>
using namespace std;
class Pitcher
{
private:
string _name;
double _ERA1;
double _ERA2;
public:
Pitcher();
Pitcher(string, double, double);
vector<Pitcher> Pitchers;
string GetName();
double GetERA1();
double GetERA2();
void InsertionSort(vector<Pitcher>&);
~Pitcher();
};
#endif
#include "Pitcher.h"
#include <iostream>
#include <string>
#include <vector>
#include <iomanip>
using namespace std;
Pitcher::Pitcher()
{
}
Pitcher::~Pitcher()
{
}
string Pitcher::GetName()
{
return _name;
}
Pitcher::Pitcher(string name, double ERA1, double ERA2)
{
_name = name;
_ERA1 = ERA1;
_ERA2 = ERA2;
}
double Pitcher::GetERA1()
{
return _ERA1;
}
double Pitcher::GetERA2()
{
return _ERA2;
}
#include "Pitcher.h"
#include <iostream>
#include <string>
#include <vector>
#include <iomanip>
void InsertionSort(vector<Pitcher> Pitchers&);
using namespace std;
int main()
{
vector<Pitcher> Pitchers;
cout << "Pitcher" << setw(19) << "Item ERA1" << setw(13) <<
"Item ERA2\n" << endl;
Pitcher h2("Bob Jones", 1.32, 3.49);
Pitchers.push_back(h2);
Pitcher h3("F Mason", 7.34, 2.07);
Pitchers.push_back(h3);
Pitcher h1("RA Dice", 0.98, 6.44);
Pitchers.push_back(h1);
for(unsigned i = 0; i < Pitchers.size(); ++i)
{
cout << setw(19);
cout << left << Pitchers[i].GetName() << "$" <<
setw(10) << Pitchers[i].GetERA1() <<
right << "$" << Pitchers[i].GetERA2() << "\n";
}
cout << endl;
//------------------------------------------------------
InsertionSort(Pitchers);
//Now print the numbers
cout<<"The numbers in the vector after the sort are:"<<endl;
for(int i = 0; i < Pitchers.size(); i++)
{
cout<<Pitchers[i].GetERA1()<<" ";
}
cout<<endl<<endl;
system("PAUSE");
return 0;
}
void InsertionSort(vector<Pitcher> &Pitchers)
{
int firstOutOfOrder = 0;
int location = 0;
int temp;
int totalComparisons = 0; //debug purposes
for(firstOutOfOrder = 1; firstOutOfOrder < Pitchers.size() ; firstOutOfOrder++)
{
if(Pitcher.GetERA1([firstOutOfOrder]) < Pitcher.GetERA1[firstOutOfOrder - 1])
{
temp = Pitcher[firstOutOfOrder];
location = firstOutOfOrder;
do
{
totalComparisons++;
Pitcher.GetERA1[location] = Pitcher.GetERA1[location - 1];
location--;
}while(location > 0 && Pitcher.GetERA1[location - 1] > temp);
Pitcher.GetERA1[location] = temp;
}
}
cout<<endl<<endl<<"Comparisons: "<<totalComparisons<<endl<<endl;
}
Here:
for(firstOutOfOrder = 1; firstOutOfOrder < Pitchers.size() ; firstOutOfOrder++)
{
if(Pitchers[firstOutOfOrder].GetERA1() < Pitchers[firstOutOfOrder-1].GetERA1())
{ //^^^your way was not right, should first access the object then
//access member function
temp = Pitcher[firstOutOfOrder];
//^^^should be Pitchers, similar errors below
location = firstOutOfOrder;
do
{
totalComparisons++;
Pitcher.GetERA1[location] = Pitcher.GetERA1[location - 1];
//^^^similar error as inside if condition
location--;
}while(location > 0 && Pitcher.GetERA1[location - 1] > temp);
//^^^similar error as inside if condition
Pitcher.GetERA1[location] = temp;
//^^similar error as in if condition and name error
}
}
Meanwhile, you put the InsertionSort declaration as a member of the Pitcher class
public:
.
.
void InsertionSort(vector<Pitcher>&);
and you also declare the same function inside main,
void InsertionSort(vector<Pitcher> Pitchers&);
//should be vector<Pitcher>& Pitchers
using namespace std;
int main()
the member function probably should be removed in your case. InsertionSort is not a responsibility of your Pitcher class.
Unless this is homework, you're better off using the build in sort from
<algorithm>