I want to print the most visited sites/urls in the browser - c++

Below is the code that I have written in C++ and it is printing the wrong result for the 2nd and 3rd output line. I am not able to figure it out why it is happening.
Below is the code which I have written and it is a completely functional code on visual studio. This code expects the one input file named urlMgr.txt whose content should be URLs. Below is the sample URLs which I am using it.
web.whatsapp.com
web.whatsapp.com
cplusplus.com/reference/algorithm/find_if
stackoverflow.com/questions/760221/breaking-in-stdfor-each-loop
mail.google.com/mail/u/0/#inbox
http://stackoverflow.com/questions/18085331/recursive-lambda-functions-in-c14
mail.google.com/mail/u/0/#inbox
en.cppreference.com/w/cpp/language/lambda
https://www.google.co.in/?ion=1&espv=2#q=invariant%20meaning
mail.google.com/mail/u/0/#inbox
http://stackoverflow.com/questions/11699083/where-can-i-find-all-the-exception-guarantees-for-the-standard-containers-and-al
https://www.google.co.in/?ion=1&espv=2#q=array+of+references:quora&start=10
mail.google.com/mail/u/0/#inbox
web.whatsapp.com
quora.com/Whats-the-purpose-of-load-factor-in-hash-tables
https://www.quora.com/Whats-the-difference-between-the-rehash-and-reserve- methods-of-the-C++-unordered_map cplusplus.com/reference/unordered_map/unordered_map/load_factor
cplusplus.com/max_load_factor
cplusplus.com/max_load_factor
cplusplus.com/max_load_factor
cplusplus.com/max_load_factor
cplusplus.com/max_load_factor
cplusplus.com/max_load_factor
cplusplus.com/max_load_factor
cplusplus.com/max_load_factor
Code is also pasted below.
#include <iostream>
#include <string>
#include <unordered_set>
#include <algorithm>
#include <fstream>
#include <sstream>
#include <functional>
#include <unordered_map>
#include <queue>
using namespace std;
class urlInfo
{
public:
urlInfo(string &url):urlName(url),hitCount(1)
{
}
int getHitCount() const
{
return hitCount;
}
string getURL()
{
return urlName;
}
string getURL() const
{
return urlName;
}
void updateHitCount()
{
hitCount++;
}
void setHitCount(int count)
{
hitCount = count;
}
private:
string urlName;
int hitCount;
};
class urlInfoMaxHeap
{
public:
bool operator() (urlInfo *url1, urlInfo *url2) const
{
if(url2->getHitCount() > url1->getHitCount())
return true;
else
return false;
}
};
bool operator==(const urlInfo &ui1,const urlInfo& ui2)
{
//return (ui1.getURL().compare(ui2.getURL()) == 0) ? 1:0;
return (ui1.getURL() == ui2.getURL());
}
namespace std
{
template <> struct hash<urlInfo>
{
size_t operator()(urlInfo const & ui)
{
return hash<string>()(ui.getURL());
}
};
}
class urlMgr
{
public:
urlMgr(string &fileName)
{
ifstream rdStr;
string str;
rdStr.open(fileName.c_str(),ios::in);
if(rdStr.is_open())
{
int len;
rdStr.seekg(0,ios::end);
len = rdStr.tellg();
rdStr.seekg(0,ios::beg);
str.reserve(len+1);
char *buff = new char[len +1];
memset(buff,0,len+1);
rdStr.read(buff,len);
rdStr.close();
str.assign(buff);
delete [] buff;
}
stringstream ss(str);
string token;
while(getline(ss,token,'\n'))
{
//cout<<endl<<token;
addUrl(token);
}
}
void addUrl(string &url)
{
unordered_map<string,urlInfo*>::iterator itr;
itr = urls.find(url);
if(itr == urls.end())
{
urlInfo *u = new urlInfo(url);
urls[url] = u;
maxHeap.push_back(u);
}
else
{
itr->second->updateHitCount();
urlInfo* u = itr->second;
vector<urlInfo*>::iterator vItr;
vItr = find(maxHeap.begin(),maxHeap.end(),u);
if(vItr!=maxHeap.end())
{
maxHeap.erase(vItr);
maxHeap.push_back(u);
}
}
make_heap(maxHeap.begin(),maxHeap.end(),urlInfoMaxHeap());
}
void releaseResources()
{
for_each(urls.begin(),urls.end(),[](pair<string,urlInfo*> p){
urlInfo* u = p.second;
delete u;
});
}
void printHeap()
{
for_each(maxHeap.begin(),maxHeap.end(),[](urlInfo* u){
cout<<endl<<u->getHitCount()<<" "<<u->getURL();
});
}
private:
unordered_map<string,urlInfo*> urls;
vector<urlInfo*> maxHeap;
};
int main()
{
string fileName("urlMgr.txt");
urlMgr um(fileName);
um.printHeap();
um.releaseResources();
cout<<endl<<"Successfully inserted the data"<<endl;
}
The output i am getting is
8 cplusplus.com/max_load_factor
3 web.whatsapp.com
4 mail.google.com/mail/u/0/#inbox
1 en.cppreference.com/w/cpp/language/lambda
1 other url's and so on. //all other url's show count as 1.
What i expect is
8 cplusplus.com/max_load_factor
4 mail.google.com/mail/u/0/#inbox
3 web.whatsapp.com
1 en.cppreference.com/w/cpp/language/lambda
1 other url's and so on. //all other url's show count as 1.

Finally after some debugging i have found the problem.The problem is in the way you are interpreting how max_heap() works.
Consider this.
url1 occurs 8 times
url2 occurs 4 times
url3 occurs 3 times
After a call to max_heap() what you will get is
maxHeap[0]=8 8
maxHeap[1]=4 4 3
maxHeap[2]=3
Or you can also get
maxHeap[0]=8 8
maxHeap[1]=3 3 4
maxHeap[2]=4
Both of the above are maxHeaps but you are considering that only the first heap can occur and so in the below code you are just printing maxHeap content without realizing that you may be printing second heap.
void printHeap()
{
for_each(maxHeap.begin(),maxHeap.end(),[](urlInfo* u){
cout<<endl<<u->getHitCount()<<" "<<u->getURL();
});
}
To resolve this.One way is to after picking up maxHeap[0] .You delete first element and again call max_heap before picking up maxHeap[0] again.Or you can also have something like below.
while(maxHeap.size()>0){
cout<<(*maxHeap.begin())->getHitCount()<<" "<<(*maxHeap.begin())->getURL()<<endl;
std::pop_heap(maxHeap.begin(),maxHeap.end(),urlInfoMaxHeap());maxHeap.pop_back();}
In the above code pop_heap() will move the topmost element(which has the highest priority according to your implementation of compare function which you pass to make_heap()) to the end and heapify again. You can then delete the last element then.
Also i did not find the use of the below in your code
vector<urlInfo*>::iterator vItr;
vItr = find(maxHeap.begin(),maxHeap.end(),u);
if(vItr!=maxHeap.end())
{
maxHeap.erase(vItr);
maxHeap.push_back(u);
}

Related

How do I access elements of multiset within a vector in the format "vector<multiset<char> vp;"?

I am creating a program that receives a value in multiset in the form of vector<multisetvp; and stores it in multiset inside the vector when the number of it becomes five. If you store values from 1 to 10, when you print out vector,
1 2 3 4 5
6 7 8 9 10
I want it to come out like this.
However, it is difficult to output the value stored in multiset inside the vector. Ask for help in how to solve this problem.
I also tried to output the value of 'sp' using overlapping 'range-based for statements', but it ended up outputting only one multiset of vector. I want to store and output multisets with up to five elements in the vector.
#include <iostream>
#include <set>
#include <vector>
#include <array>
using namespace std;
class MyCharector {
vector<multiset<char>> vp;
vector<multiset<char>>::iterator vit;
multiset<char>* sp;
multiset<char>::iterator sit;
public:
~MyCharector() { }
void ininven(multiset<char> s) {
vp.push_back(s);
}
void getItem(char* item) {
sp = new multiset<char>;
for (int i = 0; i < 10; i++) {
sp->insert(item[i]);
if (sp->size() == 5) {
ininven(*sp);
}
}
delete sp;
}
void dropItem() { // is not use
vit = vp.begin();
vit = vp.erase(vit);
}
void showItem() {
for (vit = vp.begin(); vit != vp.end(); vit++) {
// problems.....
}
}
};
int main(int argc, const char* argv[]) {
MyCharector my;
array<char,10> item = { 'a','a','e','d','g','f','c','c','h','b' };
my.getItem(item.data());
my.showItem();
return 0;
}
Of course you can make it work with iterators but what's wrong with simple range based loops?
for (const auto& ms : vp)
for (char c : ms)
cout << c;
Also why use new and delete in getItem? And why declare class variables when you should use local variables?
void getItem(char* item) {
multiset<char> sp;
for (int i = 0; i < 10; i++) {
sp.insert(item[i]);
if (sp.size() == 5) {
ininven(sp);
}
}
}
sp doesn't need to be a pointer, and it should be a local variable.
EDIT
Also I think getItem has a bug. I'm guessing that you want a new multiset every five character, but that's not what the code does. Maybe this is what you want
void getItem(char* item) {
multiset<char> sp;
for (int i = 0; i < 10; i++) {
sp.insert(item[i]);
if (sp.size() == 5) {
ininven(sp);
sp.clear(); // start again
}
}
}

Member function doesn't work when using pointer to class

Scenario: I have two classes, each contains a pointer to the other (when using them, being able to refer to the other is going to be important so I deemed this appropriate). When I try accessing a private variable from one class via using the pointer to the other and a getter function inside that, it works perfectly.
Problem: Using a setter (in this case, addPoints)/manipulating the variables however leads to no result.
I'm new so anything here might be "improper etiquette" and bad practice. Feel free to point them out! But please also try to provide a solution. This is also my first question on SO, so please be gentle!
Related code pieces:
Team.h
#include "Driver.h"
using namespace std;
class Team {
int Points = 0;
vector<Driver*> Drivers;
public:
void addPoints(int gained); //does not work
int getPoints(); //works perfectly
Driver getDriver(int nr);
void setInstance(vector<Driver*> drivers);
};
Team.cpp
#include "Team.h"
#include "Driver.h"
using namespace std;
void Team::addPoints(int gained) {
this->Points = this->Points + gained;
}
int Team::getPoints() {
return this->Points;
}
Driver Team::getDriver(int nr) {
return *Drivers[nr];
}
void Team::setInstance(vector<Driver*> drivers) {
this->Drivers = drivers;
}
Driver.h
using namespace std;
class Team;
class Driver {
int Points = 0;
Team* DriversTeam;
public:
void SetTeam(Team& team);
Team getTeam();
int getPoints(); //works
void addPoints(int gained); //doesn't work
};
Driver.cpp
#include "Driver.h"
#include "Team.h"
using namespace std;
void Driver::SetTeam(::Team& team) {
this->DriversTeam = &team;
}
Team Driver::getTeam() {
return *DriversTeam;
}
int Driver::getPoints() {
return this->Points;
}
void Driver::addPoints(int gained) {
this->Points = this->Points + gained;
}
Initializer.cpp (linking drivers to teams)
void InitializeData(vector<Team>& teams, vector<Driver> &drivers) {
//(...)
//reads each team in from data file to memory
//key part:
vector<Driver*> teamsDrivers;
for (auto& iter : drivers) { //this loop mainly determines which driver to link with which teams
if (iter.getName().compare(values[4]) == 0) { //values is csv line data in a string vector. I guess not the prettiest parsing method here but will be revised
teamsDrivers.push_back(&iter);
}else if(iter.getName().compare(values[5]) == 0) {
teamsDrivers.push_back(&iter);
}
}
tempTeam.setInstance(teamsDrivers);
teams.push_back(tempTeam);
}
(linking driver to team)
//drivers are linked to teams last, as they are declared first (so I cannot link them to the yet nonexisting teams)
void LinkTeam(vector<Driver>& drivers, vector<Team>& teams) {
for (auto& driverIter : drivers) { //iterate through drivers
for (auto& teamIter : teams) { // iterate through teams
bool found = 0;
for (size_t i = 0; i < teamIter.DriverAmount(); i++) {
if (driverIter.getName() == teamIter.getDriver(i).getName()) {
driverIter.SetTeam(teamIter);
found = 1;
break;
}
}
if (found) { //exit iterating if driver is found
break;
}
}
}
}
Example of use in main.cpp
teams[0].addPoints(10);
drivers[3].getTeam().addPoints(15); //driver 3 is linked to team 0
cout << teams[0].getPoints(); //15
cout << drivers[3].getTeam().getPoints(); //15
teams[0].getDriver(1).addPoints(20); //driver 1 of team 0=driver[3]
drivers[3].addPoints(25);
cout << drivers[3].getPoints(); //25
cout << teams[0].getDriver(1).getPoints(); //25
Thanks for the help in advance.
This is quite simple:
Your getTeam() and getDriver() functions are returning copies of the objects, not references, so the addPoints() are performed on temporary copies and not the real ones.
To fix it, simply change the return types to references (add &):
Team& getTeam();
and
Driver& getDriver();

C++ - one function makes others malfunction

Here is my task:
Write class Word which has:
pointer on array of characters
constructors and destructors
function to read word
function to check if character which is passed to it as argument occurs in word and return position of occurance
function to check which of two words has more occurances of number 10 and to return that number of occurances
Here is my solution. I compiled it without errors but it doesn't work as it shoud.
#include <iostream>
#include <string.h>
using namespace std;
class Word
{
private:
char *content;
int length;
public:
Word();
Word(char *);
~Word();
void print_content(void);
int check_character(char);
friend int check_number(Word,Word);
};
Word::Word()
{
}
Word::Word(char *n)
{
length=strlen(n);
content=new char [length];
for(int i=0;i<length;i++)
{
content[i]=n[i];
}
}
Word::~Word()
{
delete content;
}
void Word::print_content(void)
{
for(int i=0;i<length;i++)
{
cout<<""<<content[i];
}
}
int Word::check_character(char a)
{
int position=0;
for(int i=0;i<length;i++)
{
if(content[i]==a)
{
position=i+1;
}
}
if(position>0)
{
return position;
}
else return 0;
}
int check_number(Word n,Word m)
{
int counter_n=0;
int counter_m=0;
for(int i=1;i<n.length;i++)
{
if((n.content[i-1]=='1')&&(n.content[i]=='0'))
{
counter_n=counter_n+1;
}
}
for(int i=1;i<m.length;i++)
{
if((m.content[i-1]=='1')&&(m.content[i]=='0'))
{
counter_m=counter_m+1;
}
}
if(counter_n>counter_m)
{
return counter_n;
}
else if(counter_n<counter_m)
{
return counter_m;
}
else return 0;
}
int main()
{
char characters1[]="qwerty10",*p1,*p2;
char characters2[]="stackoverflow101010";
p1=characters1;
p2=characters2;
Word first(p1);
Word second(p2);
cout<<""<<first.check_character('q')<<endl;
cout<<""<<second.check_character('f')<<endl;
//cout<<""<<check_number(first,second)<<endl;
first.print_content();
second.print_content();
}
Function check_number(first,second) for some reason makes other functions to work incorrectly, if you call it by removing "//" you will see that first.print_content() and second.print_content() don't give us correct result. Or if function first.check_character('r') is first called, second.check_character('j') second called and then check_number(first,second), then two firsly called functions don't work.
What's reason for this strange behaviour?
Word objects are passed by copy to check_number, but you did not define the copy constructor. So default one is used by the compiler and this one copies pointer (char* content). Temporary objects passed to the function are pointing to data created first and second in the main function...upon deletion (temprary objects are deleted after the function is called), they delete the pointers, so first and second objects are pointing to deleted memory. You have undetermined behaviour here, this explains side effects you experienced.
Passing objects by reference to check_number is an easy way to fix your problem. Here is a working code (including many fixes because you did not access arrays correctly):
#include <iostream>
using namespace std;
#include <iostream>
#include <string.h>
using namespace std;
class Word
{
private:
char *content;
int length;
public:
Word();
Word(char *);
~Word();
void print_content(void);
int check_character(char);
friend int check_number(const Word&,const Word&); // changed here
};
Word::Word()
{
}
Word::Word(char *n)
{
length=strlen(n);
content=new char [length];
for(int i=0;i<length;i++)
{
content[i]=n[i]; // changed here
}
}
Word::~Word()
{
delete [] content; // changed here
}
void Word::print_content(void)
{
for(int i=0;i<length;i++)
{
cout<<""<<content[i]; // changed here
}
}
int Word::check_character(char a)
{
int position=0;
for(int i=0;i<length;i++)
{
if(content[i]==a) // changed here
{
position=i+1;
}
}
if(position>0)
{
return position;
}
else return 0;
}
int check_number( const Word& n, const Word& m)// changed here
{
int counter_n=0;
int counter_m=0;
for(int i=1;i<n.length;i++)
{
if((n.content[i-1]=='1')&&(n.content[i]=='0')) // changed here
{
counter_n=counter_n+1;
}
}
for(int i=1;i<m.length;i++)
{
if((m.content[i-1]=='1')&&(m.content[i]=='0')) // changed here
{
counter_m=counter_m+1;
}
}
if(counter_n>counter_m)
{
return counter_n;
}
else if(counter_n<counter_m)
{
return counter_m;
}
else return 0;
}
int main()
{
char characters1[]="qwerty10",*p1,*p2;
char characters2[]="stackoverflow101010";
p1=characters1;
p2=characters2;
Word first(p1);
Word second(p2);
cout<<""<<first.check_character('q')<<endl;
cout<<""<<second.check_character('f')<<endl;
cout<<""<<check_number(first,second)<<endl;
first.print_content();
second.print_content();
}
This outputs:
1
10
3
qwerty10stackoverflow101010
Declaring a copy constructor is another way to fix the problem:
Word( const Wodr& word ) :
length( word.length ),
content( new char[word.length] )
{
memcpy( content, word.content, word.length );
}
That would be less efficient than passing objects by const reference, but would make your code safer (it's good to always declare copy constructor to prevent bug you experienced here).
Finally, if you are lazy, you can also declare the copy constructor as private, to prevent compiler to copy objects, just declare it, don't impelment it:
class Word
{
....
private:
Word( const Word& word ); // this makes argument passed by copy impossible.
};
Then, compiler will not let you call check_number.

Vector losing contents between files in C++

I have some methods in lexer.h which make use of a Vector made of Tokens.
In this method void getNextToken() I am making use of the said vector where I am adding new tokens to it.
The problem is, that when I go to a different file, I am trying to access ANOTHER method which makes use of this vector, but it is crashing with an out of bounds error (most probably it's being deferenced or something)
Is there a way how I can fix this?
The methods in concern are:
Token* nextToken()
{
if (it!= tokensUsed.end())
{
// we Assigned what is found in the iterator it (of the vector)
// so we get the data found in that pointer
itrToken = &*it;
//Move Iterator forward
it ++;
return itrToken;
}
}
/*
Used in Parser to go get the PREVIOUS Tokens
*/
Token* prevToken()
{
itrToken --;
if (it!= tokensUsed.begin())
{
itrToken = &*this->it;
return itrToken;
}
}
void getNextToken()
{
//CODE ADDING TOKENS
//EXAMPLE
if (ch == '"')
{
addAndGetNext(ch);
cout << "STRING: " << strBuffer << endl; //TEST
//create new token and push it into the vector
tk = new Token (Token::ttString, strBuffer, row, col);
tokensUsed.push_back(*tk); //Add the new token to the Vector
startNewString(); //Clear the string
}
tokenMatch = true;
}
The above is just partial code, to show an example.
Now in Parser.h I am using this method to call the lexer.h:
void relOpP()
{
Token* tk = nextToken();
if (tk -> getType() == Token::ttString)
{
cout << "Ture";
}
}
which calls the Lexer's nextToken() it crashes, and when I tried checking it's contents it goes outofBounds error (and CodeBlocks giving me a SIGSEGV error)
I know it's something from the pointers that it's going awry, but how can I fix it?
Edit:
These are the global variables I have declared:
vector<Token>::iterator it;
vector<Token> tokensUsed;
Token* itrToken; // used for iterator
bool checkQuote = false;
Token* tk = new Token (syNewToken, "", 1,0);
Token token; // Creates an instance of the class Token found in the file token.h
Token* t;
SAMPLE CODE:
main.cpp
#include <iostream>
#include "lexer.h"
#include "parser.h"
using namespace std;
int main()
{
Lexer* l;
l -> getNextToken();
Parser p(l);
p.relOpP();
}
Token (int type, string sBuffer, int rRow, int cCol)
{
this->tType = type;
this->strBuffer = sBuffer;
this->row = rRow;
this->col = cCol;
}
parser.h
#ifndef PARSER_H_INCLUDED
#define PARSER_H_INCLUDED
#include <string>
#include <vector>
#include "lexer.h"
#include "token.h"
using namespace std;
class Parser{
private:
Lexer* lexer;
string tree = "";
public:
Parser (Lexer* l)
{
this -> lexer = l;
}
Token nextToken()
{
Token tk = lexer -> nextToken();
return tk;
}
void relOpP()
{
Token tk = nextToken();
if (tk.getType() == 1)
{
cout << "Ture";
}
}
#endif // PARSER_H_INCLUDED
};
token.h
#ifndef TOKEN_H_INCLUDED
#define TOKEN_H_INCLUDED
#include <iostream>
using namespace std;
class Token
{
private:
int tType; //identifier or reserved by compiler?
string strBuffer; //string found in buffer at that moment
int row;
int col;
public:
enum tokenType
{
tkString
};
Token()
{
}
// The instance of a token with 4 parameters resulting the type, the contents of the string that represents that type
// the row it is found in and the column.
Token (int type, string sBuffer, int rRow, int cCol)
{
this->tType = type;
this->strBuffer = sBuffer;
this->row = rRow;
this->col = cCol;
}
Token (Token* getT)
{
this-> tType = getT -> tType;
this->strBuffer = getT -> strBuffer;
this->row = getT -> row;
this->col = getT -> col;
}
int getType ()
{
return this->tType;
}
//return the string contents
string getBuffer()
{
return this->strBuffer;
}
//return row
int getRow()
{
return row;
}
//return col
int getCol ()
{
return col;
}
};
#endif // TOKEN_H_INCLUDED
Lexer.h
#ifndef LEXER_H_INCLUDED
#define LEXER_H_INCLUDED
#include "token.h"
#include <vector>
using namespace std;
class Lexer
{
private:
Token tk = new Token (1, "", 1,0);
vector<Token>::iterator it;
vector<Token> tokensUsed;
Token itrToken; // used for iterator
public:
Token nextToken()
{
if (it!= tokensUsed.end())
{
// we Assigned what is found in the iterator it (of the vector)
// so we get the data found in that pointer
itrToken = &*it;
//Move Iterator forward
it ++;
return &itrToken;
}
else
{
cout << "ERROR" << endl;
}
return nullptr;
}
void getNextToken()
{
cout << "Test" << endl;
string strBuffer = "test";
int row = 0;
int col = 0;
tk = new Token (1,strBuffer,row,col);
}
};
#endif // LEXER_H_INCLUDED
In nextToken() and prevToken() there is no return for the case the if evaluates to false. The return value in that case is not very likely to be something (it could be anything...) that you can then dereference.
If you want to keep the current design you should return nullptr or (NULL if you don't have C++11 support) in that case. Then you need to change any code that uses the result of those functions to check if the pointer is valid before dereferencing it.
You would probably be better changing your design to not involve so much manual pointer manipulation. But to fix up your current version you should change your prevToken and nextToken to be something along the lines of:
Token* nextToken()
{
if (it!= tokensUsed.end())
{
...
return itrToken;
}
else
{
return nullptr;
}
}
Then if tk is the result of calling one of these functions you must not use tk-> or *tk if it is nullptr. Any code wanting to work with the result will need to check first.
So for example you could change you if statement to be:
if (tk && // Make sure tk is not nullptr
tk -> getType() == Token::ttString)
{
...
There are too many problems with your code for me to address them all in this post. The first, and most obvious one is this.
In the main function:
Lexer* l;
l -> getNextToken();
Here, you did not create a Lexer object. You just created an uninitialized pointer to one. Then you called a member function as if it pointed to an object. This is undefined behavior. You then pass this pointer to your Parser class, which continues to treat it as a valid object, resulting in more undefined behavior.
There are many other problems with your code, but most of them have to do with your mishandling of pointers, indicating a lack of understanding of how they work. The best suggestion for you is to stop using them entirely. There is no reason you need to use any pointers whatsoever to do what you are doing. If you can't figure out how to do what you are trying to do without pointers, it is because of a lack of fundamental understanding of the language. You need to read a C++ book, to completion. Here's a list of some good ones.
The Definitive C++ Book Guide and List

C++ Priority Queue, logical error, can't figure out

I'm implementing a simple priority queue in C++.
However when it runs, it prints out gibberish numbers.
Am I somehow trying to access invalid entries in the array in my code?
Below is the code.
Also, is my "remove" function somehow not doing its job? Conceptually, shall I be putting null into the first entry and return whatever was just erased?
Thanks.
[Priority.h]
#ifndef Priority_h
#define Priority_h
class Priority
{
public:
Priority(void);
Priority(int s);
~Priority(void);
void insert(long value);
long remove();
long peekMin();
bool isEmpty();
bool isFull();
int maxSize;
long queArray [5];
int nItems;
private:
};
#endif
[Priority.cpp]
#include <iostream>
#include <string>
#include <sstream>
#include <stack>
#include "Priority.h"
using namespace std;
Priority::Priority(void)
{
}
Priority::Priority(int s)
{
nItems = 0;
}
Priority::~Priority(void)
{
}
void Priority::insert(long item)
{
int j;
if(nItems==0) // if no items,
{
queArray[0] = item; nItems++;
}// insert at 0
else // if items,
{
for(j=nItems-1; j=0; j--) // start at end,
{
if( item > queArray[j] ) // if new item larger,
queArray[j+1] = queArray[j]; // shift upward
else // if smaller,
break; // done shifting
} // end for
queArray[j+1] = item; // insert it
nItems++;
} // end else (nItems > 0)
}
long Priority::remove()
{
return queArray[0];
}
long Priority::peekMin()
{
return queArray[nItems-1];
}
bool Priority::isEmpty()
{
return (nItems==0);
}
bool Priority::isFull()
{
return (nItems == maxSize);
}
int main ()
{
Priority thePQ;
thePQ.insert(30);
thePQ.insert(50);
thePQ.insert(10);
thePQ.insert(40);
thePQ.insert(20);
while( !thePQ.isEmpty() )
{
long item = thePQ.remove();
cout << item << " "; // 10, 20, 30, 40, 50
} // end while
cout << "" << endl;
system("pause");
}
Here is one error:
for(j=nItems-1; j=0; j--) // start at end,
^ this is assignment, not comparison.
I am also not convinced that there isn't an off-by-one error in
queArray[j+1] = item; // insert it
Finally, your default constructor fails to initialize nItems.
There could be further errors, but I'll stop at this.
I agree with the other answers here, but I would add this:
Your "Remove" method isn't actually removing anything - it is just returning the first element - but it doesn't do anything to the array itself.
Edited to say that your insert method needs some work - it may or may not write over the end of the array, but it is certainly confusing as to what it is doing.
Try initializing your queue array in the constructor.