I've searched all over stackoverflow but just can't seem to find what i'm looking for, so here goes..
I have 2 custom classes one being used in the second and when i'm trying to sort the second class.. which is essentially a vector of the first class it throws the error : - message 0x010c3e18 "vector iterators incompatible" const wchar_t *at vc\include\vector line 238 .. here is my code :
#include <iostream>
#include <conio.h>
#include <cmath>
#include <string>
#include <vector>
#include <fstream>
#include <algorithm>
using namespace std;
class cityPhone {
private:
string cityName;
string cityCode;
public:
void setCode(string code){
cityCode=code;
}
void setName(string name){
cityName=name;
}
cityPhone(){
cityName="Varna";
cityCode="0888123123";
}
cityPhone(string name, string code){
cityName=name;
cityCode=code;
}
string getCity(){
return cityName;
}
string getCode(){
return cityCode;
}
};
//struct { //ive used these 2 also and still it doesnt work
// bool operator()(cityPhone a, cityPhone b)
// {
// if (a.getCity().compare(b.getCity())>0)return true;
// return false;
// }
// } cmpCity;
// struct {
// bool operator()(cityPhone a, cityPhone b)
// {
// if (a.getCode().compare(b.getCode())>0)return true;
// return false;
// }
// } cmpCode;
bool cmpCity(cityPhone a, cityPhone b) // i'm using these 2 in the sorting method
{
if (a.getCity().compare(b.getCity())>0)return true;
return false;
}
bool cmpCode(cityPhone a, cityPhone b)
{
if (a.getCode().compare(b.getCode())>0)return true;
return false;
}
class phoneDirectory {
private :
vector<cityPhone> data;
public:
phoneDirectory (string path){
read(path);
}
phoneDirectory (){
data=vector<cityPhone>();
}
void read(string path){
cout<<endl;
try {
string line;
ifstream myfile (path);
cityPhone bla = cityPhone();
if (myfile.is_open())
{
while ( getline (myfile,line) )
{
try{
bla = cityPhone(line.substr(0,line.find_first_of(" ")),line.substr(line.find_first_of(" ")+1));
data.push_back(bla);
}
catch(exception){ }
}
myfile.close();
}
else cout << "Unable to open file";
} catch (exception) {}
}
void addCityPhone(string city,string phone){
try{
data.push_back(cityPhone(city,phone));
}
catch(exception){
cout<<"Error adding item "<<endl;
}
}
void delCityPhone(int index){
try{
vector<cityPhone>::iterator p=data.begin();
p+=index;
data.erase(p);
}
catch(exception){
cout<<"Error deleting item with index "+index<<endl;
}
}
cityPhone getCityPhone(unsigned index){
try{
vector<cityPhone>::iterator p=data.begin();
p+=index;
return *p;
}
catch(exception){
cout<<"Error deleting item with index "+index<<endl;
return cityPhone();
}
}
vector<cityPhone> getData(){
return data;
}
void phoneChange(string city, string newPhone){
try{
int i=0;
vector<cityPhone>::iterator p=data.begin();
for(p=data.begin();p<data.end();p++,i++){
if (getCityPhone(i).getCity().compare(city)==0){
string oldPhone = getCityPhone(i).getCode();
getCityPhone(i).setCode(newPhone);
cout<<"Phone of city "+city + " was changed from "+oldPhone + " to " + newPhone<<endl;
return;
}
cout<<"No such city exists!\n";
}
}
catch(exception){
cout<<"Error changing phone"<<endl;
}
}
friend istream& operator>>(ostream& out,phoneDirectory a);
friend ostream& operator<<(ostream& out,phoneDirectory a);
};
istream& operator>>(istream& in,phoneDirectory& a){
string city,phone;
in >> city >> phone;
a.addCityPhone(city,phone);
return in;
}
ostream& operator<<(ostream &out, cityPhone a){
return out << a.getCity() <<" " << a.getCode() <<endl;
}
void sortByCity(phoneDirectory a){//with these two i try to sort
vector<cityPhone>::iterator p=a.getData().begin();
vector<cityPhone>::iterator q=a.getData().end();
std::sort(p,a.getData().end(),cmpCity);
}
void sortByCode(phoneDirectory a){
vector<cityPhone>::iterator p=a.getData().begin();
vector<cityPhone>::iterator q=a.getData().end();
std::sort(p,q,cmpCode);//i've tried with std::sort(a.getData().begin(),a.getData().end(),cmpCode) still no effect
}
//bool wayToSortCity (cityPhone a, cityPhone b){ //i've tryed also with these , still no effect
//if (a.getCity().compare(b.getCity())>0)return true;
//return false;
//}
// bool wayToSortCode (cityPhone a, cityPhone b){
//if (a.getCode().compare(b.getCode())>0)return true;
//return false;
//}
int main()
{
phoneDirectory test("C:\\t.txt");
sortByCity(test);//here it crashes
for(unsigned i=0;i<test.getData().size();i++)
cout<<test.getCityPhone(i);
cin>>test;
//test.sortBy(1);
system("pause");
return 0;
}
The problem is that phoneDirectory::getData returns a copy of the data member, so each iterator "belongs to" a different vector.
You need it to return the actual member, not a copy of it.
const vector<cityPhone>& getData() const
{
return data;
}
You have
void sortByCity(phoneDirectory a){//with these two i try to sort
vector<cityPhone>::iterator p=a.getData().begin();
vector<cityPhone>::iterator q=a.getData().end();
std::sort(p,a.getData().end(),cmpCity);
}
Problems with that function:
a.getData() returns a copy of the private data by value. Hence, p and q are iterators on different vectors. Comparing them leads to undefined behavior. You are not comparing p with q but you are comparing p with getData().end(), which is essentially the same thing.
Since the return value is a copy of the member data of a, these are temporary objects. The objects get destructed after the execution of the lines. p and q are the equivalent of dangling pointers.
The argument to the function is an object. After the above errors are fixed, you'll end of sorting a copy of the argument used to call the function. In the calling function, you still won't notice any difference.
The function sortByCode suffers from the same errors.
How to fix the problems
Change the argument type of the function to a reference.
void sortByCity(phoneDirectory& a){
With that change, you will notice any changes to the object in the calling function.
Change the return value of phoneDirectory::getData() to a reference.
vector<cityPhone>& getData(){
return data;
}
That will not only fix all the errors but it will also sort the contents a and not a copy of the contents of a.
Related
I'm trying to implement a LinkedQueue Structure in c++ to store the data of some flights.
So, first of all I have to read a csv file, what provides the data to store.
The LinkedQueue must work this way: the atributes of each Flight has to be stored using the Flight class, and then the LinkedQueue must have a specific nodes called FlightNode to finally store flights.
My code isn't compiling because i can't implement the getNext() function in a correct way.
I'm giving my code below with the implementation of each class. If you guys can make any suggestion it will be very helpfull.
Thank you a lot!!
This is my header class for Flight.h:
class Flight {
public:
Flight();
virtual ~Flight();
string getID();
void setID(string new_id);
string getOrigen();
void setOrigen(string new_origen);
string getDesti();
void setDesti(string new_desti);
string getHora();
void setHora(string new_hora);
private:
string id;
string origen;
string desti;
string hora_sortida;
};
Flight.cpp:
Flight::Flight() {
}
Flight::~Flight() {
}
string Flight::getID(){
return id;
}
string Flight::getOrigen(){
return origen;
}
string Flight::getDesti(){
return desti;
}
string Flight::getHora(){
return hora_sortida;
}
void Flight::setID(string new_id){
id = new_id;
}
void Flight::setOrigen(string new_origen){
origen = new_origen;
}
void Flight::setDesti(string new_desti){
desti = new_desti;
}
void Flight::setHora(string new_hora){
hora_sortida = new_hora;
}
FlightNode.h:
class FlightNode {
public:
FlightNode(Flight& f);
FlightNode(const FlightNode& orig);
virtual ~FlightNode();
FlightNode* getNext();
void setNext(FlightNode* n);
Flight& getElement();
private:
Flight* _element;
FlightNode* _next;
};
FlightNode.cpp:
FlightNode::FlightNode(Flight& f) {
this->_element = &f;
this->_next = nullptr;
}
FlightNode::FlightNode(const FlightNode& orig) {
}
FlightNode::~FlightNode() {
}
FlightNode* FlightNode::getNext(){
return this->_next;
}
void FlightNode::setNext(FlightNode* n){
this->_next = n;
}
Flight& FlightNode::getElement(){
//Don't know how to implement this one, because I declared _element as a pointer but what I need here is to return a reference.
}
main.cpp:
string id;
string origen;
string desti;
string hora;
fstream fin;
fin.open("flights.csv", ios::in);
string line, word;
string id, origen, desti, hora;
while (getline(fin, line)) {
stringstream in(line);
Flight* new_flight = new Flight;
for (int i = 0; getline(in, word, ','); ++i) {
switch (i) {
case 0:
new_flight->setID(word);
break;
case 1:
new_flight->setOrigen(word);
break;
case 2:
new_flight->setDesti(word);
break;
case 3:
new_flight->setHora(word);
break;
}
}
cout << "id:" << new_flight->getID() << " origen:" << new_flight->getOrigen() << " desti: " << new_flight->getDesti() << endl;
queue.enqueue(*new_flight);
}
You can just return the reference behind the pointer:
return *_element;
However, if you plan to do so please ensure that the pointer is not null at the time of the above dereference.
I created a program that use a dynamic array. It works, when i use my insert function and then i show the elements of the arrays, it show me all what i want. The problem is that at the end of the program it doesn't return with value 0, but it is blocked for a few second and say "Process exited with value 3221225477". What is wrong?
header:
#ifndef VETTORE_H
#define VETTORE_H
#include "regalo.h"
typedef regalo T;
class vettore {
friend ostream& operator<<(ostream&,const vettore&);
friend istream& operator>>(istream&,vettore&);
private:
T *v;
int riemp;
int max;
public:
vettore();
vettore(const int);
~vettore(){delete [] v;};
bool full(){return riemp==max;};
bool empty()const;
bool inserisci(const T&);
T& operator[](const int index);
};
#endif
cpp file:
#include "vettore.h"
ostream &operator<<(ostream& out,const vettore & v1){
for(int i=0;i<v1.riemp;i++){
out<<v1.v[i];
}
return out;
}
istream &operator>>(istream& in,vettore &v1){
for(int i=0;i<v1.riemp;i++){
in>>v1.v[i];
}
return in;
}
vettore::vettore(){
riemp=0;
max=10;
v=new T[max];
}
vettore::vettore(const int n):max(n),riemp(0){
v=new T[max];
}
bool vettore::empty()const{
if(riemp==0){
return true;
}else return false;
}
bool vettore::inserisci(const T& n){
if(max==0){
cout<<"Inserisci il massimo di elementi del vettore: ";
cin>>max;
}
if(!full()){
v[riemp]=n;
riemp++;
return true;
}else return false;
}
T& vettore::operator[](const int index){
return v[index];
}
main file:
#include "vettore.h"
int main(int argc, char** argv) {
int riempimento;
vettore vett(1);
regalo r1("Alex",300,"quadrato");
vett.inserisci(r1);
cout<<"Gli elementi del vettore sono: \n";
for(int i=0;i<riempimento;i++){
cout<<vett[i]<<endl;
}
system("PAUSE");
return 0;
}
There are a few issues in your code:
riempimento is not initialised so the for loop in main will perform an unknown number of iterations, likely more than the size of your vector. It would be better to expose the value of riemp from inside the vector and use that in the loop instead.
You need to implement the rule of three, this isn't causing you a problem yet but will in the future if you copy your vettore objects.
If max is 0 when you call inserisci you prompt the user for a value of max, you don't check that cin succeeds and you don't reallocate v to be large enough to contain max elements.
Not a problem but empty could simply be implemented as:
bool vettore::empty()const{
return riemp==0;
}
I have class Pstring
class Pstring
{
private:
string palindrome;
public:
Pstring() { palindrome = ""; }
Pstring(string pal) { setString(pal); }
void setString(string pal) { palindrome = pal; }
string getPal() const { return palindrome; }
};
an object in my main method Pstring palindrome(palin) defined by
string palin = "";
cout << "Enter a palindrome:\n";
getline(cin, palin);
Pstring palindrome(palin);
and a current test method bool isPalindrome(string pal)defined as
bool isPalindrome(string pal)
{
bool flag;
cout << "Do I have access to this?";
cout << pal;
//code goes here to check for palindrome, return bool
}
I want to have my Pstring class object palindrome use the method isPalindrome in main, but when I try and invoke the method by using palindrome.isPalinedrome(palin); it doesn't seem to have access to the method.
What can I do to allow a method outside the class to be used by a class object in main?
You don't have a isPalinedrome() method defined in the Pstring class, so you can't call it as palindrome.isPalinedrome() in your main code.
Instead of having Pstring try to call a function in your main code, you should move the palindrome logic into Pstring, and then the main code can ask Pstring when needed.
Try this:
class Pstring
{
private:
string value;
public:
Pstring() { }
Pstring(const string &s) { setString(s); }
void setString(const string &s) { value = s; }
string getString() const { return value; }
// add this...
bool isPalindrome() const {
//code goes here to check value for palindrome, return bool
}
};
Then your main code can do this:
bool isPalindrome(const string &value)
{
Pstring palindrome(value);
return palindrome.isPalindrome();
// or simply:
// return Pstring(value).isPalindrome();
}
int main()
{
string palin;
cout << "Enter a palindrome:\n";
getline(cin, palin);
if (isPalindrome(palin)) {
// do something ...
} else {
// do something else...
}
return 0;
}
Or this:
int main()
{
string palin;
cout << "Enter a palindrome:\n";
getline(cin, palin);
Pstring palindrome(palin);
if (palindrome.isPalindrome()) {
// do something ...
} else {
// do something else...
}
return 0;
}
You should add your test method into the class:
class Pstring
{
private:
string palindrome;
public:
// you don't need to initialize palindrome = "" (it's initialized by default)
Pstring() {}
// always pass strings as const reference unless you have
// special reason to do it another way...
Pstring(const string& pal) { setString(pal); }
void setString(const string& pal) { palindrome = pal; }
string getPal() const { return palindrome; }
bool isPalindrome() const // you don't have to pass string
{
bool flag;
cout << "Do I have access to this?";
cout << palindrome; // please note this
//code goes here to check for palindrome, return bool
}
};
And also please note the typo:
palindrome.isPalinedrome(palin);
You can use function pointer to implement it:
declare class:
class Pstring{
private:
string palindrome;
public:
Pstring() { palindrome = ""; }
Pstring(string pal) { setString(pal); }
void setString(string pal) { palindrome = pal; }
string getPal() const { return palindrome; }
//add a function pointer member:
bool(*isPalindrome) (string);
};
then define function:
bool isPalindrome(string pal)
{
bool flag;
cout << "Do I have access to this?";
cout << pal;
//code goes here to check for palindrome, return bool
return true;
}
now you can write code in main function:
string palin = "";
cout << "Enter a palindrome:\n";
getline(cin, palin);
Pstring palindrome(palin);
palindrome.isPalindrome = isPalindrome;//bind function
you can use the function by the object now:
palindrome.isPalindrome(palin);
Sorry. what's the point to create this class? the only thing you need is the helper function isPalindrome(const std::string&). If you need some kinda scope protection, put it into a namespace may look better
Sorry but I have to say you are just make things complicated.
C++ is not java. If you don't use it, you should not pay for it.
I am trying string comparision using operator overloading i am using > operator , i am not getting the correct output, can you tell me what mistake i am doing here is my code
#include<iostream.h>
#include<stdio.h>
#include<string.h>
#include<conio.h>
class strclass
{
public:
char s1[20];
void getdata()
{
cin>>s1;
}
void showdata()
{
cout<<s1;
}
int operator>(strclass obj)
{
int temp,temp1;
temp=strlen(s1);
temp1=strlen(obj.s1);
if(temp>temp1)
{
return 1;
}
else
return 0;
}
};
void main()
{
clrscr();
strclass obj1,obj2;
int temp3;
if(obj1>obj2)
{
cout<<"string 1 is greater";
}
else
{
cout<<"string 2 is greater";
}
cout<<"enter string 1"<<endl;
obj1.getdata();
// obj1.showdata();
cout<<"enter string 2"<<endl;
obj2.getdata();
// obj2.showdata();
getch();
}
I am using basic library functions. Thanks!
You need to put the data before comparing the strings
The operator should return an int
For your class, with a public s1 member, you should use a free function for the comparison operator, which increases encapsulation, of the form bool operator<(strclass s1, strclass s2) instead of a member function
in my school assignment i need a small help
this is my header file:
#include <iostream>
#include <cstring>
using namespace std;
#include "ISBNPrefix.h"
class ISBN
{
char str[11];
char area[6];
char publisher[8];
char title[7];
bool registered;
public:
ISBN();
ISBN(const char*,ISBNPrefix &);
void toStr(char*)const;
void toStrWithStyle(char*)const;
bool empty()const;
bool isRegistered() const;
bool read(istream& is, const ISBNPrefix& list);
void display(ostream&) const;
};
int isValid(const char* str);
and this is the implementation of my file:
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include <iomanip>
using namespace std;
#include "ISBN.h"
ISBN::ISBN()
{
str[0]='\0';
area[0]='\0';
publisher[0]='\0';
title[0]='\0';
registered=false;
}
ISBN::ISBN(const char* s,ISBNPrefix& p)
{
if(isValid(s)==1)
{
strcpy_s(str,s);
}
else
{
*this=ISBN();
}
}
bool ISBN::empty()const
{
bool chk=false;
if(str[0]=='\0')
chk=true;
return chk;
}
void ISBN::toStrWithStyle(char* s) const
{
if(registered)
{
sprintf(s,"%s-%s-%s-%c",area,publisher,title,str[9]);
}
else
{
toStr(s);
}
}
void ISBN::toStr(char* s) const
{
if (str[0]!='\0')
strcpy(s,str);
else
strcpy(s,"no data");
}
void ISBN::display(ostream & os) const
{
char str[14];
toStrWithStyle(str);
cout<< setw (13) <<str;
}
int isValid(const char* str)
{
int rc=0;
if(str!=0)
{
int sum,i=0;
sum=0;
for(i=0;i<10;i++)
sum+=(str[i]-'0')*(10-i);
if(sum%11==0)
{
rc= 1;
}
}
else
rc=0;
return rc;
}
bool ISBN::read(istream& is, const ISBNPrefix& list)
{
char str[11];
bool quit=false;
bool ok=false;
char lists;
do{
cout<<"ISBN (0 to quit) : ";
is.getline(str,11); //or is.get(str,11)
if(strcmp(str,"0")==0)
quit=true;
else if (isValid(str)==1)
{
*this=ISBN(str,list);
ok=true;
cout<<"isbn is valid"<<endl;
}
else
{
*this=ISBN();
cout<<"invalid ISBN"<<endl;
}
} while(!quit&&!ok);
return !quit;
}
in the ISBN::read where I say
*this=ISBN(str,list);
i want to overload another member but i can't.
can anyone tell me how can i do that?
First I would suggest use std::string in favour of char[]. It will save a lot of trouble. For reading ISBN I would write something like this:
bool ISBN::read(istream& is)
{
ISBN result;
// reading into result
std::swap(*this,result);
return !quit;
}
Or even better (as a non member function):
std::istream& operator>>(istream& is, ISBN& obj)
{
ISBN result;
// reading into result
is(!quit)
is.clear(std::ios_base::failbit);
std::swap(obj,result);
return is;
}
In any way you should RAII classes for your resources. In your special case std::string instead of char[].