Deleting nodes from a tree

I am trying to delete specific nodes from a tree that end in .net but I get an Error 1 error C2664: 'int remove(const char *)' : cannot convert argument 1 from 'std::string' to 'const char *'

and I don't understand what that is or what the fix might be. Any help is greatly appreciated.

email file looks something like this but with a lot more data

a@a.net
b@b.com
c@a.com
c@a.org
a@v.net


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167

#include<iostream>
#include<fstream>
#include<string>
using namespace std;

struct emailTree
{
	string emailName;
	emailTree *lchild;
	emailTree *rchild;
};

emailTree *root = NULL;

void insert(emailTree *&nodePtr, emailTree *&newNode) //inserts the nodes
{
	if (nodePtr == NULL)
	{
		nodePtr = newNode;
	}
	else if (newNode->emailName < nodePtr->emailName)
	{
		insert(nodePtr->lchild, newNode);
	}
	else
	{
		insert(nodePtr->rchild, newNode);
	}

}

void insertNode(string name) //inserts the nodes
{
	emailTree *newNode = NULL;

	newNode = new emailTree;
	newNode->emailName = name;
	newNode->lchild = NULL;
	newNode->rchild = NULL;

	insert(root, newNode);
}

void read() //reads in the emails
{
	ifstream infile;
	infile.open("email.txt");
	string eName;

	while (!infile.eof())
	{
		getline(infile, eName);
		eName.erase(eName.end() - 1);
		insertNode(eName);
	}

}

void displayTree(emailTree *nodePtr) //displays the tree in preorder
{
	if (nodePtr == NULL)
	{
		return;
	}
		displayTree(nodePtr->lchild);
		cout << nodePtr->emailName << endl;
		displayTree(nodePtr->rchild);
}

bool netEnd(emailTree *nodePtr)//// checks to see if the ending is a .net
{
	string ending = ".net";
	if (nodePtr->emailName >= ending)
	{
		return (0 == nodePtr->emailName.compare(nodePtr->emailName.length() - ending.length(), ending.length(), ending));
	}
	else
	{
		return false;
	}
}

void deletion(emailTree *&nodePtr) /// deletes the node from the tree
{
	emailTree *temp = NULL;

	if (nodePtr == NULL)
	{
		cout << "Empty tree" << endl;
	}
	else if (nodePtr->rchild == NULL)
	{
		temp = nodePtr;
		nodePtr = nodePtr->lchild;
		delete temp;
	}
	else if (nodePtr->lchild == NULL)
	{
		temp = nodePtr;
		nodePtr = nodePtr->rchild;
		delete temp;
	}
	else
	{
		temp = nodePtr->rchild;

		while (temp->lchild)
		{
			temp = temp->lchild;
		}

		temp->lchild = nodePtr->lchild;
		temp = nodePtr;
		nodePtr = nodePtr->rchild;
		delete temp;
	}
}

void displayNet(emailTree *&nodePtr) //displays all the .net email addresses
{                                    //then should call the remove function but doesn't work
	if (nodePtr == NULL)
	{
		return;
	}
	displayNet(nodePtr->lchild);
	if (netEnd(nodePtr))
	{
		cout << nodePtr->emailName << endl;
		remove(nodePtr->emailName);  ////////I get an error right here
	}
	displayNet(nodePtr->rchild);
}

void deleteNet(emailTree *&nodePtr, string email) ///goes through the tree searching to delete
{
	if (email < nodePtr->emailName)
	{
		deleteNet(nodePtr->lchild, email);
	}
	else if (email > nodePtr->emailName)
	{
		deleteNet(nodePtr->rchild, email);
	}
	else
	{
		deletion(nodePtr);
	}
}

void remove(string email) //passes the tree and email to the deletNet function
{
	deleteNet(root, email);
}

int main()
{

	read();
	displayTree(root);
	cout << endl;
	displayNet(root);
	cout << endl;
	displayTree(root);

	return 0;
}
Hi, didn't look through all your code, but in response to this:
but I get an Error 1 error C2664: 'int remove(const char *)' : cannot convert argument 1 from 'std::string' to 'const char *'
To make std::string get passed as a c_string, you need to pass
my_string.c_str() into the function that expects a const char*


Edit:
In other words, do this:
1
2
3
4
5
	if (netEnd(nodePtr))
	{
		cout << nodePtr->emailName << endl;
		remove(nodePtr->emailName.c_str());  ////////I get an error right here
	}


That made it compile for me.

That being said, the error is weird since your remove function is expecting a string, I'm honestly not sure what's going on.
Last edited on
I did that and it makes it compile, but it doesn't delete anything. I realized that it doesn't actually call the remove function it just skips over it for some reason. I figured that out by putting a cout statement in the remove function and it never does it. Why is that happening?
Last edited on
Your program is calling the wrong remove function. You can tell because the error says int remove(const char *) while your function is void remove(string email). The return type and parameters are both different. I assume that this is the function being called:

http://en.cppreference.com/w/cpp/io/c/remove

Not sure how to fix it. I suppose you could always remove the using namespace std; so that the program knows you're not trying to use int std::remove(const char *).
Last edited on
I fixed the problem by moving all of my functions to the bottom of my program, but that gives me another problem. In my displayNet function I get an error on the
1
2
3
4
if(nodePtr == NULL)
{
   return;
}

when nodePtr is equal to NULL it causes an error instead of returning. I have also included my new code with more comments around the error.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
#include<iostream>
#include<fstream>
#include<string>
using namespace std;

struct emailTree
{
	string emailName;
	emailTree *lchild;
	emailTree *rchild;
};

emailTree *root = NULL;

void insert(emailTree *&nodePtr, emailTree *&newNode); //inserts the nodes

void insertNode(string name); //inserts the nodes

void read(); //reads in the emails

void displayTree(emailTree *nodePtr); //displays the tree in preorder

bool netEnd(emailTree *nodePtr);//// checks to see if the ending is a .net

void deletion(emailTree *&nodePtr); /// deletes the node from the tree

void remov(string email); //passes the tree and email to the deletNet function

void displayNet(emailTree *&nodePtr); //displays all the .net email addresses
                                  //then should call the remove function but doesn't work

void deleteNet(emailTree *&nodePtr, string email); ///goes through the tree searching to delete


int main()
{

	read();
	displayTree(root);
	cout << endl;
	displayNet(root);
	cout << endl;
	displayTree(root);

	return 0;
}

void insert(emailTree *&nodePtr, emailTree *&newNode) //inserts the nodes
{
	if (nodePtr == NULL)
	{
		nodePtr = newNode;
	}
	else if (newNode->emailName < nodePtr->emailName)
	{
		insert(nodePtr->lchild, newNode);
	}
	else
	{
		insert(nodePtr->rchild, newNode);
	}

}

void insertNode(string name) //inserts the nodes
{
	emailTree *newNode = NULL;

	newNode = new emailTree;
	newNode->emailName = name;
	newNode->lchild = NULL;
	newNode->rchild = NULL;

	insert(root, newNode);
}

void read() //reads in the emails
{
	ifstream infile;
	infile.open("email.txt");
	string eName;

	while (!infile.eof())
	{
		getline(infile, eName);
		eName.erase(eName.end() - 1);
		insertNode(eName);
	}

}

void displayTree(emailTree *nodePtr) //displays the tree in preorder
{
	if (nodePtr == NULL)
	{
		return;
	}
	displayTree(nodePtr->lchild);
	cout << nodePtr->emailName << endl;
	displayTree(nodePtr->rchild);
}

bool netEnd(emailTree *nodePtr)//// checks to see if the ending is a .net
{
	string ending = ".net";
	if (nodePtr->emailName >= ending)
	{
		return (0 == nodePtr->emailName.compare(nodePtr->emailName.length() - ending.length(), ending.length(), ending));
	}
	else
	{
		return false;
	}
}

void deletion(emailTree *&nodePtr) /// deletes the node from the tree
{
	emailTree *temp = NULL;

	if (nodePtr == NULL)
	{
		cout << "Empty tree" << endl;
	}
	else if (nodePtr->rchild == NULL)
	{
		temp = nodePtr;
		nodePtr = nodePtr->lchild;
		delete temp;
	}
	else if (nodePtr->lchild == NULL)
	{
		temp = nodePtr;
		nodePtr = nodePtr->rchild;
		delete temp;
	}
	else
	{
		temp = nodePtr->rchild;

		while (temp->lchild)
		{
			temp = temp->lchild;
		}

		temp->lchild = nodePtr->lchild;
		temp = nodePtr;
		nodePtr = nodePtr->rchild;
		delete temp;
	}
}

void remov(string email) //passes the tree and email to the deletNet function
{
	cout << "here" << endl;
	deleteNet(root, email);
}

void displayNet(emailTree *&nodePtr) //displays all the .net email addresses
{                                    //then should call the remove function but doesn't work
	if (nodePtr == NULL) ///This is where I put my stopper in the debugger because it messes up when nodePtr is NULL why does this happen
	{					/// why does it not just go the return statement thats what I make it do in the debugger and it seems to work fine
		return;
	}
	displayNet(nodePtr->lchild);
	if (netEnd(nodePtr))
	{
		cout << nodePtr->emailName << endl;
		remov(nodePtr->emailName);  ////////I get an error right here
	}
	displayNet(nodePtr->rchild);

}

void deleteNet(emailTree *&nodePtr, string email) ///goes through the tree searching to delete
{
	if (email < nodePtr->emailName)
	{
		deleteNet(nodePtr->lchild, email);
	}
	else if (email > nodePtr->emailName)
	{
		deleteNet(nodePtr->rchild, email);
	}
	else
	{
		deletion(nodePtr);
	}
}
void displayNet(emailTree *&nodePtr); should be void displayNet(emailTree *nodePtr);. Same for all the other functions with *&nodePtr.
Why should I get rid of the *&nodePtr because in my text book that is the way they have it? I also get the same error without the &'s
Last edited on
I figured out the reason. It's because you don't return anything from your insertion functions. I guess your new nodes that you create with new are automatically deleted when the function returns and the variables go out of scope. Though that doesn't make sense to me since that invalidates the reason we need to use delete, it's the only explanation I can think of.

See this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include <iostream>
#include <string>

using namespace std;

struct TreeNode
{
    string name;
    TreeNode *lchild;
    TreeNode *rchild;
};

void displayTree(TreeNode *node)
{
    if (node == NULL)
        return;
    displayTree(node->lchild);
    cout << node->name << '\t';
    displayTree(node->rchild);
}

TreeNode * insertNode(TreeNode *node, string str)
{
    if (node == NULL)
    {
        node = new TreeNode;
        node->name = str;
        node->lchild = NULL;
        node->rchild = NULL;
    }
    else if (str < node->name)
        node->lchild = insertNode(node->lchild, str);
    else
        node->rchild = insertNode(node->rchild, str);
    return node;
}

void deleteTree(TreeNode *node)
{
    if (node == NULL)
        return;
    deleteTree(node->lchild);
    deleteTree(node->rchild);
    delete node;
    node = NULL;
}

int main()
{
    TreeNode *root = NULL;
    root = insertNode(root, "John Doe");
    displayTree(root);
    cout << endl;
    root = insertNode(root, "Jane Doe");
    displayTree(root);
    cout << endl;
    root = insertNode(root, "Mary Sue");
    displayTree(root);
    cout << endl;
    root = insertNode(root, "Gary Stu");
    displayTree(root);
    deleteTree(root);
    return 0;
}

As opposed to this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include <iostream>
#include <string>

using namespace std;

struct TreeNode
{
    string name;
    TreeNode *lchild;
    TreeNode *rchild;
};

void displayTree(TreeNode *node)
{
    if (node == NULL)
        return;
    displayTree(node->lchild);
    cout << node->name << '\t';
    displayTree(node->rchild);
}

void insertNode(TreeNode *node, string str)
{
    if (node == NULL)
    {
        node = new TreeNode;
        node->name = str;
        node->lchild = NULL;
        node->rchild = NULL;
    }
    else if (str < node->name)
        insertNode(node->lchild, str);
    else
        insertNode(node->rchild, str);
}

void deleteTree(TreeNode *node)
{
    if (node == NULL)
        return;
    deleteTree(node->lchild);
    deleteTree(node->rchild);
    delete node;
    node = NULL;
}

int main()
{
    TreeNode *root = NULL;
    insertNode(root, "John Doe");
    displayTree(root);
    cout << endl;
    insertNode(root, "Jane Doe");
    displayTree(root);
    cout << endl;
    insertNode(root, "Mary Sue");
    displayTree(root);
    cout << endl;
    insertNode(root, "Gary Stu");
    displayTree(root);
    deleteTree(root);
    return 0;
}
My insertions work fine my code will display the entire tree and will display the .net emails too when I comment out the remov function call in the displayNet function. The only thing that messes up is the remov function when it's in there. I stepped through it debugging and after it returns from the remov function it calls displayNet (nodePtr->rchild) it should be NULL then it checks if (nodePtr == NULL) and it stops working because nodePtr is NULL. It never makes it to the return statement in that if statement like it should which makes no sense to me.
OK, ignore my last two posts. I guess I'm still just a beginner and didn't know how the parameter passing worked. I thought passing *&nodePtr meant passing a pointer to the address of your nodePtr, which didn't make sense to me. Instead, it means passing the address (ie reference) of nodePtr, which does make sense. I couldn't get insertion to work because I changed it.

Now for your current problem, I'm not sure what's wrong. I can compile and run what you have right now without any problems. Maybe it has to do with the data you're inputting and your deletion functions. Suppose that you input F, H, G, I, J in that order.

The root node is F, F's right child is H, H's left child is G and right child is I, I's right child is J. So your tree looks like this:

F
  \
    H
  /   \
G       I
          \
            J

Let's say that F, H and G are addresses that end in ".net" but the others don't. When you call displayNet(), it first checks for the left children of F. There is none, so now it goes and checks F. F ends it ".net" so it goes right ahead and deletes F, and now the nodePtr is at H. Since the function has already checked for the left child of nodePtr and nodePtr itself, now it checks nodePtr's right children. In other words, it skips checking H and G.

EDIT: You also have to be careful when calling void deleteNet(emailTree *&nodePtr, string email). If email doesn't exist in your tree, that would lead to an infinite loop.
Last edited on
I see exactly what the problem was and I rewrote a few lines and added a new function and got it running exactly as it should. I also fixed that infinite loop problem. I appreciate all the help!
Topic archived. No new replies allowed.