I am trying to make a mask delivery, ordering service code.
The function order will add a new order to order list.
The function output will output the list from newest to oldest order.
The function deliver removes the oldest order.
The following is the code:
#include <iostream>
#include <string>
using namespace std;
struct Mask {
string type;
string customer;
Mask *next;
};
void order(Mask *&head, string type, string customer){
cout << "Ordering " << type << " for " << customer << endl;
Mask *oldHead = head;
head = new Mask;
head->type = type;
head->customer = customer;
head->next = oldHead;
}
void output(Mask *head){
cout << "Outputting order list " << endl;
for (Mask *p = head; p != NULL; p = p->next)
cout << " " << p->type << " for " << p->customer << endl;
}
void deliver(Mask *&head){
if (head->next == NULL){
cout << "Delivering " << head->type;
cout << " for " << head->customer << endl;
delete head;
}
else
deliver(head->next);
}
int main()
{
Mask *head = NULL;
order(head, "3M-N95", "Alice");
order(head, "OxyAir", "Burce");
order(head, "3M-N95", "Cindy");
output(head);
deliver(head);
output(head);
}
Everything runs smoothly, but it says segmentation error(core dumped) at the end. I tried adding this:
if (head->next->next == NULL){
deliver(head->next);
head->next == NULL;
}
But the problem still exists. Any help is appreciated.
I changed deliver to this:
void deliver(Mask *&head){
if (head->next->next == NULL){
cout << "Delivering " << head->next->type;
cout << " for " << head->next->customer << endl;
head->next = head->next->next;
delete head->next;
}
else
deliver(head->next);
}
Apparently, just setting the pointer to NULL does not fix the problem, so I just updated it so that the second last pointer pointed directly to the end.
in "deliver" you force the function to meet the condition if(head->next == NULL)
and then trying to reach head->next->next which is like trying to say null->next (resulting with segmentation fault).
I would recommend traversing to the last "Mask" object with a while loop instead of using all those "if" statements which lead to the same result, or at least change the second if to else if in order to avoid meeting this "if" again.
Related
For an assignment I was tasked with creating a queue with linked lists. Our professor has given us the test code to insure the program is working properly and for grading. My serve function returns a character. However in the main(), the function is called twice within one cout statement, and it returns the character in incorrect order. The getSize function is also called, however it does not seem to do anything.
cout << boolalpha;
Queue q1 = Queue();
q1.append('m');
q1.append('a');
q1.append('b');
q1.append('b');
q1.display();
cout << q1.serve() << " " << q1.serve() << " " << q1.getSize() << endl;
the display outputs: m a b b. However the cout shows as: a m 4. This should obviously come out as: m a 2.
If i separate the serve and the getSize functions, it works just fine, i.e. cout << q1.serve() << " "; cout << q1.serve() << " "; cout << q1.getSize() << " ";
Below I have posted the code for the linked queue. I imagine I have made a mistake with my node pointers, however I have drawn pictures and re-written the code to no avail.
I also apologize if Ive improperly formatted this as it is my first posting. Thank you.
#include <iostream>
using namespace std;
struct Node {
char data;
Node* next;
};
class Queue {
private:
Node* front, * rear;
int size;
public:
Queue();
void append(char);
char serve();
bool isEmpty();
bool isFull();
int getSize();
void display();
};
Queue::Queue() {
front = rear = nullptr;
size = 0;
}
void Queue::append(char v) {
Node* p = new Node;
p->data = v;
p->next = nullptr;
if (size == 0) {
front = rear = p;
size++;
}
else if (size == 1) {
front->next = p;
rear = p;
size++;
}
else {
rear->next = p;
rear = p;
size++;
}
}
char Queue::serve() {
if (front != nullptr) {
Node* temp = front;
char v = temp->data;
front = front->next;
delete temp;
size--;
return v;
}
}
bool Queue::isEmpty() {
return size == 0;
}
bool Queue::isFull() {
return false;
}
int Queue::getSize() {
return size;
}
void Queue::display() {
Node* runner = front;
while (runner != nullptr) {
cout << runner->data << " ";
runner = runner->next;
}
cout << endl;
}
int main() {
cout << boolalpha;
Queue q1 = Queue();
q1.append('m');
q1.append('a');
q1.append('b');
q1.append('b');
q1.display();
cout << endl << q1.isEmpty() << " " << q1.isFull() << " " << q1.getSize() << endl;
cout << q1.serve() << " " << q1.serve() << " " << q1.getSize() << endl;
q1.display();
cout << endl;
/*cout << q1.isEmpty() << " " << q1.isFull() << " " << q1.getSize() << endl;
char a = q1.serve(); char b = q1.serve();
cout << a << " " << b << " " << q1.getSize() << endl;*/
}
I'll give you a big hint: Your output is "a m 4", not "m a 4". The remainder of the answer is below...
.
.
.
.
.
.
(edit: added more explanation)
The cout is running the arguments right to left, because of the associativity of the << operator. So it's getting the size, then getting the first item in the queue, then getting the next one. Even though the operator itself is Left-to-Right, in order to apply them in that order, it's evaluating the arguments right to left.
Think of it this way, while it's required to apply the operators on the left before it applies the ones on the right, it's still evaluating the argument on the right of the operator before it evaluates the one on the left.
This is fundamentally about how the stack works. It's loading the evaluation of the arguments and operators right to left so that it can apply the operators in the reverse order.
Since the operators are all the same precedence, it's pushing the right most operand, then the right most operator, then that' operator's left operand, which is everything to the left.
If your operators are L-R associative, that means that the operands are evaluated R-L before being operated on L-R.
Just do
cout << q1.serve() << " ";
cout << q1.serve() << " ";
cout << q1.getSize() << endl;
this is my first post on Stack Overflow :)
Sorry if I seems egoistic, but I have an exam tomorrow and I'm facing a problem that I cannot solve. Hope to find here an answer, I tried to find out if there was already an opened 3d, but I cannot find it.
Here's my problem:
I'm writing a code in C++, using the pointer. Because of I retrieve always the same error on a larger code, I tried with an easier one, but the error persists.
The code is the following:
#include <iostream>
using namespace std;
struct EXAMPLE {
int value;
EXAMPLE *next;
};
int insertnew(EXAMPLE *&sorting, EXAMPLE val);
int printlist(EXAMPLE *&sorting);
int main() {
int i;
EXAMPLE new;
EXAMPLE *list = NULL;
for (i = 0; i < 3; i++)
{
cout << "value: " << endl;
cin >> new.value;
insertnew(list, new);
}
printlist(list);
system("Pause");
return 0;
}
int insertnew(EXAMPLE *&sorting, EXAMPLE val){
EXAMPLE *temp;
temp = new EXAMPLE;
temp->value = val.value;
temp->next = sorting;
sorting = temp;
return 0;
}
int printlist(EXAMPLE *&sorting) {
while (sorting != 0)
{
sorting = sorting->next;
cout << sorting->next << " " << sorting->value << endl;
}
return 0;
}
It's an easy LIFO structure.
I get a bad reading access error on this line:
cout << elenco->next << " " << elenco->valore << endl;
But here's the curios thing.
If I revert the lines in this way:
int printlist(EXAMPLE *&sorting) {
while (sorting != 0)
{
cout << sorting->next << " " << sorting->value << endl;
sorting = sorting->next;
}
return 0;
}
as a FIFO structure, I got no error at all!
Can you help me understanding where the problem is?
Thanks in advance
//edit
Uops, find out my error.
The while was supposed to be a recursive function, dunno why I inserted a while, assuming it will function as a recursive function.
just solved
cout << lista->value << endl;
while (list != NULL)
{
list = list->next;
if (list != 0) {
cout << list->value << endl;
}
}
Sorry
Let's take a look at your example code:
int printlist(EXAMPLE *&sorting) {
while (sorting != 0) //As long as "sorting" is not null
{
sorting = sorting->next; //Set "sorting" to the next value
cout << sorting->next << " " << sorting->value << endl; //print the value
}
return 0;
}
Just play this code through if you have only one element in your LIFO list.
int printlist(EXAMPLE *&sorting) {
while (sorting != 0) //"sorting" is not null
{
sorting = sorting->next; //Set "sorting" to the next value, which is null
cout << sorting->next << " " << sorting->value << endl; //crash because "sorting" is null
}
return 0;
}
This will happen every time you hit the last element.
You can change your code to a do-while-loop with an additional if, or add an if with a break within your current loop. But I would recommend to go with a for-loop on this one.
Also you don't need to pass the pointer by reference. You even shouldn't do it, as you don't want to change your list when printing it (as your current code does...)
How about something like this:
int printlist(EXAMPLE * sorting) {
for (EXAMPLE * current = sorting; current != 0; current = current->next)
{
cout << current << " " << current->value << " -> " << current->next << endl;
}
return 0;
}
I also changed the output a little bit to show more interesting data.
You are trying to access the tail of the list when sorting->next reaches the last element. With the second code you access only list elements.
Clear, thanks
I also tried another version
int printlist(EXAMPLE *list) {
if (list != NULL)
{
cout << list->value << "-> " << list->next << endl;
printlist(list->next);
}
return 0;
}
and this is how it was supposed to work from the beginning. In this way by just switching the two rows inside the IF I can change from LIFO to FIFO :)
I'm still new to programming. I just wanted to ask how do I to do linear search using pointers. I wanted to make a book management program and i have made a program with pointers written.
This is the example of how i want it.
This is the coding
#include <iostream>
#define MAX 5
using namespace std;
struct record
{
int id;//stores id
float price;//store price
int qty;//stores quantity
record* next;//reference to the next node
};
record* head;//create empty record
record* tail;//the end of the record
void push(record *& head, record *&tail, int id, float price, int qty)
{
if (head == NULL)
{
record* r = new record;
r->id = id;
r->price = price;
r->qty = qty;
r->next = NULL;//end of the list
head = r;
tail = r;
}
else if (head != NULL && (MAX - 1))
{
record* r = new record;
r->id = id;
r->price = price;
r->qty = qty;
r->next = head;
head = r;
}
}
int pop(record *&head, record *& tail)
{
if (head == NULL)
{
cout << "No record in memory" << endl;
}
else if (head == tail)
{
cout << "The record "<<"ID: " << head->id << "\nPrice: " << head->price << "\nQuantity: " << head->qty << "\n" << "was deleted" << endl; //CORRECTION HERE
}
else
{
record* delptr = new record;
delptr = head;
head = head->next;
cout << "The record " << delptr->id << ", " << delptr->price << ", " << delptr->qty << " was deleted" << endl; //CORRECTION HERE
delete delptr;
}
return 0;
}
void display(record *&head)
{
record* temp = new record; //CORRECTION HERE
temp = head;
if (temp == NULL)
{
cout << "No record in memory" << endl;
}
else
{
cout << "Record : " << endl;
while (temp != NULL)
{
cout <<"\nID: "<< temp->id << "\nPrice: " << temp->price << "\nQuantity: " << temp->qty <<"\n"<< endl; //CORRECTION HERE
temp = temp->next;
}
}
}
int LinearSearch(record *&head) {
}
char menu()
{
char choice;
cout << "\t::MENU::\n" << endl;
cout << "1. Add new record\n" << endl;
cout << "2. Delete record\n" << endl;
cout << "3. Show record\n" << endl;
cout << "4. Quit\n" << endl;
cout << "-----------------------\n" << endl;
cout << "\nEnter selection : " << endl;
cin >> choice;
return choice;
}
int main()
{
record* head;
record* tail;
head = NULL;
tail = NULL;
char choice;
do
{
cout << "---------------------- - \n" << endl;
choice = menu();
switch (choice) { //CORRECTION HERE
case '1':
int id, qty;
float price;
cout << "Enter ID:";
cin >> id; // Please correct yourself here, what is r here, r is not declared anywhere
cout << "\nEnter Price: ";
cin >> price;
cout << "\nEnter Quantity: ";
cin >> qty;
push(head, tail, id, price, qty);
break;
case '2':
pop(head, tail);
break;
case'3':
display(head);
break;
default:
cout << "Quiting...\n";
}
} while (choice != '4');
return 0;
}
How do I write linear search of pointer code for this coding? I tried finding examples throughout the web and when i execute it, it didn't work so i just leave it blank.
Well, I saw you have a list and you are dealing with pointers.
If you want to do linear search in a record id, for example, you can do it like this:
record *aux = head;
while(aux != NULL){
if(aux->id == id_you_want_to_find){
printf("I found it\n");
}
aux = aux->next;
}
you usually use object.attribute to access the attributes of common objects, but when you have a pointer to an object, you must do pointerToObject->attribute.
You can write one if you want but there is no need to when there already exists libraries that do this for you. Since you are using a list structure I show this using a simple std::list. You could also change this to a std::vector and just do a simple for loop iteration using index notation since the speed of search through them is constant as opposed to linear. Here is one method of doing a search through a list linear.
#include <list>
record* searchRecords( std::list<record>& records, int id ) {
if ( records.empty() ) {
std::ostringstream strStream;
strStream << __FUNCTION__ << " Invalid list of records: list is empty.";
throw ExceptionHandler( strStream ); // Not Written, but what should be done instead of returning.
return nullptr;
}
std::list<record>::iterator it = records.begin();
while ( it != records.end() ) {
if ( it->id == id ) {
return (&(*it));
}
++it;
}
std::ostringstream strStream;
strStream << __FUNCTION__ << " No entry found in search with ID{" << id << "}.";
Logger::log( strStream, Logger::LOGGER_INFO ); // Not implemented here same as above for ExceptionHandler
return nullptr;
}
Since linked lists are not associative they Must be traversed from beginning to end for every entry N in the list to either insert, find or delete. The time complexity here is linear.
If you want faster time insertion time with large lists you can use <multiset> if there may be duplicate items or <set> if every known item is unique. These have instant insertion. If you want constant search and don't care about insertion time then <vector> is what you would want.
The normal answer would be: don't write a linear search yourself, it's called std::find_if. However, C++ expects that your datastructure exposes iterators. An iterator refers to a record (or the end of your list). You get the actual record by calling operator* on the record, and you get the next record by calling operator++.
Yes, this is similar to pointers. That's intentional; pointers are iterators for contiguous arrays. That means you can call std::find_if on an array. But since you chose to implement a linked list instead of an array, you'd' need to implement your own iterator class.
This is for a lab I have done, which is to create a simple queue using C++.
#include "Task5.h"
#include <iostream>
using namespace std;
void push(const long &i, node* &n) {
if (n == NULL) {
node *ptr = new node;
ptr -> item = i;
ptr -> next = NULL;
n = ptr;
cout << "Created New Node." << endl;
}
else {
node *ptr = n;
cout << "Created Pointer" << endl;
while (ptr -> next != NULL){
cout << "Finding Next..." << endl;
ptr = ptr -> next;
}
cout << "I'm here." << endl;
node *temp = new node;
temp -> item = i;
ptr -> next = temp;
cout << "Node Created." << endl;
}
}
long pop(node* &n) {
if (n == NULL) cout << "HEY!!! Can't pop an empty queue." << endl;
else {
long val;
node *ptr = n;
n = n -> next;
val = ptr -> item;
delete ptr;
return val;
}
}
int main() {
node *head = NULL;
push(13,head);
push(10,head);
push(18,head);
push(22,head);
cout << pop(head) << endl;
cout << pop(head) << endl;
cout << pop(head) << endl;
cout << pop(head) << endl;
cout << pop(head) << endl;
cout << pop(head) << endl;
}
This is giving the following output:
Created New Node.
Created Pointer
I'm Here.
Node Created.
Created Pointer
Finding Next...
I'm here.
Node Created.
Created Pointer
Finding Next...
Finding Next...
I'm here.
Node Created.
13
10
18
22
HEY!!! Can't pop an empty queue.
6296192
HEY!!! Can't pop an empty queue.
6296192
So the end result is that the code works, HOWEVER it outputs 6296192 randomly. I thought maybe I misspell something or cout is converting endl; to hex. My lab instructor also has no idea what's happening. Can someone tell me what is happening? If it helps, I am running this code via Linux-run terminal.
Thanks in advance.
In your function:
long pop(node* &n) {
you don't return anything in case of n == NULL is true. So this is UB, and might also cause such random values in output.
I'd suggest using the debugger with a breakpoint on the first cout << pop(head) << endl; and watch the value returned from pop each time.
Also the compiler is probably giving you a warning about the cause of the issue, always pay attention to the warnings it usually means something unintended will happen.
The cout << pop(head) << endl; uses the value returned by pop() but in the case of an empty queue there is no value returned, resulting in undefined behavior.
First of all, apologies if this is a duplicate question. I'm just learning C++ and probably don't know the correct search terms to find what I'm sure has already been asked.
Anyways, I'm teaching myself C++ by working through the 30 days of code on HackerRank. However, I've hit a roadblock that I can't seem to solve when asked to implement an insert method for a LinkedList. Conceptually, I know what needs to be done, but syntactically I'm running into an issue.
Below is my code, with debugging printouts included. What seems to be happening is that new_node keeps getting put in the same location in memory, regardless of which loop iteration its on. How do I ensure this gets a new place in memory? I seem to get the same behavior regardless of if I declare new_node as static or not.
Here's the code:
#include <iostream>
#include <cstddef>
using namespace std;
class Node
{
public:
int data;
Node *next;
Node(int d){
data=d;
next=NULL;
}
};
class Solution{
public:
/// ----- MY CODE BEGINS HERE:
Node* insert(Node *head,int data)
{
cout << "----------" << endl;
cout << data << endl;
int i = 0;
if (head){
Node *curr = head;
Node *next = curr->next;
while(next){
cout << data << "," << i << ": " << curr << "," << curr->next
<< "," << curr->data << endl;
i++;
curr = curr->next;
next = curr->next;
}
cout << data << "," << i << ": " << curr << "," << curr->next
<< "," << curr->data << endl;
static Node new_node = Node(data);
curr->next = &new_node;
cout << " *** Adding " << data << " at " << curr->next
<< " and next points to: " << (curr->next)->next << endl;
return head;
}
else{
static Node new_head = Node(data);
cout << " *** Adding " << data << " at " << &new_head
<< " and next points to: " << new_head.next << endl;
return &new_head;
}
}
// ------- MY CODE ENDS HERE
void display(Node *head)
{
Node *start=head;
while(start)
{
cout<<start->data<<" ";
start=start->next;
}
}
};
int main()
{
Node* head=NULL;
Solution mylist;
int T,data;
cin>>T;
while(T-->0){
cin>>data;
head=mylist.insert(head,data);
}
mylist.display(head);
}
When I run this with the sample input of (4, 2, 3, 4, 1), I get the following:
----------
2
*** Adding 2 at 0x6022e0 and next points to: 0
----------
3
3,0: 0x6022e0,0,2
*** Adding 3 at 0x7fff3ddc1d80 and next points to: 0
----------
4
4,0: 0x6022e0,0x7fff3ddc1d80,2
4,1: 0x7fff3ddc1d80,0,3
*** Adding 4 at 0x7fff3ddc1d80 and next points to: 0x7fff3ddc1d80
----------
1
1,0: 0x6022e0,0x7fff3ddc1d80,2
1,1: 0x7fff3ddc1d80,0x7fff3ddc1d80,4
1,2: 0x7fff3ddc1d80,0x7fff3ddc1d80,4
1,3: 0x7fff3ddc1d80,0x7fff3ddc1d80,4
1,4: 0x7fff3ddc1d80,0x7fff3ddc1d80,4
1,5: 0x7fff3ddc1d80,0x7fff3ddc1d80,4
and this continues until a Segmentation Fault ebcause its caught in an infinite loop...
Any ideas why new_node keeps getting placed in the same memory location (with or without the static)? Is this not even the main issue and I'm completely missing the point? Thanks in advance!
-- C++ neophyte.
EDIT: The suggested duplicate doesn't quite address the question here. My trouble was not understanding the difference between pointers and references, but rather the difference between:
Node node_1 = Node(data);
static node_2 = Node(data);
node_3 = new Node(data);
As I was unaware of the new operator at the time of writing the question (obviously!), I did not know to (a) search for this or (b) include this term in the title. The title has been edited for clarity, and this edit has been included for future readers.
When you declare a variable static, there's only one copy of that variable. It gets created the first time you execute the declaration, and future calls to the function reuse the same data. So every time you use new_node, it's the same node.
You need to allocate dynamic data with the new operator. As the operator name implies, this creates a new object every time you use it. When you add a remove() operation to the class, it will use delete to free the memory.
Node* insert(Node *head,int data)
{
cout << "----------" << endl;
cout << data << endl;
int i = 0;
if (head){
Node *curr = head;
Node *next = curr->next;
while(next){
cout << data << "," << i << ": " << curr << "," << curr->next
<< "," << curr->data << endl;
i++;
curr = curr->next;
next = curr->next;
}
cout << data << "," << i << ": " << curr << "," << curr->next
<< "," << curr->data << endl;
Node *new_node = new Node(data);
curr->next = new_node;
cout << " *** Adding " << data << " at " << curr->next
<< " and next points to: " << (curr->next)->next << endl;
return head;
}
else{
Node *new_head = new Node(data);
cout << " *** Adding " << data << " at " << &new_head
<< " and next points to: " << new_head->next << endl;
return new_head;
}
}
you use a static variables. These are created only once, and are the same for every function call!
your intend is to create a new Node always, so these variables are not static!
try it out with
Node* new_head = new Node(data);
return new_head;
// as well as
Node* new_node = new Node(data);
curr->next = new_node;
All nodes must be create on the free store (with new), otherwise they get cleaned up when the function ends.
This means you are always referencing to not existing variables, which is a memory corruption. You must as well provide a destructor to delete the new'd nodes.
For more information read about the lifespan of variables.
Further notes:
use nullptr
std::list, or std::linked_list are the containers for lists (i know, you want to learn, but take a look at them)
your class is all public -> you can use a struct, since its the same, but default public for access specifiers.
use unique_ptr for the ownership (this is kinda advanced, but use it early)