PPP2 Chapter 17 Exercise 11

Pages: 1... 111213141516
Why all the code duplication? Shouldn't the logic be the same no matter what myth your playing with (other than the search myth and the Link to move the item into)?

How can you eliminate this code duplication?

Create a separate "move" function?
It keeps inserting only the first node whose myth string matches the passed in string and then exiting. It seems like trav and m_succ become nullptr at the time it exits so that should be the reason, but I don't get how to make it keep going as long as there are still nodes with myth strings that match the passed in string. If erasing a node makes the place where the node was previously become nullptr and that's what's causing the problem, is there any way I could clean that up so that it doesn't have to exit the loop prematurely?

This is my current code for the moving function:
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
Link *Link::move_nodes(Link *list, const std::string &myth)
{
	Link *trav = this;
	if (!trav)
	{
		return this;
	}
	while (trav->m_prev != nullptr)
	{
		trav = trav->m_prev;
	}

	while (trav)
	{
		if (trav && trav->m_god.m_myth == myth)
		{
			trav->erase();
			if (trav && trav->m_god.m_myth == myth && trav->m_god.m_name != list->m_god.m_name)
			{
				list = list->add_ordered(trav);
			}
			else if (trav && m_god.m_myth != myth)
			{
				trav = trav->m_succ;
			}
			if (!trav)
			{
				trav = this;
			}
		}
		trav = trav->m_succ;
	}
	return list;
}


The gods list has 4 gods from each of the three myths right now, but it's only putting one node into the separate myth lists. One is there from the beginning, so that makes two out of four. For the Norse list is it's only Baldr and Odin since I put Odin in there when initializing the list so that the program doesn't crash because I tried to access a garbage pointer; for the Greek list it's Ares and Zeus (Zeus was there from initialization), and for the Japanese one it's Amaterasu and Bishamonten (Amaterasu was there from initialization).
Last edited on
Create a separate "move" function?

Yes a function would be a suggestion. However it probably shouldn't be a class member function since it is modifying two separate instances.

One is there from the beginning, so that makes two out of four.

What? If all of your functions are correctly implemented it shouldn't require special care to "insert" the first element into the chain of Links.

So if a list pointer was just declared and there's a danger of some garbage pointer address being there, would it be fine to call add_ordered() on it and insert a node anyway? When I tried it once before, my program crashed. Or does this mean add_ordered() is still wrong somehow?

Anyway, I made move_nodes() a member function. I'll change it to a non-member function and try this again.
When I tried it once before, my program crashed. Or does this mean add_ordered() is still wrong somehow?

I won't, at this time, comment on add_ordered() because too much time has elapsed since you last posted the code. But since add_ordered() should be using insert() or add() those are the functions you need be concerned with not really add_ordered().

So if a list pointer was just declared and there's a danger of some garbage pointer address being there, would it be fine to call add_ordered() on it and insert a node anyway?


Short answer, don't call any of your functions with some garbage pointer.

You need to properly initialize that first element either by initially assigning pointer to a valid instance of a Link (as you've been doing) or initializing the pointer to a nullptr.

Then if your insert() code is correct (basically the same as published in the book) the code should insert the "next" instance properly. And remember the add() code should be quite similar to the insert() code with the only differences being what pointers are being manipulated.

insert() and add():
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
Link *Link::insert(Link *n)
{
	if (n == nullptr)
	{
		error("Node to add cannot be null");
	}
	n->m_succ = this;
	if (m_prev)
	{
		m_prev->m_succ = n;
	}
	n->m_prev = m_prev;
	m_prev = n;
	return n;
}

Link *Link::add(Link *n)
{
	if (n == nullptr)
	{
		error("Node to add cannot be null");
	}
	n->m_prev = this;
	if (m_succ)
	{
		m_succ->m_prev = n;
	}
	n->m_succ = m_succ;
	m_succ = n;
	return n;
}


add_ordered():
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
Link *Link::add_ordered(Link *n)
{
	if (!n)
	{
		error("Node to insert cannot be null");
	}
	
	
	Link *trav = this;
	if (!trav)
	{
		return this;
	}

	// to make sure to start at head of the list
	while (trav->m_prev != nullptr)
	{
		trav = trav->m_prev;
	}

	while (trav->m_god.m_name < n->m_god.m_name && trav->m_succ)
	{
		trav = trav->m_succ;
	}

	if (n->m_god.m_name < trav->m_god.m_name)
	{
		trav = trav->insert(n);
	}
	else if (!(n->m_god.m_name < trav->m_god.m_name))
	{
		trav = trav->add(n);
	}
	else if (n->m_god.m_name == trav->m_god.m_name)
	{
		// do nothing
	}
	return trav;
}


The move function:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void move_nodes(Link *dest_list, Link *source_list, const std::string &myth)
{
	Link *trav = source_list;
	while ((trav = source_list->find_if_myth(myth)))
	{
		if (trav)
		{
			if (trav == source_list)
			{
				trav = source_list->next();
			}
			if (trav->god().m_myth == myth)
			{
				trav->erase();
				if (trav->god().m_name != dest_list->god().m_name)
				{
					dest_list = dest_list->add_ordered(trav);
				}
			}
		}
	}
}


This keeps going into an infinite loop after a while. It seems like it can't get past a certain point in the source list. And having trav move to the next node is not also not helping because that also makes it get stuck in an infinite loop eventually.

By the way, do you know enough about Wt to be able to help someone learn it or at least know someone who does? I want to learn Wt to create a web application. I'm not asking to learn it now but after this current problem is taken care of.
Well your insert() code doesn't match the code from the book.

This keeps going into an infinite loop after a while.

What does this even mean? When does it go into an endless loop? Your debugger (LOL) should be able to tell you what is happening.

It seems like it can't get past a certain point in the source list.

Again what does this even mean? What point are you talking about. Again debug or print information to tell you where you're at.

And having trav move to the next node is not also not helping because that also makes it get stuck in an infinite loop eventually.

Does your code even look like the code from the book?

By the way, do you know enough about Wt to be able to help someone learn it

Well since I have no idea what "Wt" is I doubt I would be of much help. If you want to make a web app I would say you need to find some other forum since this is probably not a C++ problem

Edit: I really recommend you start with one myth and get that to "move" properly before you move on to the rest of the Links.
Last edited on
Wt is the C++ Webtoolkit. It's a web framework for C++.

Anyway, about the move code. I did check in the debugger. It's how I know it's stuck at some point. After inserting some nodes into the destination list, it isn't able to go past the point in the source list that it's at so the loop keeps iterating over the same place over and over again.

The code in the book is trying to find just one god in the list to put him in the correct pantheon. The name string is known at compile-time. What I'm doing is a little different, though, isn't it? And I did try do it more like in the book, except for using a loop that iterates over the source list as long as there are still nodes with a myth string that matches the one passed in to the function, but that didn't work either. Like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void move_nodes(Link *dest_list, Link *source_list, const std::string &myth)
{
	Link *trav = source_list->find_if_myth(myth);
	while ((trav = source_list->find_if_myth(myth)))
	{
		if (trav == source_list)
		{
			trav = source_list->next();
		}
		trav->erase();
		if (trav->god().m_name != dest_list->god().m_name)
		{
			dest_list = dest_list->add_ordered(trav);
		}
	}
}


And what's the _Right_data string in the xtring.h header? It keeps becoming nullptr on mine.

Unhandled exception thrown: read access violation.
_Right_data was nullptr.


This is code from the book for when he moved Zeus to the correct pantheon list:
1
2
3
4
5
6
Link* p2 = norse_gods->find("Zeus");
if (p2) {
    if (p2==norse_gods) norse_gods = p2->next();
    p2->erase();
    greek_gods = greek_gods->insert(p2);
}


Notice that mine is very similar to this and yet it doesn't work for trying to get multiple nodes matching the desired criteria into the other list.

And I did copy the code for insert() almost just as it was in the book. Here's the one from the book:
1
2
3
4
5
6
7
8
9
10
Link* Link::insert(Link* n) // insert n before this object; return n
{
    if (n==nullptr) return this;
    if (this==nullptr) return n;
    n–>succ = this; // this object comes after n
    if (prev) prev–>succ = n;
    n–>prev = prev; // this object’s predecessor becomes n’s predecessor
    prev = n; // n becomes this object’s predecessor
    return n;
}


I forgot and made some stuff different (I'll go change it back right now), but I aside from that it's the same.
Last edited on
The name string is known at compile-time. What I'm doing is a little different, though, isn't it?

Not really, it's basically the same thing. Just replace the "constant" with the desired myth, and "norse_gods" with the name of the Link you're trying to move the gods into.


Notice that mine is very similar to this and yet it doesn't work for trying to get multiple nodes matching the desired criteria into the other list.

Similar != Same. Your logic is different than the books logic, even taking into account the different names.


And I did copy the code for insert() almost just as it was in the book. Here's the one from the book:

Almost is the keyword here. Your code has at least a couple of differences that are critical.

I forgot and made some stuff different (I'll go change it back right now), but I aside from that it's the same.

What? Different is the keyword here!

I changed insert() to be the same as in the book. And my move code is the same as in the book except for the use of a while-loop. You can see that, can't you? I think I'm missing something else here.

And what's that string in xstring.h that keeps becoming null? What do I do about that?

insert():
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Link *Link::insert(Link *n)
{
	if (n == nullptr)
	{
		return this;
	}
	if (this == nullptr)
	{
		return n;
	}
	n->m_succ = this;    // this object comes after n
	if (m_prev)
	{
		m_prev->m_succ = n;
	}
	n->m_prev = m_prev;
	m_prev = n;
	return n;
}


add():
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Link *Link::add(Link *n)
{
	if (n == nullptr)
	{
		return this;
	}
	if (this == nullptr)
	{
		return n;
	}
	n->m_prev = this;
	if (m_succ)
	{
		m_succ->m_prev = n;
	}
	n->m_succ = m_succ;
	m_succ = n;
	return n;
}


I think I do need a loop in the move function, or else it'll exit the function after only inserting the first element each time it's called, no matter how many elements need to be inserted.

The move function in the book:
1
2
3
4
5
6
Link* p2 = norse_gods->find("Zeus");
if (p2) {
    if (p2==norse_gods) norse_gods = p2->next();
    p2->erase();
    greek_gods = greek_gods->insert(p2);
}


My move function:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void move_nodes(Link *dest_list, Link *source_list, const std::string &myth)
{
	Link *trav = source_list->find_if_myth(myth);
	while ((trav = source_list->find_if_myth(myth)))
	{
		if (trav == source_list)
		{
			trav = source_list->next();
		}
		trav->erase();
		if (trav->god().m_name != dest_list->god().m_name)
		{
			dest_list = dest_list->add_ordered(trav);
		}
	}
}


What am I missing? And would it help if I made it return something, or is that not the problem? A hint or two would probably help.

Edit: Wait, I see one possibly critical difference. I'll fix that and get back to you.

Edit2: Even after fixing that, there's still a problem. The Norse and Greek lists are both getting all of the gods, and the previous and this pointers of the Japanese one are apparently becoming null because my check for that in main is failing so that it isn't getting printed by print_all() at all.

My current code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void move_nodes(Link *dest_list, Link *source_list, const std::string &myth)
{
	Link *trav = source_list->find_if_myth(myth);
	while ((trav = source_list->find_if_myth(myth)))
	{
		if (trav == source_list)
		{
			source_list = trav->next();
		}
		trav->erase();
		if (trav->god().m_name != dest_list->god().m_name)
		{
			dest_list = dest_list->add_ordered(trav);
		}
	}
}


main():
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
int main()
{
	try
	{
		Link *gods = new Link{ { "Odin", "Norse", "Eight-legged flying horse called Sleipnir", "Spear called Gungnir" } };
		gods = gods->add_ordered(new Link{ { "Thor", "Norse", "Chariot pulled by goats Tanngrisnir and Tanngnjostr",
			"Hammer called Mjolnir" } });
		gods = gods->add_ordered(new Link{ { "Baldr", "Norse", "A giant ship called Hringorni", "None" } });
		gods = gods->add_ordered(new Link{ { "Frejya", "Norse", "Chariot pulled by two cats", "Magic called seidr" } });
		gods = gods->add_ordered(new Link{ { "Zeus", "Greek", "A chariot pulled by the four major winds shaped as horses",
			"Thunderbolt and the shield called Aegis" } });
		gods = gods->add_ordered(new Link{ { "Hera", "Greek", "A chariot drawn by peacocks", "Her intelligence" } });
		gods = gods->add_ordered(new Link{ { "Athena", "Greek", "", "Allowed to use Zeus's Thunderbolt and the Aegis" } });
		gods = gods->add_ordered(new Link{ { "Ares", "Greek", "War chariot", "Sword and spear" } });
		gods = gods->add_ordered(new Link{ { "Amaterasu", "Japanese", "", "Sword of Kusanagi, Jewel of Yasakani, Mirror of Yata" } });
		gods = gods->add_ordered(new Link{ { "Susanoo", "Japanese", "", "Sword of Totsuka" } });
		gods = gods->add_ordered(new Link{ { "Izanagi", "Japanese", "", "Sword of Totsuka (later given to Susanoo)" } });
		gods = gods->add_ordered(new Link{ { "Bishamonten", "Japanese", "", "A spear" } });

		Link *Odin = new Link{ { "Odin", "Norse", "Eight-legged flying horse called Sleipnir", "Spear called Gungnir" } };
		Link *Zeus = new Link{ { "Zeus", "Greek", "A chariot pulled by the four major winds shaped as horses",
			"Thunderbolt and the shield called Aegis" } };
		Link *Amaterasu = new Link{ { "Amaterasu", "Japanese", "", "Sword of Kusanagi, Jewel of Yasakani, Mirror of Yata" } };

		Link *norse_gods = Odin;
		Link *greek_gods = Zeus;
		Link *jap_gods = Amaterasu;

		move_nodes(norse_gods, gods, "Norse");
		move_nodes(greek_gods, gods, "Greek");
		move_nodes(jap_gods, gods, "Japanese");

		if (norse_gods->previous() != nullptr && norse_gods != nullptr)
		{
			std::cout << "\nnorse_gods list:\n";
			print_all(norse_gods);
		}
		if (greek_gods->previous() != nullptr && greek_gods != nullptr)
		{
			std::cout << "\ngreek_gods list:\n";
			print_all(greek_gods);
		}
		if (jap_gods->previous() != nullptr && jap_gods != nullptr)
		{
			std::cout << "\njap_gods list:\n";
			print_all(jap_gods);
		}

		delete Odin;
		delete Zeus;
		delete Amaterasu;
		delete gods;
	}
	catch (const std::runtime_error &rte)
	{
		std::cerr << "Runtime error: " << rte.what() << '\n';
		keep_window_open();
		return 1;
	}
	catch (const std::bad_alloc &ba)
	{
		std::cerr << "Bad allocation error: " << ba.what() << '\n';
		keep_window_open();
		return 2;
	}
	catch (const std::exception &e)
	{
		std::cerr << "Exception: " << e.what() << "\n";
		keep_window_open();
		return 3;
	}
	catch (...)
	{
		std::cerr << "An unknown exception occurred\n";
		keep_window_open();
		return 4;
	}

	keep_window_open();
}


Edit3: Now when I checked it in the debugger, it got caught in an infinite loop on the second call of move_nodes(). It was stuck on Hera and Zeus. The trav->m_succ pointer is pointing at Zeus and the trav pointer itself is pointing at Hera, with the current node in the dest_list also being Hera. I'm not letting it insert a node with the same name string as one already in the list, so that's the reason for the infinite loop. How do fix this in a way that the function would insert the node in the correct list without any duplications?
Last edited on
Just saw your Edit.

So when you say try to get it to work with one myth first, do you mean I should try it with just the gods list and one of the other three lists? And only those two lists?

Also, as you can see, my code is now closer to the "move" code in the book. But it's still not working. So what am I missing? Do I need three separate loops in the function, one for each myth? And how do I get rid of that infinite loop?
Here's the code again:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Link *move_nodes(Link *dest_list, Link *source_list, const std::string &myth)
{
	Link *trav = source_list->find_if_myth(myth);
	while ((trav = source_list->find_if_myth(myth)))
	{
		if (trav == source_list)
		{
			source_list = trav->next();
		}
		trav->erase();
		if (trav->god().m_myth == myth)
		{
			dest_list = dest_list->add_ordered(trav);
		}
	}
	return dest_list;
}


This time I tried it with just the Norse list. The output was:
norse_gods list:
{
Name: Frejya; Myth: Norse; Vehicle: Chariot pulled by two cats; Weapon: Magic called seidr
Name: Odin; Myth: Norse; Vehicle: Eight-legged flying horse called Sleipnir; Weapon: Spear called Gungnir
Name: Odin; Myth: Norse; Vehicle: Eight-legged flying horse called Sleipnir; Weapon: Spear called Gungnir
Name: Thor; Myth: Norse; Vehicle: Chariot pulled by goats Tanngrisnir and Tanngnjostr; Weapon: Hammer called Mjolnir
}


Really erroneous, right?

Here's main():
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
int main()
{
	try
	{
		Link *gods = new Link{ { "Odin", "Norse", "Eight-legged flying horse called Sleipnir", "Spear called Gungnir" } };
		gods = gods->add_ordered(new Link{ { "Thor", "Norse", "Chariot pulled by goats Tanngrisnir and Tanngnjostr",
			"Hammer called Mjolnir" } });
		gods = gods->add_ordered(new Link{ { "Baldr", "Norse", "A giant ship called Hringorni", "None" } });
		gods = gods->add_ordered(new Link{ { "Frejya", "Norse", "Chariot pulled by two cats", "Magic called seidr" } });
		gods = gods->add_ordered(new Link{ { "Zeus", "Greek", "A chariot pulled by the four major winds shaped as horses",
			"Thunderbolt and the shield called Aegis" } });
		gods = gods->add_ordered(new Link{ { "Hera", "Greek", "A chariot drawn by peacocks", "Her intelligence" } });
		gods = gods->add_ordered(new Link{ { "Athena", "Greek", "", "Allowed to use Zeus's Thunderbolt and the Aegis" } });
		gods = gods->add_ordered(new Link{ { "Ares", "Greek", "War chariot", "Sword and spear" } });
		gods = gods->add_ordered(new Link{ { "Amaterasu", "Japanese", "", "Sword of Kusanagi, Jewel of Yasakani, Mirror of Yata" } });
		gods = gods->add_ordered(new Link{ { "Susanoo", "Japanese", "", "Sword of Totsuka" } });
		gods = gods->add_ordered(new Link{ { "Izanagi", "Japanese", "", "Sword of Totsuka (later given to Susanoo)" } });
		gods = gods->add_ordered(new Link{ { "Bishamonten", "Japanese", "", "A spear" } });

		Link *Odin = new Link{ { "Odin", "Norse", "Eight-legged flying horse called Sleipnir", "Spear called Gungnir" } };
		//Link *Zeus = new Link{ { "Zeus", "Greek", "A chariot pulled by the four major winds shaped as horses",
			//"Thunderbolt and the shield called Aegis" } };
		//Link *Amaterasu = new Link{ { "Amaterasu", "Japanese", "", "Sword of Kusanagi, Jewel of Yasakani, Mirror of Yata" } };

		Link *norse_gods = Odin;
		//Link *greek_gods = Zeus;
		//Link *jap_gods = Amaterasu;

		norse_gods = move_nodes(norse_gods, gods, "Norse");
		//move_nodes(greek_gods, gods, "Greek");
		//move_nodes(jap_gods, gods, "Japanese");

		if (norse_gods->previous() != nullptr && norse_gods != nullptr)
		{
			std::cout << "\nnorse_gods list:\n";
			print_all(norse_gods);
		}
		/*if (greek_gods->previous() != nullptr && greek_gods != nullptr)
		{
			std::cout << "\ngreek_gods list:\n";
			print_all(greek_gods);
		}
		if (jap_gods->previous() != nullptr && jap_gods != nullptr)
		{
			std::cout << "\njap_gods list:\n";
			print_all(jap_gods);
		}*/

		delete Odin;
		//delete Zeus;
		//delete Amaterasu;
		delete gods;
	}
	catch (const std::runtime_error &rte)
	{
		std::cerr << "Runtime error: " << rte.what() << '\n';
		keep_window_open();
		return 1;
	}
	catch (const std::bad_alloc &ba)
	{
		std::cerr << "Bad allocation error: " << ba.what() << '\n';
		keep_window_open();
		return 2;
	}
	catch (const std::exception &e)
	{
		std::cerr << "Exception: " << e.what() << "\n";
		keep_window_open();
		return 3;
	}
	catch (...)
	{
		std::cerr << "An unknown exception occurred\n";
		keep_window_open();
		return 4;
	}

	keep_window_open();
}
Really erroneous, right?

What? Other than missing one of your gods (Baldr) it looks about right. You need to find out why that god is missing.
Not only is one god missing, there's one god mentioned twice as well. Even though adding a conditional check for trav's name string being the same as one already in the destination list didn't help, which is why I tried taking it out to see what happens. Is there something I should do in add_ordered() to make sure there are no duplicate nodes? What I have in there currently for that is:
1
2
3
4
else if (n->m_god.m_name == trav->m_god.m_name)
{
	return trav;
}


I tried running the code through my debugger a few times, but I can't see what the problem really is. I'm also watching the pointers and the passed in string. I'll try it again now.
Not only is one god missing, there's one god mentioned twice as well.

With the way your code is currently structured two gods with the same name is to be expected, as is the missing god.

Even though adding a conditional check for trav's name string being the same as one already in the destination list didn't help, which is why I tried taking it out to see what happens.

I would question the validity of the logic used in your check since when you removed the "check" code the program no longer seems to go into an endless loop.

Is there something I should do in add_ordered() to make sure there are no duplicate nodes?

I would suggest you get the program working when you don't have duplicate nodes in the first place, worry about duplicate nodes after you get the "insertion" working properly.

I tried running the code through my debugger a few times, but I can't see what the problem really is.

Where are you looking? If you're not looking in the correct place finding the problem will be much more difficult.



I was looking in the "move" function, at trav, trav->m_succ and the myth string passed in.

I managed to insert them in there correctly this time, except for the duplication on Odin. Should I not initialize the lists with one god prior to calling add_ordered() on them? Or will I get an error if I try to call add_ordered() or any other inserting function on a null list?

The output now is:
norse_gods list:
{
Name: Baldr; Myth: Norse; Vehicle: A giant ship called Hringorni; Weapon: None
Name: Frejya; Myth: Norse; Vehicle: Chariot pulled by two cats; Weapon: Magic called seidr
Name: Odin; Myth: Norse; Vehicle: Eight-legged flying horse called Sleipnir; Weapon: Spear called Gungnir
Name: Odin; Myth: Norse; Vehicle: Eight-legged flying horse called Sleipnir; Weapon: Spear called Gungnir
Name: Thor; Myth: Norse; Vehicle: Chariot pulled by goats Tanngrisnir and Tanngnjostr; Weapon: Hammer called Mjolnir
}


move_nodes():
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Link *move_nodes(Link *dest_list, Link *source_list, const std::string &myth)
{
	Link *trav = source_list->find_if_myth(myth);
	if (trav && trav->next())
	{
		if (trav && trav->god().m_myth == myth)
		{
			if (trav == source_list)
			{
				source_list = trav->next();
			}
			trav->erase();
			if (trav->god().m_myth == myth)
			{
				if (trav->god().m_name != dest_list->god().m_name)
				{
					dest_list = dest_list->add_ordered(trav);
				}
			}
		}
	}
	return dest_list;
}


main():
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
int main()
{
	try
	{
		Link *gods = new Link{ { "Odin", "Norse", "Eight-legged flying horse called Sleipnir", "Spear called Gungnir" } };
		gods = gods->add_ordered(new Link{ { "Thor", "Norse", "Chariot pulled by goats Tanngrisnir and Tanngnjostr",
			"Hammer called Mjolnir" } });
		gods = gods->add_ordered(new Link{ { "Baldr", "Norse", "A giant ship called Hringorni", "None" } });
		gods = gods->add_ordered(new Link{ { "Frejya", "Norse", "Chariot pulled by two cats", "Magic called seidr" } });
		gods = gods->add_ordered(new Link{ { "Zeus", "Greek", "A chariot pulled by the four major winds shaped as horses",
			"Thunderbolt and the shield called Aegis" } });
		gods = gods->add_ordered(new Link{ { "Hera", "Greek", "A chariot drawn by peacocks", "Her intelligence" } });
		gods = gods->add_ordered(new Link{ { "Athena", "Greek", "", "Allowed to use Zeus's Thunderbolt and the Aegis" } });
		gods = gods->add_ordered(new Link{ { "Ares", "Greek", "War chariot", "Sword and spear" } });
		gods = gods->add_ordered(new Link{ { "Amaterasu", "Japanese", "", "Sword of Kusanagi, Jewel of Yasakani, Mirror of Yata" } });
		gods = gods->add_ordered(new Link{ { "Susanoo", "Japanese", "", "Sword of Totsuka" } });
		gods = gods->add_ordered(new Link{ { "Izanagi", "Japanese", "", "Sword of Totsuka (later given to Susanoo)" } });
		gods = gods->add_ordered(new Link{ { "Bishamonten", "Japanese", "", "A spear" } });

		Link *Odin = new Link{ { "Odin", "Norse", "Eight-legged flying horse called Sleipnir", "Spear called Gungnir" } };
		//Link *Zeus = new Link{ { "Zeus", "Greek", "A chariot pulled by the four major winds shaped as horses",
			//"Thunderbolt and the shield called Aegis" } };
		//Link *Amaterasu = new Link{ { "Amaterasu", "Japanese", "", "Sword of Kusanagi, Jewel of Yasakani, Mirror of Yata" } };

		Link *norse_gods = Odin;
		//Link *greek_gods = Zeus;
		//Link *jap_gods = Amaterasu;

		while (gods->find_if_myth("Norse"))
		{
			norse_gods = move_nodes(norse_gods, gods, "Norse");
		}
		//move_nodes(greek_gods, gods, "Greek");
		//move_nodes(jap_gods, gods, "Japanese");

		if (norse_gods->previous() != nullptr && norse_gods != nullptr)
		{
			std::cout << "\nnorse_gods list:\n";
			print_all(norse_gods);
		}
		/*if (greek_gods->previous() != nullptr && greek_gods != nullptr)
		{
			std::cout << "\ngreek_gods list:\n";
			print_all(greek_gods);
		}
		if (jap_gods->previous() != nullptr && jap_gods != nullptr)
		{
			std::cout << "\njap_gods list:\n";
			print_all(jap_gods);
		}*/

		delete Odin;
		//delete Zeus;
		//delete Amaterasu;
		delete gods;
	}
	catch (const std::runtime_error &rte)
	{
		std::cerr << "Runtime error: " << rte.what() << '\n';
		keep_window_open();
		return 1;
	}
	catch (const std::bad_alloc &ba)
	{
		std::cerr << "Bad allocation error: " << ba.what() << '\n';
		keep_window_open();
		return 2;
	}
	catch (const std::exception &e)
	{
		std::cerr << "Exception: " << e.what() << "\n";
		keep_window_open();
		return 3;
	}
	catch (...)
	{
		std::cerr << "An unknown exception occurred\n";
		keep_window_open();
		return 4;
	}

	keep_window_open();
}


I'm having find() and find_if_myth() return nullptr if it can't find a node matching the criteria and I'm checking for whether it returns null or not when I use it.
Last edited on
Here's my current output:
norse_gods list:
{
Name: Baldr; Myth: Norse; Vehicle: A giant ship called Hringorni; Weapon: None
Name: Frejya; Myth: Norse; Vehicle: Chariot pulled by two cats; Weapon: Magic called seidr
Name: Odin; Myth: Norse; Vehicle: Eight-legged flying horse called Sleipnir; Weapon: Spear called Gungnir
Name: Odin; Myth: Norse; Vehicle: Eight-legged flying horse called Sleipnir; Weapon: Spear called Gungnir
Name: Thor; Myth: Norse; Vehicle: Chariot pulled by goats Tanngrisnir and Tanngnjostr; Weapon: Hammer called Mjolnir
}

greek_gods list:
{
Name: Ares; Myth: Greek; Vehicle: War chariot; Weapon: Sword and spear
Name: Athena; Myth: Greek; Vehicle: ; Weapon: Allowed to use Zeus's Thunderbolt and the Aegis
Name: Hera; Myth: Greek; Vehicle: A chariot drawn by peacocks; Weapon: Her intelligence
Name: Zeus; Myth: Greek; Vehicle: A chariot pulled by the four major winds shaped as horses; Weapon: Thunderbolt and the shield called Aegis
}

jap_gods list:
{
Name: Amaterasu; Myth: Japanese; Vehicle: ; Weapon: Sword of Kusanagi, Jewel of Yasakani, Mirror of Yata
Name: Bishamonten; Myth: Japanese; Vehicle: ; Weapon: A spear
}


My current main():
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
int main()
{
	try
	{
		Link *gods = new Link{ { "Odin", "Norse", "Eight-legged flying horse called Sleipnir", "Spear called Gungnir" } };
		gods = gods->add_ordered(new Link{ { "Thor", "Norse", "Chariot pulled by goats Tanngrisnir and Tanngnjostr",
			"Hammer called Mjolnir" } });
		gods = gods->add_ordered(new Link{ { "Baldr", "Norse", "A giant ship called Hringorni", "None" } });
		gods = gods->add_ordered(new Link{ { "Frejya", "Norse", "Chariot pulled by two cats", "Magic called seidr" } });
		gods = gods->add_ordered(new Link{ { "Zeus", "Greek", "A chariot pulled by the four major winds shaped as horses",
			"Thunderbolt and the shield called Aegis" } });
		gods = gods->add_ordered(new Link{ { "Hera", "Greek", "A chariot drawn by peacocks", "Her intelligence" } });
		gods = gods->add_ordered(new Link{ { "Athena", "Greek", "", "Allowed to use Zeus's Thunderbolt and the Aegis" } });
		gods = gods->add_ordered(new Link{ { "Ares", "Greek", "War chariot", "Sword and spear" } });
		gods = gods->add_ordered(new Link{ { "Amaterasu", "Japanese", "", "Sword of Kusanagi, Jewel of Yasakani, Mirror of Yata" } });
		gods = gods->add_ordered(new Link{ { "Susanoo", "Japanese", "", "Sword of Totsuka" } });
		gods = gods->add_ordered(new Link{ { "Izanagi", "Japanese", "", "Sword of Totsuka (later given to Susanoo)" } });
		gods = gods->add_ordered(new Link{ { "Bishamonten", "Japanese", "", "A spear" } });

		Link *Odin = new Link{ { "Odin", "Norse", "Eight-legged flying horse called Sleipnir", "Spear called Gungnir" } };
		Link *Zeus = new Link{ { "Zeus", "Greek", "A chariot pulled by the four major winds shaped as horses",
			"Thunderbolt and the shield called Aegis" } };
		Link *Amaterasu = new Link{ { "Amaterasu", "Japanese", "", "Sword of Kusanagi, Jewel of Yasakani, Mirror of Yata" } };

		Link *norse_gods = Odin;
		Link *greek_gods = Zeus;
		Link *jap_gods = Amaterasu;

		while (gods->find_if_myth("Norse"))
		{
			norse_gods = move_nodes(norse_gods, gods, "Norse");
		}
		while (gods->find_if_myth("Greek"))
		{
			greek_gods = move_nodes(greek_gods, gods, "Greek");
		}
		while (gods->find_if_myth("Japanese"))
		{
			jap_gods = move_nodes(jap_gods, gods, "Japanese");
		}

		std::cout << "\nnorse_gods list:\n";
		print_all(norse_gods);
		std::cout << "\ngreek_gods list:\n";
		print_all(greek_gods);
		std::cout << "\njap_gods list:\n";
		print_all(jap_gods);

		delete Odin;
		delete Zeus;
		delete Amaterasu;
		delete gods;
	}
	catch (const std::runtime_error &rte)
	{
		std::cerr << "Runtime error: " << rte.what() << '\n';
		keep_window_open();
		return 1;
	}
	catch (const std::bad_alloc &ba)
	{
		std::cerr << "Bad allocation error: " << ba.what() << '\n';
		keep_window_open();
		return 2;
	}
	catch (const std::exception &e)
	{
		std::cerr << "Exception: " << e.what() << "\n";
		keep_window_open();
		return 3;
	}
	catch (...)
	{
		std::cerr << "An unknown exception occurred\n";
		keep_window_open();
		return 4;
	}

	keep_window_open();
}


move_nodes():
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Link *move_nodes(Link *dest_list, Link *source_list, const std::string &myth)
{
	Link *trav = source_list->find_if_myth(myth);
	if (trav && trav->next())
	{
		if (trav && trav->next())
		{
			if (trav == source_list)
			{
				source_list = trav->next();
			}
			trav->erase();
			if (trav->god().m_myth == myth)
			{
				if (trav->god().m_name != dest_list->god().m_name)
				{
					dest_list = dest_list->add_ordered(trav);
				}
			}
		}
	}
	return dest_list;
}
I changed the move_nodes() code to this:
1
2
3
4
5
6
7
8
9
10
11
12
void move_nodes(Link *dest_list, Link *source_list, const std::string &myth)
{
	Link *trav = source_list->find_if_myth(myth);
	if (trav && trav->next())
	{
		trav->erase();
		if (trav->god().m_name != dest_list->god().m_name)
		{
			dest_list = dest_list->add_ordered(trav);
		}
	}
}
for the sake of simplicity. The reason for making it void was that I felt like some of the "wrongness" may have been because I was returning dest_list. Now there's no duplication on the nodes, at least.

I can't seem to figure out why it isn't going past Amaterasu and Bishamonten for the gods that should go into the Japanese list. But yeah, why are Izanagi and Susanoo not being entered into jap_gods, and why does gods (the list) still have Bishamonten even though it should already have become a completely NULL list?
Last edited on
Now I've got just one problem: Bishamonten is still in the gods list and I can't get him out. The other gods that need to be in the Japanese myth list are already in it.

Here's my current main():
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
int main()
{
	try
	{
		Link *gods = new Link{ { "Odin", "Norse", "Eight-legged flying horse called Sleipnir", "Spear called Gungnir" } };
		gods = gods->add_ordered(new Link{ { "Thor", "Norse", "Chariot pulled by goats Tanngrisnir and Tanngnjostr",
			"Hammer called Mjolnir" } });
		gods = gods->add_ordered(new Link{ { "Baldr", "Norse", "A giant ship called Hringorni", "None" } });
		gods = gods->add_ordered(new Link{ { "Frejya", "Norse", "Chariot pulled by two cats", "Magic called seidr" } });
		gods = gods->add_ordered(new Link{ { "Zeus", "Greek", "A chariot pulled by the four major winds shaped as horses",
			"Thunderbolt and the shield called Aegis" } });
		gods = gods->add_ordered(new Link{ { "Hera", "Greek", "A chariot drawn by peacocks", "Her intelligence" } });
		gods = gods->add_ordered(new Link{ { "Athena", "Greek", "", "Allowed to use Zeus's Thunderbolt and the Aegis" } });
		gods = gods->add_ordered(new Link{ { "Ares", "Greek", "War chariot", "Sword and spear" } });
		gods = gods->add_ordered(new Link{ { "Amaterasu", "Japanese", "", "Sword of Kusanagi, Jewel of Yasakani, Mirror of Yata" } });
		gods = gods->add_ordered(new Link{ { "Susanoo", "Japanese", "", "Sword of Totsuka" } });
		gods = gods->add_ordered(new Link{ { "Izanagi", "Japanese", "", "Sword of Totsuka (later given to Susanoo)" } });
		gods = gods->add_ordered(new Link{ { "Bishamonten", "Japanese", "", "A spear" } });

		Link *Odin = new Link{ { "Odin", "Norse", "Eight-legged flying horse called Sleipnir", "Spear called Gungnir" } };
		Link *Zeus = new Link{ { "Zeus", "Greek", "A chariot pulled by the four major winds shaped as horses",
			"Thunderbolt and the shield called Aegis" } };
		Link *Amaterasu = new Link{ { "Amaterasu", "Japanese", "", "Sword of Kusanagi, Jewel of Yasakani, Mirror of Yata" } };

		Link *norse_gods = Odin;
		Link *greek_gods = Zeus;
		Link *jap_gods = Amaterasu;

		while (gods->next() && gods->find_if_myth("Norse"))
		{
			move_nodes(norse_gods, gods, "Norse");
		}
		while (gods->next() && gods->find_if_myth("Greek"))
		{
			move_nodes(greek_gods, gods, "Greek");
		}
		while (gods->next() && gods->find_if_myth("Japanese"))
		{
			move_nodes(jap_gods, gods, "Japanese");
		}

		std::cout << "\nnorse_gods list:\n";
		print_all(norse_gods);
		std::cout << "\ngreek_gods list:\n";
		print_all(greek_gods);
		std::cout << "\njap_gods list:\n";
		print_all(jap_gods);
		std::cout << "\ngods list:\n";
		print_all(gods);

		delete Odin;
		delete Zeus;
		delete Amaterasu;
		delete gods;
	}
	catch (const std::runtime_error &rte)
	{
		std::cerr << "Runtime error: " << rte.what() << '\n';
		keep_window_open();
		return 1;
	}
	catch (const std::bad_alloc &ba)
	{
		std::cerr << "Bad allocation error: " << ba.what() << '\n';
		keep_window_open();
		return 2;
	}
	catch (const std::exception &e)
	{
		std::cerr << "Exception: " << e.what() << "\n";
		keep_window_open();
		return 3;
	}
	catch (...)
	{
		std::cerr << "An unknown exception occurred\n";
		keep_window_open();
		return 4;
	}

	keep_window_open();
}


find_if_myth():
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Link *Link::find_if_myth(const std::string &myth)
{
	Link *trav = this;
	if (trav->m_prev)
	{
		while (trav->m_prev)
		{
			trav = trav->m_prev;
		}
	}

	while (trav && trav->m_succ)
	{
		if (trav->m_god.m_myth == myth)
		{
			return trav;
		}
		trav = trav->m_succ;
	}
	return nullptr;
}


move_nodes():
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void move_nodes(Link *dest_list, Link *source_list, const std::string &myth)
{
	Link *trav = source_list->find_if_myth(myth);
	if (trav)
	{
		if (trav == source_list)
		{
			trav = source_list->next();
		}
		trav->erase();
		if (trav->god().m_name != dest_list->god().m_name && trav->god().m_myth == myth)
		{
			dest_list = dest_list->add_ordered(trav);
		}
	}
}


output:
norse_gods list:
{
Name: Baldr; Myth: Norse; Vehicle: A giant ship called Hringorni; Weapon: None
Name: Frejya; Myth: Norse; Vehicle: Chariot pulled by two cats; Weapon: Magic called seidr
Name: Odin; Myth: Norse; Vehicle: Eight-legged flying horse called Sleipnir; Weapon: Spear called Gungnir
Name: Thor; Myth: Norse; Vehicle: Chariot pulled by goats Tanngrisnir and Tanngnjostr; Weapon: Hammer called Mjolnir
}

greek_gods list:
{
Name: Ares; Myth: Greek; Vehicle: War chariot; Weapon: Sword and spear
Name: Athena; Myth: Greek; Vehicle: N/A; Weapon: Allowed to use Zeus's Thunderbolt and the Aegis
Name: Hera; Myth: Greek; Vehicle: A chariot drawn by peacocks; Weapon: Her intelligence
Name: Zeus; Myth: Greek; Vehicle: A chariot pulled by the four major winds shaped as horses; Weapon: Thunderbolt and the shield called Aegis
}

jap_gods list:
{
Name: Amaterasu; Myth: Japanese; Vehicle: N/A; Weapon: Sword of Kusanagi, Jewel of Yasakani, Mirror of Yata
Name: Izanagi; Myth: Japanese; Vehicle: N/A; Weapon: Sword of Totsuka (later given to Susanoo)
Name: Susanoo; Myth: Japanese; Vehicle: N/A; Weapon: Sword of Totsuka
}

gods list:
{
Name: Bishamonten; Myth: Japanese; Vehicle: N/A; Weapon: A spear
}


What am I still missing?
Pages: 1... 111213141516