I have an assignment and it's to build a queue linked list.
Our professor gave us the skeleton and told us to use his main.
I wrote my functions and everything compiled right but when I ran it, I got this error.
Don't know what to do from here.
Source Code:
#include<iostream>
using namespace std;
template<class ItemType>
struct NodeType
{
ItemType info;
NodeType* next;
};
template<class ItemType>
class Queue
{
private:
int size;
NodeType<ItemType>* front; // It points to the front of a singly-linked list
NodeType<ItemType>* rear; // It points to the end of a singly-linked list
public:
Queue(); // default constructor: Queue is created and empty
Queue(const Queue<ItemType> &x); // copy constructor: implicitly called
// for a deep copy
void MakeEmpty(); // Queue is made empty; you should deallocate all
// the nodes of the linked list
bool IsEmpty( ); // test if the queue is empty
bool IsFull( ); // test if the queue is full; assume MAXITEM=5
int length( ); // return the number of elements in the queue
void Print( ); // print the value of all elements in the queue in the sequence
// from the front to rear
void Enqueue(ItemType x); // insert x to the rear of the queue
// Precondition: the queue is not full
void Dequeue(ItemType &x); // delete the element from the front of the queue
// Precondition: the queue is not empty
~Queue(); // Destructor: memory for the dynamic array needs to be deallocated
};
template<class ItemType>
Queue<ItemType>::Queue()
{
size = 0;
front = NULL;
rear = NULL;
}
template<class ItemType>
Queue<ItemType>::Queue(const Queue<ItemType> &x)
{
NodeType<ItemType>* ptr1 ;
NodeType<ItemType>* ptr2 ;
if ( x.front == NULL )
{
front = NULL ;
}
else // allocate memory for first node
{
front = new NodeType<ItemType> ;
front->info = x.front->info ;
ptr1 = x.front->next ;
ptr2 = front ;
while ( ptr1 != NULL ) // deep copy other nodes
{
ptr2->next = new NodeType<ItemType> ;
ptr2 = ptr2->next ;
ptr2->info = ptr1->info ;
ptr1 = ptr1->next ;
}
ptr2->next = NULL;
rear = ptr2;
}
}
template<class ItemType>
void Queue<ItemType>::MakeEmpty()
{
NodeType<ItemType>* tempPtr;
while(front != NULL)
{
tempPtr = front;
front = front->next;
delete tempPtr;
}
rear=NULL;
}
template<class ItemType>
bool Queue<ItemType>::IsEmpty()
{
return (size == 0);
}
template<class ItemType>
bool Queue<ItemType>::IsFull()
{
return (size >= 5);
}
template<class ItemType>
int Queue<ItemType>::length()
{
return size;
}
template<class ItemType>
void Queue<ItemType>::Enqueue(ItemType x)
{
NodeType<ItemType>* newNode;
newNode = new NodeType<ItemType>;
newNode->info = x;
newNode->next = NULL;
if(rear == NULL)
{
front = newNode;
}
else
{
rear->next = newNode;
rear = newNode;
}
size++;
}
template<class ItemType>
void Queue<ItemType>::Dequeue(ItemType &x)
{
NodeType<ItemType>* tempPtr;
if(!IsEmpty())
{
tempPtr = front;
x = front->info;
front = front->next;
if(front == NULL)
{
rear = NULL;
}
delete tempPtr;
}
size--;
}
template<class ItemType>
void Queue<ItemType>::Print()
{
NodeType<ItemType> *temp;
temp = rear;
while(temp != NULL)
{
cout<<temp->info<<endl;
temp = temp->next;
}
}
template<class ItemType>
Queue<ItemType>::~Queue()
{
MakeEmpty();
}
int main()
{
Queue<int>IntQueue;
int x;
IntQueue.MakeEmpty();
IntQueue.Dequeue(x);
IntQueue.Enqueue(10);
IntQueue.Enqueue(20);
IntQueue.Enqueue(30);
IntQueue.Enqueue(40);
cout << "int length 3 = " << IntQueue.length() << endl;
IntQueue.Dequeue(x);
cout << "int length 4 = " << IntQueue.length() << endl;
cout << "The int queue contains: " << endl;
IntQueue.Print();
if(IntQueue.IsFull() == false)
cout << "The int queue is not full !" << endl;
else
cout << "The int queue is full !" << endl;
Queue<float>FloatQueue;
float y;
FloatQueue.MakeEmpty();
FloatQueue.Dequeue(y);
FloatQueue.Enqueue(7.1);
cout << "float length 3 = " << FloatQueue.length() << endl;
FloatQueue.Enqueue(2.3);
cout << "float length 4 = " << FloatQueue.length() << endl;
FloatQueue.Enqueue(3.1);
FloatQueue.Dequeue(y);
cout << "The float queue contains: " << endl;
FloatQueue.Print();
Queue<float> FloatQueue2 = FloatQueue;
cout << "The float queue 2 contains: " << endl;
FloatQueue2.Print();
FloatQueue.MakeEmpty();
cout << "The float queue 3 contains: " << endl;
FloatQueue2.Print();
system("pause");
return 0;
}
The problem I'm having is obviously with the print function.
Any help is appreciated.
Inside your copy constructor, you aren't setting rear to anything when x.front == NULL. This sets temp to an invalid value inside Print, causing you both to loop when you shouldn't and dereference an invalid pointer.
Related
I'm trying to create an HTTP server using C++ 98.
The issue is that, every time I launch my server, I get the response, sending again the request from the same browser tab, and the browser keeps loading.
In my kqueue, it seems like the block for checking the read event is not being executed on the second time.
This is my code:
void webserv::Server::lunch(){
this->kq.create_event(this->sock.getSocket(), EVFILT_READ);
while(1)
this->_lunch_worker();
}
void webserv::Server::_lunch_worker(void)
{
int n_ev;
int accept_sock;
int address_size;
char buff[1000];
webserv::Header header;
// register the events in ev_list
std::cout << GREEN << "---- WAITING FOR CONNECTION ----" << RESET << std::endl;
n_ev = this->kq.get_event();
for (int i = 0; i < n_ev; i++)
{
if (this->kq.get_fd(i) < 0)
continue;
if (this->kq.get_fd(i) == this->sock.getSocket())
{
std::cout << "--- RECEIVED NEW CONNECTION ---" << std::endl;
address_size = sizeof(this->sock.getAddress());
accept_sock = accept(
this->sock.getSocket(),
(struct sockaddr*)&this->sock.getAddress(),
(socklen_t *)&address_size
);
this->sock.test_error(accept_sock);
this->kq.create_event(accept_sock, EVFILT_READ);
int flags;
if ((flags = fcntl(accept_sock, F_GETFL, 0)) < 0) {
perror("fcntl");
close(accept_sock);
close(this->sock.getSocket());
}
if (fcntl(accept_sock, F_SETFL, flags | O_NONBLOCK) < 0) {
perror("fcntl");
close(accept_sock);
close(this->sock.getSocket());
}
this->kq.create_event(accept_sock, EVFILT_WRITE, EV_ADD | EV_ONESHOT);
}
else if (this->kq.is_read_available(i))
{
int bytes_read;
std::cout << "START: is_read_available" << std::endl;
if ((bytes_read = recv(this->kq.get_fd(i), buff, 999, 0)) > 0)
{
}
}
else if (this->kq.is_write_available(i))
{
std::string hello = "HTTP/1.1 200 OK\nContent-Type: text/plain\nContent-Length: 12\n\nHello world!";
if (send(this->kq.get_fd(i), hello.c_str(), hello.length(), 0) != 0)
{
std::cout << "TEST2" << std::endl;
this->kq.set_event(this->kq.get_fd(i), EVFILT_WRITE, EV_DELETE);
this->kq.get_event_list()[i].ident = -1;
close(this->kq.get_fd(i));
}
std::cout << "END: is_write_available" << std::endl;
}
}
}
And this is the kqueue class:
/************************ CONSTRUCTORS/DESTRUCTOR ************************/
webserv::Kqueue::Kqueue()
{
this->_kq = kqueue();
std::cout << "KQUEUE CREATED" << std::endl;
this->test_error(this->_kq, "Creating Kqueue :");
this->_n_ev = 0;
}
webserv::Kqueue::~Kqueue()
{
close(this->_kq);
}
/************************ MEMBER FUNCTIONS ************************/
void webserv::Kqueue::set_event(int fd, int filter, int flags, void *udata)
{
EV_SET(&this->_ev_set, fd, filter, flags, 0, 0, udata);
}
void webserv::Kqueue::add_event(void)
{
int ret;
ret = kevent(this->_kq, &this->_ev_set, 1, NULL, 0, NULL);
this->test_error(ret, "Kqueue/add_even functions");
}
int webserv::Kqueue::get_event(void)
{
this->_n_ev = kevent(this->_kq, NULL, 0, this->_ev_list, __EV_LIST_SIZE__, NULL);
this->test_error(this->_n_ev, "Kqueue/get_event function:");
return (this->_n_ev);
}
void webserv::Kqueue::create_event(int fd, int filter, int flags, void *udata)
{
this->set_event(fd, filter, flags, udata);
this->add_event();
}
bool webserv::Kqueue::isEOF(int index)
{
if (this->_n_ev <= index)
this->test_error(-1, "Kqueue/isEOF function:");
return (this->_ev_list[index].flags & EV_EOF);
}
bool webserv::Kqueue::is_read_available(int index)
{
if (this->_n_ev <= index)
this->test_error(-1, "Kqueue/is_read_available function:");
return (this->_ev_list[index].filter == EVFILT_READ);
}
bool webserv::Kqueue::is_write_available(int index)
{
if (this->_n_ev <= index)
this->test_error(-1, "Kqueue/is_write_available function:");
return (this->_ev_list[index].filter == EVFILT_WRITE);
}
void webserv::Kqueue::test_error(int fd, const std::string &str)
{
if (fd < 0)
{
std::cerr << RED << str << " ";
perror("The following error occured: ");
std::cerr << RESET;
exit(EXIT_FAILURE);
}
}
/************************ GETTERS/SETTERS ************************/
struct kevent *webserv::Kqueue::get_event_list()
{
return (this->_ev_list);
}
int webserv::Kqueue::get_fd(int index)
{
if (this->_n_ev <= index)
this->test_error(-1, "Kqueue/get_ev_list function:");
return (this->_ev_list[index].ident);
}
void webserv::Kqueue::set_kqueue(int fd)
{
this->_kq = fd;
}
I am going to create a single linked list and construct a function (Locate()) that returns the address of the element.But in the end, I didn't see the result of this function. I tried it. This function should be run, but the result is different from what I expected.
use vs2019 on WIndows10,a student:)
#include<iostream>
using namespace std;
struct Node { //Node
int data;
Node* link;
Node(int item, Node* l = NULL)
{
data = item;
link = l;
}
Node(Node* l = NULL)
{
data = 0;
link = l;
}
};
class Link :public Node { //Link
private:
Node* first;
public:
Link(Node* l = NULL)
{
first = l;
}
Link(int d, Node* l = NULL)
{
first = new Node(d);
}
Node* Locate(int i);
};
Node* Link::Locate(int i) //Locate()
{
if (i < 0)
{
cerr << "wrong operation when locating" << endl;
exit(1);
}
int count = 0;
Node* current = first;
while (count < i && current->link != NULL)
{
current = current->link;
count++;
}
return current;
}
int main()
{
Link a;
Node* b = new Node(1);
Node* c = new Node(2);
a.link = b;
b->link = c;
cout << a.data << ' ' << b->data << ' '<<c->data<<endl;
cout << a.Locate(1) << endl;
return 0;
}
Will not output the result of this function 'Locate()' being called
Locate() accesses first->link. At that time, first is a null pointer. Whereupon your program exhibits undefined behavior; in practice, it most likely crashes.
When I re-modify the List constructor, its(Locate()) output is normal and the expected result is obtained.
The modified constructors are as follows:
Link()
{
first = new Node;
}
Link(int d)
{
first = new Node(d);
}
Node* Locate(int i);
i'm new in C++. I met a problem when doing exercise in C++ Primer 5th edition(Ex 9.43). The for loop can't stop in my function find_and_replace. Here is the code:
#include <iostream>
#include <string>
int find_and_replace(std::string& org_str, const std::string& str4find, const std::string& str4replace);
int main(int argc, char const *argv[])
{
std::string str("I am a very loooooong string to be process!");
int find_times;
find_times = find_and_replace(str, "a", "###");
std::cout << find_times << std::endl;
std::cout << str << std::endl;
return 0;
}
int find_and_replace(std::string& org_str, const std::string& str4find, const std::string& str4replace)
{
int find_times = 0;
if (org_str.size() < str4find.size())
{
std::cout << "Error: The original string is too short!" << std::endl;
return find_times;
}
else if (org_str == str4find)
{
org_str.assign(str4replace);
++find_times;
return find_times;
}
for (auto i = org_str.begin(), j = i + str4find.size(); j != org_str.end(); )
{
std::string temp(i, j);
// std::cout << temp << std::endl;
if (temp == str4find)
{
j = org_str.erase(i, j);
org_str.insert(i, str4replace.begin(), str4replace.end());
// std::cout << org_str << std::endl;
// std::cout << *i << std::endl;
j = i + str4find.size();
// std::cout << *j << std::endl;
++find_times;
}
else
{
++i;
++j;
}
}
if (org_str.substr(org_str.size() - str4find.size()) == str4find)
{
org_str.erase(org_str.size() - str4find.size(), str4find.size());
org_str.insert(org_str.end(), str4replace.begin(), str4replace.end());
++find_times;
}
return find_times;
}
I update iterator j and i after erase and insert operation, so i think, i and j are not invalid.
Anyone can tell me why the end condition: j != org_str.end() is not work?
SOLVED!
Although the cout output is correct, the i iterator is already invalid. Here is the new code. Just change few lines in for-loop.
#include <iostream>
#include <string>
int find_and_replace(std::string& org_str, const std::string& str4find, const std::string& str4replace);
int main(int argc, char const *argv[])
{
std::string str("I am a very loooooong string to be process!");
int find_times;
find_times = find_and_replace(str, "a", "###");
std::cout << find_times << std::endl;
std::cout << str << std::endl;
return 0;
}
int find_and_replace(std::string& org_str, const std::string& str4find, const std::string& str4replace)
{
int find_times = 0;
if (org_str.size() < str4find.size())
{
std::cout << "Error: The original string is too short!" << std::endl;
return find_times;
}
else if (org_str == str4find)
{
org_str.assign(str4replace);
++find_times;
return find_times;
}
for (auto i = org_str.begin(), j = i + str4find.size(); j != org_str.end(); )
{
std::string temp(i, j);
// std::cout << temp << std::endl;
if (temp == str4find)
{
i = org_str.erase(i, j);
//CHANGE BEGIN
//org_str.insert(i, str4replace.begin(), str4replace.end());
for (auto k = str4replace.begin(); k != str4replace.end(); ++k, ++i)
{
i = org_str.insert(i, *k);
}
//CHANGE END
// std::cout << org_str << std::endl;
// std::cout << *i << std::endl;
j = i + str4find.size();
// std::cout << *j << std::endl;
++find_times;
}
else
{
++i;
++j;
}
}
if (org_str.substr(org_str.size() - str4find.size()) == str4find)
{
org_str.erase(org_str.size() - str4find.size(), str4find.size());
org_str.insert(org_str.end(), str4replace.begin(), str4replace.end());
++find_times;
The i iterator become invalid after calling erase and insert, you should use the return values of that functions or recalculate the position starting from s.begin() again.
#include <iostream>
#include <string>
using std::cout;
using std::string;
int find_and_replace( string &s, const string &oldVal, const string &newVal ) {
int find_times = 0;
if ( s.size() < oldVal.size() ) {
std::cout << "Error: The original string is too short!" << std::endl;
return find_times;
}
if ( s == oldVal ) {
s.assign(newVal);
return ++find_times;
}
for ( auto i = s.begin(); i != s.end(); ++i ) {
// compare using iterators
bool is_equal = true;
auto k = i;
for ( auto j = oldVal.begin(); j != oldVal.end(); ++j, ++k ) {
if ( k == s.end() || *j != *k ) {
is_equal = false;
break;
}
}
if ( is_equal ) {
auto ie = s.erase(i, i + oldVal.size());
// This may not work with older version of g++
auto ii = s.insert(ie, std::begin(newVal), std::end(newVal));
i = ii + newVal.size() - 1;
++find_times;
}
}
return find_times;
}
int main() {
string str("I am a very loooooong string to be process!");
int find_times;
find_times = find_and_replace(str, "a", "###");
cout << find_times << '\n';
cout << str << '\n';
return 0;
}
The output (as you can see here) is:
2
I ###m ### very loooooong string to be process!
I am writing a server/client program using linux sockets. I want that both server and client can read and write at the same time with threads.
(The full code I followed can be downloaded at http://www.praxisbuch.net/embedded-linux/downloads.html).
When I start() my thread it throws a infinite loop of 'Bad file descriptor'.
My client.cpp is as follows:
class receiveThread : public Thread {
public:
receiveThread(RawMessage& rawMsg) : data_control(rawMsg) {}
virtual void run() {
cout << "starting recveive thread ..." << endl;
while(1) {
int recvBytes = bt_socket.recieveMessage(&temp_data_control);
try {
cout << "Received new Target Position: " << temp_data_control.data.value1 << endl;
data_control = temp_data_control;
}
catch (SocketException) {
cout << "Received exception " << endl;
sleep(1);
}
}
}
~receiveThread() {
bt_socket.disconnect();
}
private:
BtSocket bt_socket;
RawMessage temp_data_control;
RawMessage& data_control;
};
int main() {
BtSocket BtClient(PORTNUM);
// connect to the server.
BtClient.connectToServer();
RawMessage raw_mes;
receiveThread recv_thread(raw_mes);
recv_thread.start(); //the error occurs
while (1)
{
//do something
}
return 0;
}
thread.cpp is as follows:
void Thread::start() throw(Thread::Exception) {
if (pthread_create(&thread_id, 0, thread_starter, (void *) this) != 0) {
throw Exception("Thread::start: Cannot create thread");
}
}
void* Thread::thread_starter(void* thread_obj) {
Thread* self = reinterpret_cast<Thread*> (thread_obj);
self->setRunning(true);
self->run();
self->setRunning(false);
return 0;
}
In socket.cpp the exception is thrown:
int BtSocket::recieveMessage(AbstractDatagram *abstractDgm)
{
int numBytes;
if ((numBytes = recv(s, abstractDgm->getData(), abstractDgm->getSize(), 0)) < 0)
{
cout << strerror(errno) << endl;
}
return numBytes;
}
I really don't know what the problem is.
Any help would be extremely appreciated!
EDIT: (also from socket.cpp)
Socket::Socket(int pNumber)
{
portNumber = pNumber;
blocking = 1;
if ((s = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM)) == -1)
{
throw SocketException("socket failed (socket())", true);
}
locAddr.rc_family = AF_BLUETOOTH;
str2ba(dest, &locAddr.rc_bdaddr);
locAddr.rc_channel = portNumber;
}
void BtSocket::connectToServer()
{
struct sockaddr_rc serverAddr;
serverAddr.rc_family = AF_BLUETOOTH;
serverAddr.rc_channel = 1;
str2ba(dest, &serverAddr.rc_bdaddr);
if (connect(s, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) == -1)
{
throw SocketException("Connect failed (connect())", true);
}
}
I think I opend the socket correctly!?
Could it have been closed somehow?
I am trying to directly access integer from a pointer class, by overloading * operator, but it seems VC++ 10 is not allowing it. Kindly help:
#include "stdafx.h"
#include <iostream>
#include <conio.h>
using namespace std;
int MAX7 = 10;
struct node{
int value;
node *next;
};
struct node *head = NULL;
struct node *current = NULL;
int count = 0;
class SmartPointer{
public:
SmartPointer(){
}
int push(int i){
if(count == MAX7) return 0;
if(head == NULL){
head = new node();
current = head;
head -> next = NULL;
head -> value = i;
count = 1;
}
else{
struct node *ptr = head;
while(ptr->next != NULL) ptr = ptr->next;
ptr->next = new node;
ptr = ptr->next;
ptr->next = NULL;
ptr->value = i;
count++;
}
return 1;
}
void Display(){
node *ptr = head;
while(ptr != NULL){
cout << ptr->value << "(" << ptr << ")";
if( ptr == current )
cout << "*";
cout << ", ";
ptr = ptr->next;
}
}
int operator *(){
if(current == NULL) return -1;
struct node *ptr = current;
return ptr->value;
}
};
int main(){
SmartPointer *sp;
sp = new SmartPointer();
sp->push(99);
for(int i=100; i<120; i++){
if(sp->push(i))
cout << "\nPushing ("<<i<<"): Successful!";
else
cout << "\nPushing ("<<i<<"): Failed!";
}
cout << "\n";
sp->Display();
int i = *sp;
getch();
return 0;
}
Error#
1>test7.cpp(71): error C2440: 'initializing' : cannot convert from 'SmartPointer' to 'int'
1> No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
sp is not a smart pointer - it's a plain old dumb pointer to SmartPointer class. *sp uses built-in dereference operator, producing an lvalue of SmartPointer type. It does not call SmartPointer::operator*() - for that, you need to write **sp (two stars).
It's not at all clear why you want to allocate SmartPointer instance on the heap. That's an unusual thing to want to do (also too, you leak it). I'm pretty sure you would be better off with
SmartPointer sp;
sp.push(99);
and so on.
short answer:
int i = **sp;
You should not allocate objects with new. Your code looks like java. In C++, you must delete everything you allocate with new. In C++ you can write:
SmartPointer sp;
sp.push(99);
int i = *sp;