I'm creating a binary tree and trying to print the names of a student object which im passing in. When I try to print the tree, I get an error:
tree.h:181:46: error: ‘class samuel::Student’ has no member named ‘printInOrder’
str += Node->get_data().printInOrder() + "\n";
This is the function I'm calling in main using
BSTree<Student>* student_tree = new BSTree<Student>;
Student student = Student("Adam");
student_tree->insert(student);
student_tree->printInOrder();
string printInOrder(){return inOrder(root, 0);}
private:
string inOrder(BTNode<value_type>* Node, size_t level)
{
string str ="";
if(Node != NULL)
{
str += inOrder(Node->get_right(), level++);
for(int i = 1; i <= level; ++i)
{
str = str + "| ";
}
str += Node->get_data().printInOrder() + "\n";
str += inOrder(Node->get_left(), level++);
}
return str;
}
I'm not sure why when I try to access printInOrder it goes through Student. This is my student class
typedef Student value_type;
Student::Student()
{
}
Student::Student(std::string init_name, float init_grade)
{
name = init_name;
std::string studentName[50]={"Adam", "Cameron", "Jackson", "KiSoon", "Nicholas", "Adrian", "Chris", "Jacob", "Lance", "Ryan",
"Alexander", "Damian", "James", "Liam", "Sang", "Andrew", "David", "Jared", "Madison", "Shane", "Ashley", "Dillon",
"Jodi", "Magdalena", "Simon", "Benjamin", "Dylan", "Jonathan", "Marcus", "Thomas", "Bradley", "Ethan" "Joshua", "Mark",
"Timothy", "Brobie", "Frederik", "Julius", "Melanie", "Trent", "Callan", "Hong", "Kelly", "Min", "Troy", "Callum", "Hugh", "Kenias", "Mitchell", "Zaanif"};
for (int i = 0; i <50; i++)
{
int j = (rand() % (i-1));
string temp = studentName[j];
studentName[j] = studentName[i];
studentName[i] = temp;
}
}
Student::~Student()
{
}
void Student::set_name(string new_name)
{
name = new_name;
}
const string Student::get_name() const
{
return name;
}
void Student::set_grade(float new_grade)
{
grade = new_grade;
}
float Student::get_grade()
{
return grade;
}
An alternative method I tried was using
string infix(BTNode<value_type>* Node)
{
if (Node == NULL)
{
return "";
}else{
return (infix(Node->get_left()) + Node->get_data()) +
infix(Node->get_right());
}
}
friend ostream& operator << (ostream& out, const BSTree<value_type>& tree)
{
out << tree.infix(tree.root) << endl;
return out;
}
and then calling cout << student_tree << endl however this printed a memory address, would anyone also be able to clarify why that happens as well, thanks
Edit: Changed how I was inserting a student. Changed cout << student_tree << endlto cout << *student_tree << endlwhich gave the error
tree.h:70:9: error: passing ‘const samuel::BSTree’ as ‘this’ argument discards qualifiers [-fpermissive]
out << tree.infix(tree.root) << endl;
tree.h:181:46: error: ‘class samuel::Student’ has no member named ‘printInOrder’
Node->get_data() returns object of samuel::Student type because of this compiler searches for printInOrder() in samuel::Student type. It's not there according to the code above. To fix the issue implement the method:
std::string Student::printInOrder()
{
// Return the data to be printed
}
student_tree->insert(* new Student());
Looks suspicious. Tree contains Student objects by value. You create an Student object on the heap, dereference pointer and copies value into the Tree. Pointer lost after that. This will cause memory leak problem.
cout << student_tree << endl however this printed a memory address
Because it's declared as BSTree<Student>* student_tree. It's a pointer to the tree, so the output is correct, you print the address. To print the tree value you need to dereference the pointer: cout << *student_tree << endl.
continuation to other answer...
and then calling cout << student_tree << endl however this printed a
memory address, would anyone also be able to clarify why that happens
as well, thanks
BSTree<Student>* student_tree = new BSTree<Student>;
student_tree is a pointer to BSTree<Student> it means it holds the memory location(a memory address) of BSTree object which is an unnamed object in this case.
you must dereference it to get the value inside the address by doing *student_tree
std::cout << *student_tree; // actual value, and will call operator<<
Related
This may be a dumb question but I'm getting pretty desperate at this point.
I am attempting to create an array of pointers:
struct vertex
{
std::string id;
std::string name;
int networkID;
std::vector<adjVertex> friends;
bool visited;
};
struct hobbylist
{
std::string hobby;
std::vector<vertex*> list;
};
hobbylist * hobbies[HASHMAP_SIZE];
int Graph::addUserToHobby(std::string hobby1, std::string id){
//cout << "Adding to hobby: " << hobby1 << " user: " << id << endl;
vertex *user = findVertex(id);
int collisions = 0;
// initial key is based on the first 2 characters of the hobby name
int key = (hobby1[0] + hobby1[1]) % HASHMAP_SIZE;
//cout << " initial hashmap key " << key << endl;
hobbylist *h = new hobbylist;
if(hobbies[key] == NULL){
h->hobby = hobby1;
h->list.push_back(user);
hobbies[key] = h;}
else if (hobbies[key]!=NULL){
hobbies[key]->list.push_back(user);
collisions++;}
return collisions;
}
I am getting a seg fault at the last line in the else statement in the addUserToHobby function when running the function the first time and I am confused why the function would go to the else statement when the array should be empty and therefore hobbies[key] should be null the first time the function is run? Upon further inspection the function will always enter the else statement, so the array values are never null?
Each location is the array is not set to null by default, it's just whatever trash was in there before you allocated it.
I suck at c++ so i suspect it's a dumb mistake I have made. After a bit of research I see that that STATUS_ACCESS_VIOLATION happens when the program tries to access invalid memory blocks. That said I'm not seeing what is causing that to happen in the code below.
int main() {
cout << "!!!Hello World!!!" << endl;
Node* testNode = new Node("jhon","doe", 1, 80);
BraidedLinkedList* testList = new BraidedLinkedList();
testList->AddNode(testNode);
return 0;}
BraidedLinkedList.cpp
void BraidedLinkedList::AddNode(Node *newNode) {
if (this->start == NULL) {
this->start = newNode;
cout<<newNode->getInfo();
//the following line does not work either
//cout<<this->start->getInfo()<<endl;
}
Node.cpp
const string& Node::getInfo() {
string returnString = "";
returnString += this->getFristName() + " ";
returnString += this->getLastName() + " ";
returnString += this->getId() + " ";
returnString += this->getGrade() + " ";
}
Your 'Node::getInfo' method is returning a const reference to a temporary string object. At the point at which it attempts to print the string it's highly likely it could crash. I'm assuming you simply left out the return. In this scenario the return type should simply be 'string'.
I wrote a simple function to perform in place reversal:
void in_place_reverse(char *str){
if(!str || !(*str)){
return;
}
char *str_end = str+strlen(str)-1;
int temp;
while(str < str_end){
temp = *str;
*(str++) = *str_end;
*(str_end--) = temp;
}
}
I'm just wondering why when I do something like this:
char str[] = "Reverse me!";
cout << "Original: " << str << endl;
in_place_reverse(str);
cout << "Reversed: " << str << endl;
str wasn't changed inside of the function. The reason I ask is because the line *(str++) is incrementing the pointer that points to str. So what I'm really asking is why something like this isn't necessary:
char *str_beg = str;
char *str_end = str+strlen(str)-1;
int temp;
while(str_beg < str_end){
temp = *str_beg;
*(str_beg++) = *str_end;
*(str_end--) = temp;
}
So that we're not actually changing the pointer that points to the first position of str.
You actually are doing this implicitely because 'str' is passed by value (read: 'as a copy in a temporary variable').
To clarify this without the (distracting) pointer: consider
void increment(int x) {
x++;
}
int i = 1;
cout << i << endl;
increment(i);
cout << i << endl;
This will print '1' twice. The x that is seen inside the increment routine has the same value like the passed i. But it is not the same variable i. In fact it is a copy of i. When we return from the routine, the copy is discarded. Further reading: This would be different if we'd pass x by reference, like so:
void increment(int &x) {
x++;
}
The declaration of the function void in_place_reverse(char *str) results in a copy of the pointer being created when the function is called, in a variable called str that is private and local to the in_place_reverse. You can modify this value all you like without affecting the original that exists in the scope of the calling function.
I realize the way I am approaching this is wrong, but I don't know why.
I am very new to C++/programming in general.
I want my program to do the following.
If I cin "setwanted joe" I want it to store joe into a char array. I have it so I can succesfully seperate and cout joe, but I am can't return the char array from the function.
Here's my example code.
char * GETNAME (char *searchinput, char*searchtext)
{
char returnname[64];
int starter=0;
for(;;)
{
if (*searchinput == *searchtext)
{
searchinput++;
searchtext++;
}
if (*searchinput == ' ')
{
searchinput++;
searchtext++;
}
if (*searchinput!='\0' && *searchinput!= *searchtext && *searchinput != ' ')
{
returnname[starter] = *searchinput;
starter++;
searchinput++;
searchtext++;
}
if (*searchinput=='\0')
{
returnname[starter]='\0';
cout << "Char Array to Return: " << returnname << endl;
return returnname;
}
}
}
Above is the function I made to try to return the name from the char array.
Here is the code I was using to call the function.
char Recv[256];
cin >> Recv;
char * wantedname = new char[64];
wantedname = GETNAME(Recv,"setwanted");
cout << "Returned Name: " << wantedname << endl;
Thanks for reading/your patience I know this is messy.
Use std::array, std::vector or std::string (in case of array of characters) to easily return an array of items. You're code invokes undefined behavior due to returning a pointer to a local temporary object. I prefer this
std::string GETNAME(const std::string &searchinput,const std::string &searchtext)
{
std::string returnname;
...
return returnname;
}
I'm trying to create constructor taking reference to an object. After creating object using reference I need to prints field values of both objects. Then I must delete first object, and once again show values of fields of both objects. My class Person looks like this :
class Person {
char* name;
int age;
public:
Person(){
int size=0;
cout << "Give length of char*" << endl;
cin >> size;
name = new char[size];
age = 0;
}
~Person(){
cout << "Destroying resources" << endl;
delete[] name;
delete age;
}
void init(char* n, int a) {
name = n;
age = a;
}
};
Here's my implementation (with the use of function show() ). My professor said that if this task is written correctly it will return an error.
#include <iostream>
using namespace std;
class Person {
char* name;
int age;
public:
Person(){
int size=0;
cout << "Give length of char*" << endl;
cin >> size;
name = new char[size];
age = 0;
}
Person(const Person& p){
name = p.name;
age = p.age;
}
~Person(){
cout << "Destroying resources" << endl;
delete[] name;
delete age;
}
void init(char* n, int a) {
name = n;
age = a;
}
void show(char* n, int a){
cout << "Name: " << name << "," << "age: " << age << "," << endl;
}
};
int main(void) {
Person *p = new Person;
p->init("Mary", 25);
p->show();
Person &p = pRef;
pRef->name = "Tom";
pRef->age = 18;
Person *p2 = new Person(pRef);
p->show();
p2->show();
system("PAUSE");
return 0;
}
The problem with your copy constructor is that it merely assigns p.name:
name = p.name // Now this and p hold a pointer to the same memory
Since both this and p now hold a pointer to the same memory location, whichever one destructs first will free the memory while the second one will be holding a pointer to a non-existent object. Subsequently using that pointer or deleting it will result in undefined behavior. The solution is to allocate a new array for name and copy the contents of p.name into that array, so that the memory isn't shared.
Likewise, your init function overwrites name, ignoring the fact that memory has been allocating (it is a memory leak) and also ignoring the fact that the string will later be destructed (even though the caller probably expects to own and free that string, itself). Also, I should point out that your show function takes a parameter "n", but uses "name", instead. Your show function probably shouldn't take any parameters (indeed, the way you call it implies that it doesn't), given that all the needed fields are already present in your class (or maybe you intended for that to be a freestanding function that takes the fields of the class?). You should take another look at your code for additional errors.
First of all, try to compile your code (it is usually a good idea to compile code before posting it on SO.) It contains several errors and compiler will show them. Second part will be to change the following:
p->init("Mary", 25);
to
{
std::string mary("Mary");
p->init(mary.c_str(), 25);
}
It should give you an error at runtime and it will give you a chance to find a problem in your implementation.