Hello I am new fairly newly to C++ and I am constructing a program that will simulate a colony of bunnies. I am a bit stuck on how to resolve this issue on how to get methods to recognize my global pointer variables. I get this error when I try to compile my program.
enter code here
main.cpp: In function ‘bool ageCheck(BunnyNode*)’:
main.cpp:133:5: error: ‘head’ was not declared in this scope
if(head){
^
I have several more errors that are similar to this one. I am under the impression that if I understand why this error is being given, I will be able to sort out the others. I chose an error from the ageCheck() method that is supposed to traverse the linked list of bunnies and check their ages.
This is what I have
enter code here
#include <iostream>
#include <string>
#include <vector>
#include <cstdlib>
//#include "listofbunny.h"
using std::cin;
using namespace std;
typedef struct BunnyNode {
string* name;
int age;
bool gender;
string* color;
bool radioactive_bunny;
BunnyNode *next;
BunnyNode *head;
BunnyNode *tail;
BunnyNode *current;
}
char menu();
int randomGeneration(int x);
void generateFeatures(BunnyNode * newBunny);
void startCheck(int pass);
void sizeCheck(bool& terminate);
bool fatherCheck(BunnyNode * bunny, bool& fatherPresent);
bool motherCheck(BunnyNode * bunny);
bool ageCheck(BunnyNode * bunny);
void addBunnyAge();
void addBabyBunny();
void addBunny();
void addBunny(BunnyNode * mother);
int mutantCount();
void mutantTransform();
void purge();
string getGender(BunnyNode * bunny);
string getName(BunnyNode * bunny);
int getColonySize();
void printColony();
void printFeature(BunnyNode * bunny);
void printSize();
bool ageCheck(BunnyNode * bunny){
if(head){
if(bunny->age >= MAX_AGE && bunny->radioactive_bunny == false){
return 1;
}
else if(bunny->age >= MAX_MUTANT_AGE && bunny->radioactive_bunny){
return 1;
}
else
return 0;
}
}
A typical linked list structure is made of three parts
The Data
class Bunny
{
string name; // don't use pointers unless you really, really need them
int age;
bool gender;
string color;
bool radioactive_bunny;
public:
string getGender(); // don't need to know which Bunny anymore because
// these functions are bound to a particular Bunny
string getName();
...
};
The Node
struct Node
{
Bunny data; // we will ignore templates for now. But they are rilly kool!
Node * next; // here is a good time to use a pointer: to point to the next node
Node(): next(nullptr) // node constructor. This really helps. Trust me.
{
}
}
Nodes know nothing except their data and a link to the next Node. The dumber you can make a Node, the safer you are. Also note that the Node contains the Data. This allows you to easily swap out the Data without having to re-write the whole node and sets you up for easy templating of the Lined List structure later (though you're probably better off jumping to std::list).
And the Linked List:
class LinkedList
{
Node *head;
Node *tail;
Node *current; // not as useful as you might think
public:
LinkedList(): head(nullptr),tail(nullptr),current(nullptr)
{
}
void add(Bunny & bunny);
void remove(const string & bunnyname);
Bunny & get(const string & bunnyname);
Bunny & getNext(); // current may help here, but look into iterators
...
};
Note that we never let the caller at a Node. They could do something stupid like delete it or mangle Node::next.
Adding, removing and iterating through the list has been beaten to death on Stack Overflow, so you should be able to find tonnes of examples of how to do this. For example: Using pointers to remove item from singly-linked list. There is, in my opinion, a really important trick in that link well worth the time spent learning. Pointers are like fire: A handy servant, but a terrifying master.
The big trick to getting linked lists is use a pencil and paper to draw the list and the nodes. See how they are connected. Redraw the list step by step as you add, remove, etc... so you can see how it needs to be done. Then write code to match the drawings. I know. Easier said than done, but way easier than banging your head against a wall with no plan whatsoever.
Related
Hello everyone i wish you are having a great day, i have a problem with allocation memory for my tree with some code i think it's easier to explain and understand.
#define H 7
class Node{
public:
int node_number;
int depth;
int value;
Node* nodes[L];
public:
Node new_node(int node_number,int depth,int value);
void add_node(Node root_node,Node new_node);
void print_node(Node print_node);
};
To create a node my function is here
Node Node::new_node(int node_number,int depth,int value){
Node x;
x.node_number=node_number;
x.depth=depth;
x.value=value;
x.nodes[L]=(Node*) std::malloc(L*sizeof(Node));
return x;
}
and now when i want to add nodes in the node him self like declared in the class i got Segmentation fault (core dumped)
void Node::add_node(Node root_node,Node new_node){
root_node.nodes[0]=&(new_node);
}
My main function
Node root_node;
root_node=root_node.new_node(10,2,23);
Node x;
x=x.new_node(17,19,7);
root_node.add_node(root_node,x);
root_node.print_node(root_node);
Thank you so much
There are few problems here. Firstly you're not actually allocating any new memory. The line in the new_node method
Node x;
is a local variable so it will be destroyed when the method completes, the method then returns a copy of this object on the stack.
Then in the add_node method there is another problem:
root_node.nodes[0]=&(new_node);
This line doesn't call the node_node method, it actually takes the address of the function. Even if it did call the method it would be returning a copy of the object on the stack not a pointer to an object on the heap which is what you need.
Your code doesn't show the definition of L, I'm going to assume that it is a macro definition. Your new_node method should look like this, node the new reserved word, this is where the new object is created on the heap:
Node* Node::new_node(int node_number,int depth,int value){
Node *x = new Node;
x->node_number=node_number;
x->depth=depth;
x->value=value;
// x->nodes[L]=(Node*) std::malloc(L*sizeof(Node));
// not needed if L is a macro and needs correcting if L is a variable
return x;
}
Now this method returns a pointer to a new object on the heap.
Your add_node method will then look like this:
void Node::add_node(Node root_node,Node new_node){
root_node.nodes[0]=new_node(/* Need to add params here! */);
}
However there is a much better way of doing what you want here. You should write a constructor for the Node class like below:
Node::Node(int node_number,int depth,int value)
{
this->node_number = node_number;
this->depth = depth;
this->value = value;
}
This removes the need for the new_node method and means your add_node method will look like this:
void Node::add_node(Node root_node,Node new_node){
root_node.nodes[0]=new Node(/* Need to add params here! */);
}
Hope this helps.
Although there is already a complete answer provided by PeteBlackerThe3rd, I deem it worthy to also provide an answer that does not use any manual memory allocation as this is often the preferred way in C++.
I took the liberty to make some minor adjustments, e.g., when adding a node it is not necessary to provide the depth in the tree as this can be derived from its parent's node.
The struct uses a std::vector which has (at least) two benefits compared to the code provided in the question. First, there is no need to know the maximum number of children nodes during compile time. If you want to fix this during compile time one can easily replace the std::vector by std::array. Second, there is no need to manually free memory at destruction as this is all taken care of by std::vector.
#include <iomanip>
#include <vector>
struct Node
{
// I expect these data members to be constants
int const d_nodeNumber;
int const d_depth;
int const d_value;
std::vector<Node> d_childNodes;
Node() = delete;
Node(int number, int depth, int value)
:
d_nodeNumber (number),
d_depth (depth),
d_value (value),
d_childNodes ()
{ }
/*
* Note that this function does not ask for a 'depth' argument
* As the depth of a child is always the depth of its parent + 1
*/
void addChildNode (int number, int value)
{
d_childNodes.emplace_back(number, d_depth + 1, value);
}
/*
* Just an arbitrarily function to generate some output
*/
void showTreeFromHere() const
{
int const n = 1 + 2 * d_depth;
std::cout << std::setw(n) << ' '
<< std::setw(5) << d_nodeNumber
<< std::setw(5) << d_depth
<< std::setw(5) << d_value << std::endl;
for (Node const &n: d_childNodes)
n.showTreeFromHere();
}
};
The struct can be used as follows:
int main()
{
Node root_node(0,0,0);
// Add two child nodes
root_node.addChildNode(1,1);
root_node.addChildNode(2,1);
// Add six grandchildren
root_node.d_childNodes[0].addChildNode(3,8);
root_node.d_childNodes[0].addChildNode(4,8);
root_node.d_childNodes[0].addChildNode(5,8);
root_node.d_childNodes[1].addChildNode(6,8);
root_node.d_childNodes[1].addChildNode(7,8);
root_node.d_childNodes[1].addChildNode(8,8);
root_node.showTreeFromHere();
}
I am solving exercises for a C++ exam I have soon. Consider the following exercise:
A travel agency uses lists to manage its trips. For each trip the agency registers its point of departure, point of arrival, distance and time/duration
1) Define the necessary structures to represent a list of trips
2) Write a function that, given integer i returns the point of departure and point of arrival of the trip in position i
Defining the structure is easy:
struct list{
char departure[100];
char arrival[100];
double distance;
double time;
list* next = NULL;
};
My problem is the function. The actual work, to find the ith trip is easy. But how can I return the two char arrays/strings departure and arrival? If this were a question in my exam, I would have solved it like this:
typedef list* list_ptr;
list_ptr get_trip(list_ptr head, const int i){
if(i<0 || head==NULL){
return NULL;
}
for(int k = 0; k<i;k++){
head = head->next;
if(head==NULL){
return NULL;
}
}
return head;
}
I am returning a pointer to the list element. One then has to print departure and arrival. I could easily return just the departure or just the arrival by using a function with return type char*. How can I properly return 2 strings?
I know that there is ways doing this using std::tuple, but I cannot use this as we haven't had it in the lecture(we only had the really basic stuff, up to classes).
Am I right that returning both strings is not possible without using additional libraries?
Cheers
OK, to start with, your list type has some problems. Don't use char[] in C++ unless you really, really have to (note: if you think you have to, you're probably wrong). C++ provides a standard library that is wonderous in its applications (well, compared to C), and you should use it. In particular, I'm talking about std::string. You're probably OK using double for distance and duration, although a lack of units means that you're going to have a bad time.
Let's try this:
struct Trip {
std::string departure;
std::string arrival;
double distance_km;
double duration_hours;
};
Now you can either use std::vector, std::list, std::slist, or roll your own list. Let's assume the last.
class TripList {
public:
TripList() = default;
// Linear in i.
Trip& operator[](std::size_t i);
const Trip& operator[](std::size_t i) const;
void append_trip(Trip trip);
void remove_trip(std::size_t i);
private:
struct Node {
Trip t;
std::unique_ptr<Node> next;
};
std::unique_ptr<Node> head;
Node* tail = nullptr; // for efficient appending
};
I'll leave implementation of this to you. Note that list and trip are separate concepts, so we're writing separate types to handle them.
Now you can write a simple function:
std::pair<string, string> GetDepartureAndArrival(const TripList& list, std::size_t index) {
const auto& trip = list[index];
return {trip.departure, trip.arrival};
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
the code send error in this line
course["CS"].student=new Course*[1];
i want create linked list of courses contain linked list of students
here is the code
struct Student{
string name;
int id;
int grade;
Student(string n, int i, int gd ){
name=n;
id=i;
grade=gd;
}
};
struct Course{
string C_Name;
Student **student;
int index;
void add_student(Student *new_student){
student[++index]=new_student;
}
};
Course course[4];
void init(){
course["CS"].student=new Course*[1];
}
Your code doesn't contain any kind of linked list, but only plain arrays.
Apart from that, the last line (course["CS"].student=new Course*[1];) contains some invalid syntax.
An integral or enum type must be used to access an array (strings or char[] wont work)
Assigning a Course** to a Student** object is not allowed
A linked list contains of nodes each having a pointer to the next node. The last node usually has a pointer with value nullptr (C++11) or 0 (older standard). Note: There is also a so-called double linked list, where every node also stores a pointer to the previous one.
A node contains all the data, that you want it to store.
Example:
struct Node {
Node* next;
// other node data here
};
To create a linked list, you first start with one node and set next = nullptr; // 0. To add another node just create a new one and change the pointer of the first one.
Example:
Node* node1 = new Node();
node1 -> next = nullptr;
Node* node2 = new Node();
node2 -> next = nullptr;
node1 -> next = node2;
You start to see a pattern. To insert at the front just create a new Node and set its next to the first already existing node. To insert between two nodes, say node1 and node2:
node1 -> next = newNode;
newNode -> next = node2;
To make it nice one usually writes a wrapper class containing functions such as
InsertNodeAt(Node* node, uint index);
Node* GetNodeAt(uint index);
RemoveNodeAt(uint index);
Since you have two different types of objects (Student and Curse), you might want to use templates and avoid writing a linked list class for each type.
If you want to create your linked list yourself, I recommend doing some additional research (google is your friend) as I have only mentioned a few things.
If you don't mind using the c++ standard library you might be interested in using the already pre-made linked list classes std::forward_list (standard linked list) and std::list (double linked list).
in c++ you didn't defined course["string"], so you may not use "CS" as an index to a Course type object
and *.student is a class Student's object, not Course type
#include <iostream>
#include <stdexcept>
using namespace std;
struct Student{
string name;
int id;
int grade;
Student(string n, int i, int gd ){
name=n;
id=i;
grade=gd;
}
};
struct Course{
string C_Name;
Student **student;
int index;
void add_student(Student *new_student){
student[++index]=new_student;
}
};
Course course[4];
void init(){
// Need allocate space for a new object of class "Course"
Course course;
course.student = new Student*[1];// "student" is Student type but not Course
}
int main()
{
try{
init();
}
catch(...){
return -1;
}
std::cerr <<"your debug info" <<endl;
return 0;
}
And in my own opinion, in c++ you may try reference and it's counter in class Course's definition to class Student. Using printer in this way may cause error unexpected.
I am in process of learning c++. I am working on creating a linkedlist data structure. One of the functions that displays the values of nodes in the structure does not work. For some reason the while loop that traverses through nodes doesn't work in the display function, hence I can't see the values in those nodes. Does anyone see what the problem is? I've been staring at the code for a while and not sure what is wrong here.
Thanks for your help in advance.
Header:
// linklist.h
// class definitions
#ifndef LINKLIST_H
#define LINKLIST_H
class linklist
{
private:
// structure containing a data part and link part
struct node
{
int data;
node *link;
}*p;
public:
linklist();
void append(int num);
void addatbeg(int num);
void addafter(int loc, int num);
void display();
int count();
void del(int num);
~linklist();
};
#endif
.cpp file
// LinkedListLecture.cpp
// Class LinkedList implementation
#include"linklist.h"
#include<iostream>
using namespace std;
// initializes data member
linklist::linklist()
{
p =NULL;
}
// adds a node at the end of a linked list
void linklist::append(int num)
{
node *temp, *r;
// if the list is empty, create first node
if(p==NULL)
{
temp = new node;
temp->data = num;
temp->link = NULL;
}
else
{
// go to last node
temp = p;
while(temp->link!=NULL)
temp = temp->link;
// add node at the end
r = new node;
r->data=num;
r->link=NULL;
temp->link=r;
}
}
// displays the contents of the linked list
void linklist::display()
{
node *temp = p;
cout<< endl;
// traverse the entire linked list
while(temp!=NULL) // DEBUG: the loop doesn't work
{
cout<<temp->data<<" ";
temp = temp->link;
}
void main()
{
linklist l;
l.append(14);
l.append(30);
l.append(25);
l.append(42);
l.append(17);
cout<<"Elements in the linked list:";
l.display(); // this function doesn't work
system("PAUSE");
}
You never set p to a non NULL value.
if(p==NULL)
{
p = new node;
p->data = num;
p->link = NULL;
}
I think GWW has highlighted the issue, but part of learning to program it to learn how to identify the mistakes.
If you do something and don't get the expected result you could:
Use the visual c++ debugger to step through and see the values of your variables.
Put in log lines to report information you think is important
inspect the code - if you think something is right but it doesn't work, then go to an earlier step and check it does the right thing.
Add unit tests, or follow design by contract adding pre/post conditions and class invariants.
Learning to program C++ by writing a linked list is like learning math by adding 1 + 1. It is old fashioned thinking, slow and mostly boring without having any context.
Math isn't calculating, like C++ programming isn't pointer manipulation. At some stage you might need to know about it, but your better off learning other important things like stl and boost.
If it was understood that append() ment create something, find the end of the list, add it. you could then see that in you append function you have create something mixed uyp with move to the end of the list, but you never add it.
DEAR All;
Hi, I'm just beginner to C++;
Please help me to understand:
What functions should be in the Linked list class ?
I think there should be overloaded operators << and >>;
Please help me to improve the code (style, errors, etc,)
Thanks for advance. Igal.
Edit:
This is only first stage, the next one will be (hopefully) with templates.
Please review the small code for the integer List (enclosed MyNODE.h and ListDriver1.cpp);
MyNODE.h
// This is my first attempt to write linked list. Igal Spector, June 2010.
#include <iostream.h>
#include <assert.h>
//Forward Declaration of the classes:
class ListNode;
class TheLinkedlist;
// Definition of the node (WITH IMPLEMENTATION !!!, without test drive):
class ListNode{
friend class TheLinkedlist;
public:
// constructor:
ListNode(const int& value, ListNode *next= 0);
// note: no destructor, as this handled by TheLinkedList class.
// accessor: return data in the node.
// int Show() const {return theData;}
private:
int theData; //the Data
ListNode* theNext; //points to the next node in the list.
};
//Implementations:
//constructor:
inline ListNode::ListNode(const int &value,ListNode *next)
:theData(value),theNext(next){}
//end of ListNode class, now for the LL class:
class TheLinkedlist
{
public:
//constructors:
TheLinkedlist();
virtual ~TheLinkedlist();
// Accessors:
void InsertAtFront(const &);
void AppendAtBack(const &);
// void InOrderInsert(const &);
bool IsEmpty()const;//predicate function
void Print() const;
private:
ListNode * Head; //pointer to first node
ListNode * Tail; //pointer to last node.
};
//Implementation:
//Default constructor
inline TheLinkedlist::TheLinkedlist():Head(0),Tail(0) {}
//Destructor
inline TheLinkedlist::~TheLinkedlist(){
if(!IsEmpty()){ //list is not empty
cout<<"\n\tDestroying Nodes"<<endl;
ListNode *currentPointer=Head, *tempPtr;
while(currentPointer != 0){ //Delete remaining Nodes.
tempPtr=currentPointer;
cout<<"The node: "<<tempPtr->theData <<" is Destroyed."<<endl<<endl;
currentPointer=currentPointer->theNext;
delete tempPtr;
}
Head=Tail = 0; //don't forget this, as it may be checked one day.
}
}
//Insert the Node to the beginning of the list:
void TheLinkedlist::InsertAtFront(const int& value){
ListNode *newPtr = new ListNode(value,Head);
assert(newPtr!=0);
if(IsEmpty()) //list is empty
Head = Tail = newPtr;
else { //list is NOT empty
newPtr->theNext = Head;
Head = newPtr;
}
}
//Insert the Node to the beginning of the list:
void TheLinkedlist::AppendAtBack(const int& value){
ListNode *newPtr = new ListNode(value, NULL);
assert(newPtr!=0);
if(IsEmpty()) //list is empty
Head = Tail = newPtr;
else { //list is NOT empty
Tail->theNext = newPtr;
Tail = newPtr;
}
}
//is the list empty?
inline bool TheLinkedlist::IsEmpty() const
{ return (Head == 0); }
// Display the contents of the list
void TheLinkedlist::Print()const{
if ( IsEmpty() ){
cout << "\n\t The list is empty!!"<<endl;
return;
}
ListNode *tempPTR = Head;
cout<<"\n\t The List is: ";
while ( tempPTR != 0 ){
cout<< tempPTR->theData <<" ";
tempPTR = tempPTR->theNext;
}
cout<<endl<<endl;
}
//////////////////////////////////////
The test Driver:
//Driver test for integer Linked List.
#include <iostream.h>
#include "MyNODE.h"
// main Driver
int main(){
cout<< "\n\t This is the test for integer LinkedList."<<endl;
const int arraySize=11,
ARRAY[arraySize]={44,77,88,99,11,2,22,204,50,58,12};
cout << "\n\tThe array is: "; //print the numbers.
for (int i=0;i<arraySize; i++)
cout<<ARRAY[i]<<", ";
TheLinkedlist list; //declare the list
for(int index=0;index<arraySize;index++)
list.AppendAtBack( ARRAY[index] );//create the list
cout<<endl<<endl;
list.Print(); //print the list
return 0; //end of the program.
}
What functions should be in the Linked list class ?
That depends on what you need to do with it. At the very least, one should probably be able to add elements to it, and to look at the elements in the list.
(This is common sense. Because if you can't modify or read your list in any way, what could it ever be used for?)
I think there should be overloaded operators << and >>;
Why? What would they do? I suppose you mean operator << to do insertion, similar to how objects are inserted into C++ IO streams; but what exactly should operator >> do? Extraction/removal of elements of some sort? If you implement insertion and extraction (?) in this manner, probably noone will be able to understand your linked list class. A linked list is not an IO stream. (Those operators with IO streams were chosen for brevity.)
I would advise you against operator overloading if the meaning of the operation is not clear. I would suggest you name your operations more explicitly, e.g. by providing methods add and remove (I'm still guessing at the meaning of the latter operation >> btw.).
Please help me to improve the code (style, errors, etc,)
I don't want to make this the main point on my answer, so just very briefly off the top of my head, some issues:
You should #include <iostream> instead of #include <iostream.h>, and then either add a using namespace std; or write (e.g.) std::cout instead of cout.
Try to get rid of the friend. You should be able to design your classes in a way that doesn't require this. friend is easily misused to get around proper encapsulation. But encapsulation is something you should definitely think about in OOP.
Though that's not an advice to give to a C++ beginner, if you made your linked list class into a template class, it could store different values than just ints. Just take this as a hint for future improvements.
And finally:
Just use the STL ("Standard Template Library") containers which are included in the C++ standard library. I know that "rolling your own" helps understanding how these data structures work, but be aware that the C++ standard library already includes a solid and efficient set of data containers.
0 should be NULL
inline only in the case that you don't care that your code will be public, usually implementation puts in separate file Mylist.cpp file.
Why your destructor virtual, do you have inheritance ?
You can just define struct node instead separate class its better define your list for practice like in stl. http://www.sgi.com/tech/stl/List.html http://www.cplusplus.com/reference/stl/list/
In C++ common to use vector vs linked list in Java
http://www.yolinux.com/TUTORIALS/LinuxTutorialC++STL.html