# Strooustrup Exercise - doubly-linked list

A

#### arnuld

Problem Statement is in the comments. I am getting compile time error:

/* Stroustrup, Chapter 7, exercise 7
*
* Consider:
* struct Tnode {
* string word;
* int count;
* Tnode* left;
* Tnode* right;
* };
*
*
* (1) Write a function for entering new words into a tree of Tnodes.
* (2) Write a function to write out a tree of Tnodes.
* (3) Write a function to write out a tree of Tnodes in alphabetical order.
* (4) Modify Tnode so that it stores (only) a pointer to an arbitrary long
* word stored as an array of characters on free store using new.
* (5) Modify the functions to use the new definition of Tnode.
*
* Right now, I am at (1), will do it and only then will go on (2).
*
*
* VERSION 1.0
*
*/

#include <iostream>
#include <string>

struct Tnode
{
std::string word;
int count;
Tnode* left;
Tnode* right;
};

int main()
{
Tnode* my_tree;

my_tree->word = NULL;
my_tree->count = 0;
my_tree->left = NULL;
my_tree->right = NULL;

return 0;
}

{
std::cout << "Please enter some words that you want to add to the Tree\n";
/* I want to use istream_iterator but can't find a way for 3rd argument to
std::copy */
/* std::copy( std::istream_iterator<std::string>(std::cin),
std::istream_iterator<std::string(),
??????? );
*/
std::string a_word;
while( std::cin >> a_word )
{
{
}
else if( NULL == add_to_tree->left )
{
}
else if( NULL == add_to_tree->right )
{
}
}

}
======================= OUTPUT ==============================
[arnuld@dune cpp]\$ g++4 -ansi -pedantic -Wall -Wextra 07_7.cpp
07_7.cpp: In function â€˜int main()â€™:
07_7.cpp:47: error: ambiguous overload for â€˜operator=â€™ in â€˜my_tree->Tnode::word = 0â€™
/usr/include/c++/3.4.3/bits/basic_string.h:434: note: candidates are:
std::basic_string<_CharT, _Traits, _Alloc>& std::basic_string<_CharT,
_Traits, _Alloc>:perator=(const std::basic_string<_CharT, _Traits,
_Alloc>&) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc =
std::allocator<char>]
/usr/include/c++/3.4.3/bits/basic_string.h:445: note:
std::basic_string<_CharT, _Traits, _Alloc>& std::basic_string<_CharT,
_Traits, _Alloc>:perator=(const _CharT*) [with _CharT = char, _Traits =
std::char_traits<char>, _Alloc = std::allocator<char>]
/usr/include/c++/3.4.3/bits/basic_string.h:459: note:
std::basic_string<_CharT, _Traits, _Alloc>& std::basic_string<_CharT,
_Traits, _Alloc>:perator=(_CharT) [with _CharT = char, _Traits =
std::char_traits<char>, _Alloc = std::allocator<char>] 07_7.cpp: In
function â€˜void add_some_words(Tnode*)â€™: 07_7.cpp:72: error: no match
for â€˜operator==â€™ in â€˜0 == add_to_tree->Tnode::wordâ€™
[arnuld@dunecpp]\$

Line 47: my_tree->word = NULL;

I don't see why it complains on that line. my_tree->word is a std::string
and we use operator= for std::string all the time.

R

#### red floyd

arnuld said:
Problem Statement is in the comments. I am getting compile time error:

/* Stroustrup, Chapter 7, exercise 7
*
* Consider:
* struct Tnode {
* string word;
* int count;
* Tnode* left;
* Tnode* right;
* };
*
*
* (1) Write a function for entering new words into a tree of Tnodes.
* (2) Write a function to write out a tree of Tnodes.
* (3) Write a function to write out a tree of Tnodes in alphabetical order.
* (4) Modify Tnode so that it stores (only) a pointer to an arbitrary long
* word stored as an array of characters on free store using new.
* (5) Modify the functions to use the new definition of Tnode.
*
* Right now, I am at (1), will do it and only then will go on (2).
*
*
* VERSION 1.0
*
*/

#include <iostream>
#include <string>

struct Tnode
{
std::string word;
int count;
Tnode* left;
Tnode* right;
};

int main()
{
Tnode* my_tree;

my_tree->word = NULL;
my_tree->count = 0;
my_tree->left = NULL;
my_tree->right = NULL;

return 0;
}

{
std::cout << "Please enter some words that you want to add to the Tree\n";
/* I want to use istream_iterator but can't find a way for 3rd argument to
std::copy */
/* std::copy( std::istream_iterator<std::string>(std::cin),
std::istream_iterator<std::string(),
??????? );
*/
std::string a_word;
while( std::cin >> a_word )
{
{
}
else if( NULL == add_to_tree->left )
{
}
else if( NULL == add_to_tree->right )
{
}
}

}
======================= OUTPUT ==============================
[arnuld@dune cpp]\$ g++4 -ansi -pedantic -Wall -Wextra 07_7.cpp
07_7.cpp: In function â€˜int main()â€™:
07_7.cpp:47: error: ambiguous overload for â€˜operator=â€™ in â€˜my_tree->Tnode::word = 0â€™
/usr/include/c++/3.4.3/bits/basic_string.h:434: note: candidates are:
std::basic_string<_CharT, _Traits, _Alloc>& std::basic_string<_CharT,
_Traits, _Alloc>:perator=(const std::basic_string<_CharT, _Traits,
_Alloc>&) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc =
std::allocator<char>]
/usr/include/c++/3.4.3/bits/basic_string.h:445: note:
std::basic_string<_CharT, _Traits, _Alloc>& std::basic_string<_CharT,
_Traits, _Alloc>:perator=(const _CharT*) [with _CharT = char, _Traits =
std::char_traits<char>, _Alloc = std::allocator<char>]
/usr/include/c++/3.4.3/bits/basic_string.h:459: note:
std::basic_string<_CharT, _Traits, _Alloc>& std::basic_string<_CharT,
_Traits, _Alloc>:perator=(_CharT) [with _CharT = char, _Traits =
std::char_traits<char>, _Alloc = std::allocator<char>] 07_7.cpp: In
function â€˜void add_some_words(Tnode*)â€™: 07_7.cpp:72: error: no match
for â€˜operator==â€™ in â€˜0 == add_to_tree->Tnode::wordâ€™
[arnuld@dunecpp]\$

Line 47: my_tree->word = NULL;

I don't see why it complains on that line. my_tree->word is a std::string
and we use operator= for std::string all the time.
Yeah, but NULL is an integer constant, defined as 0. There's no
assignment operator std::basic_string<>:perator=(int), hence the error.

By default a std::string is empty. Plus, in main, my_tree points at
garbage (uninitialized pointer). I'd declare it just as a TNode, rather

S

#### Salt_Peter

Problem Statement is in the comments. I am getting compile time error:

/* Stroustrup, Chapter 7, exercise 7
*
* Consider:
* struct Tnode {
* string word;
* int count;
* Tnode* left;
* Tnode* right;
* };
*
*
* (1) Write a function for entering new words into a tree of Tnodes.
* (2) Write a function to write out a tree of Tnodes.
* (3) Write a function to write out a tree of Tnodes in alphabetical order.
* (4) Modify Tnode so that it stores (only) a pointer to an arbitrary long
* word stored as an array of characters on free store using new.
* (5) Modify the functions to use the new definition of Tnode.
*
* Right now, I am at (1), will do it and only then will go on (2).
*
*
* VERSION 1.0
*
*/

#include <iostream>
#include <string>

struct Tnode
{
std::string word;
int count;
Tnode* left;
Tnode* right;

};

int main()
{
Tnode* my_tree;

At this point you have a pointer my_tree, it *could* potentially point
to something.
In fact, it does point somewhere, some garbage/residual value.
A pointer does not invoke construction.
So far - there *is* no Tnode at that pointer.
Can you see why naming a pointer as such is helpful?

You could allocate it and later destroy the object using new / delete.
At least then you would have an object *at* that pointer to work with.

Tnode* p_node = new Tnode;
// do stuff
delete p_node;

or you might simply do it all without manual allocation / deallocation
and just pass the address of the object using the address_of operator
&.

Tnode node;
Tnode* p_node = &node;
// do stuff
my_tree->word = NULL;

member word is a std::string, not a pointer

my_tree->word = "";
my_tree->count = 0;
my_tree->left = NULL;
my_tree->right = NULL;

return 0;

}

{
std::cout << "Please enter some words that you want to add to the Tree\n";
/* I want to use istream_iterator but can't find a way for 3rd argument to
std::copy */
/* std::copy( std::istream_iterator<std::string>(std::cin),
std::istream_iterator<std::string(),
??????? );
*/
std::string a_word;
while( std::cin >> a_word )
{
{
}
else if( NULL == add_to_tree->left )
{
}
else if( NULL == add_to_tree->right )
{
}
}

}

======================= OUTPUT ==============================
[arnuld@dune cpp]\$ g++4 -ansi -pedantic -Wall -Wextra 07_7.cpp
07_7.cpp: In function ‘int main()’:
07_7.cpp:47: error: ambiguous overload for ‘operator=’ in ‘my_tree->Tnode::word = 0’
/usr/include/c++/3.4.3/bits/basic_string.h:434: note: candidates are:
std::basic_string<_CharT, _Traits, _Alloc>& std::basic_string<_CharT,
_Traits, _Alloc>:perator=(const std::basic_string<_CharT, _Traits,
_Alloc>&) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc =
std::allocator<char>]
/usr/include/c++/3.4.3/bits/basic_string.h:445: note:
std::basic_string<_CharT, _Traits, _Alloc>& std::basic_string<_CharT,
_Traits, _Alloc>:perator=(const _CharT*) [with _CharT = char, _Traits =
std::char_traits<char>, _Alloc = std::allocator<char>]
/usr/include/c++/3.4.3/bits/basic_string.h:459: note:
std::basic_string<_CharT, _Traits, _Alloc>& std::basic_string<_CharT,
_Traits, _Alloc>:perator=(_CharT) [with _CharT = char, _Traits =
std::char_traits<char>, _Alloc = std::allocator<char>] 07_7.cpp: In
function ‘void add_some_words(Tnode*)’: 07_7.cpp:72: error: no match
for ‘operator==’ in ‘0 == add_to_tree->Tnode::word’
[arnuld@dunecpp]\$

Line 47: my_tree->word = NULL;

I don't see why it complains on that line. my_tree->word is a std::string
and we use operator= for std::string all the time.

If you read the error, its complaining that its not able to use
that operator with an rvalue that is a pointer* .

so this would do:
std::string* p_s = 0; // points to nothing yet
and this would also:
std::string s = "";

Don't get discouraged, you need to detect the crucial difference
between
an instance of a type and a pointer.
A pointer points to nothing until properly initialized.

A

#### arnuld

Yeah, but NULL is an integer constant, defined as 0. There's no
assignment operator std::basic_string<>:perator=(int), hence the error.

Oh.. I thought of std::string like a char pointer.

By default a std::string is empty. Plus, in main, my_tree points at
garbage (uninitialized pointer). I'd declare it just as a TNode, rather

Whats the benefit of it over the pointer definition ?

2nd it works fine but I get Segfault because of the some wrong code in
while() loop:

/* Stroustrup, Chapter 7, exercise 7
*
* Consider:
* struct Tnode {
* string word;
* int count;
* Tnode* left;
* Tnode* right;
* };
*
*
* (1) Write a function for entering new words into a tree of Tnodes.
* (2) Write a function to write out a tree of Tnodes.
* (3) Write a function to write out a tree of Tnodes in alphabetical order.
* (4) Modify Tnode so that it stores (only) a pointer to an arbitrary long
* word stored as an array of characters on free store using new.
* (5) Modify the functions to use the new definition of Tnode.
*
* Right now, I am at (1), will do it and only then will go on (2).
*
*
* VERSION 1.1
*
*/

#include <iostream>
#include <string>

struct Tnode
{
std::string word;
int count;
Tnode* left;
Tnode* right;
};

int main()
{
Tnode my_tree;

my_tree.word = "";
my_tree.count = 0;
my_tree.left = NULL;
my_tree.right = NULL;

return 0;
}

{
std::cout << "Please enter some words that you want to add to the Tree\n";
/* I want to use istream_iterator but can't find a way for 3rd argument to
std::copy */
/* std::copy( std::istream_iterator<std::string>(std::cin),
std::istream_iterator<std::string(),
??????? );
*/
std::string a_word;
while( std::cin >> a_word )
{
{
}
else if( NULL == add_to_tree->left )
{
}
else if( NULL == add_to_tree->right )
{
}
}
}

=================== OUTPUT ====================
[arnuld@dune cpp]\$ g++4 -ansi -pedantic -Wall -Wextra 07_7.cpp
[arnuld@dune cpp]\$ ./a.out
Please enter some words that you want to add to the Tree
Love
Linux
Segmentation fault
[arnuld@dune cpp]\$

A

#### arnuld

Um, what's wrong with 'my_tree->word.clear()'?

because I did not know this member function.

A

#### arnuld

On Thu, 06 Nov 2008 21:57:08 -0800, red floyd wrote:

PROBLEM: It's not adding words to the Tree, though it compiles fine.

/* Stroustrup, Chapter 7, exercise 7
*
* Consider:
* struct Tnode {
* string word;
* int count;
* Tnode* left;
* Tnode* right;
* };
*
*
* (1) Write a function for entering new words into a tree of Tnodes.
* (2) Write a function to write out a tree of Tnodes.
* (3) Write a function to write out a tree of Tnodes in alphabetical order.
* (4) Modify Tnode so that it stores (only) a pointer to an arbitrary long
* word stored as an array of characters on free store using new.
* (5) Modify the functions to use the new definition of Tnode.
*
* Right now, I am at (1), will do it and only then will go on (2).
*
* Problem doe snot explain why the "count" exists as a member of Tnode. I think
* the author does not want us to have duplicates getting stored in Tnode. So if
* we get a some duplicate word, then we can increase the count of that specific
* node.
*
* VERSION 1.2
*
*/

#include <iostream>
#include <string>

struct Tnode
{
std::string word;
int count;
Tnode* left;
Tnode* right;
};

void make_tree_null( Tnode* );
void print_tree( Tnode* );

int main()
{
Tnode my_tree;

make_tree_null( &my_tree );
print_tree( &my_tree );

return 0;
}

void make_tree_null( Tnode* non_null_tree )
{
non_null_tree->word = "";
non_null_tree->count = 0;
non_null_tree->left = NULL;
non_null_tree->right = NULL;
}

{
std::cout << "Please enter some words that you want to add to the Tree\n";
std::string a_word;
while( std::cin >> a_word )
{
}
/* Instead of while() loop I want to use istream_iterator but can't find a
way for 3rd argument to std::copy:
std::copy( std::istream_iterator<std::string>(std::cin),
std::istream_iterator<std::string(),
???????????????????????????????? )
*/
}

/* Uses recursion, inspired from K&R2,Self-Referential structures, section 6.5
function is printing the word and the string comparison without any trouble.

argument "ts" means "tree structure", but easy to type.
*/
Tnode* add_single_word( Tnode* ts, std::string single_word )
{
int comparison;

if( NULL == ts )
{
ts = new Tnode;
std::cout << "-------------\n";
if( ts )
{
ts->word.clear();
ts->count++;
}
else
{
std::cerr << "Can't allocate memory\n";
return ts;
}
}
else if( !(comparison = single_word.compare(ts->word)) )
{
ts->count++;
}
else if( comparison < 0 )
{
}
else if( comparison > 0 )
{
}

return ts;
}

void print_tree( Tnode* a_tree)
{
if( a_tree )
{
print_tree(a_tree->left);

std::cout << a_tree->word
<< " occured "
<< a_tree->count
<< " times"
<< std::endl;

print_tree(a_tree->right);
}
else
{
std::cout << "NULL tree" << std::endl;
}
}

==================== OUTPUT =======================
[arnuld@dune C++]\$ ./a.out
Please enter some words that you want to add to the Tree
Bjarne Stroustrup and Hurb Sutter

D

#### DJ Dharme

PROBLEM:    It's not adding words to the Tree, though it compiles fine.

/* Stroustrup, Chapter 7, exercise 7
*
* Consider:
*           struct Tnode {
*                          string word;
*                          int count;
*                          Tnode* left;
*                          Tnode* right;
*                     };
*
*
*  (1) Write a function for entering new words into a tree of Tnodes..
*  (2) Write a function to write out a tree of Tnodes.
*  (3) Write a function to write out a tree of Tnodes in alphabetical order.
*  (4) Modify Tnode so that it stores (only) a pointer to an arbitrary long
*      word stored as an array of characters on free store using new.
*  (5) Modify the functions to use the new definition of Tnode.
*
* Right now, I am at (1), will do it and only then will go on (2).
*
* Problem doe snot explain why the "count" exists as a member of Tnode.. I think
* the author does not want us to have duplicates getting stored in Tnode. So if
* we get a some duplicate word, then we can increase the count of that specific
* node.
*
* VERSION 1.2
*
*/

#include <iostream>
#include <string>

struct Tnode
{
std::string word;
int count;
Tnode* left;
Tnode* right;

};

void make_tree_null( Tnode* );
void print_tree( Tnode* );

int main()
{
Tnode my_tree;

make_tree_null( &my_tree );
print_tree( &my_tree );

return 0;

}

void make_tree_null( Tnode* non_null_tree )
{
non_null_tree->word  = "";
non_null_tree->count = 0;
non_null_tree->left  = NULL;
non_null_tree->right = NULL;

}

{
std::cout << "Please enter some words that you want to add to the Tree\n";
std::string a_word;
while( std::cin >> a_word )
{
}
/* Instead of while() loop I want to use istream_iterator but can't find a
way for 3rd argument to std::copy:
std::copy( std::istream_iterator<std::string>(std::cin),
std::istream_iterator<std::string(),
???????????????????????????????? )
*/

}

/* Uses recursion, inspired from K&R2,Self-Referential structures, section 6.5
function is printing the word and  the string comparison without any trouble.

argument "ts" means "tree structure", but easy to type.
*/
Tnode* add_single_word( Tnode* ts, std::string single_word )
{
int comparison;

if( NULL == ts )
{
ts = new Tnode;
std::cout << "-------------\n";
if( ts )
{
ts->word.clear();
ts->count++;
}
else
{
std::cerr << "Can't allocate memory\n";
return ts;
}
}
else if( !(comparison = single_word.compare(ts->word)) )
{
ts->count++;
}
else if( comparison < 0 )
{
}
else if( comparison > 0 )
{
}

return ts;

}

void print_tree( Tnode* a_tree)
{
if( a_tree )
{
print_tree(a_tree->left);

std::cout << a_tree->word
<< " occured "
<< a_tree->count
<< " times"
<< std::endl;

print_tree(a_tree->right);
}
else
{
std::cout << "NULL tree" << std::endl;
}

}

==================== OUTPUT =======================
[arnuld@dune C++]\$ ./a.out
Please enter some words that you want to add to the Tree
Bjarne Stroustrup and Hurb Sutter
-------------
-------------
-------------
-------------
-------------
NULL tree
occured 0 times
NULL tree
[arnuld@dune C++]\$

--www.lispmachine.wordpress.com
my email is @ the above blog.

Try this one out

#include <iostream>
#include <string>

struct Tnode
{
std::string word;
int count;
Tnode* left;
Tnode* right;

};

void reset_node(Tnode* pnode);
void print_tree(Tnode* proot);

int main()
{
Tnode root;

reset_node(&root);

std::cout << "Printing Items in the alphabetical order (Case
Sensitive)" << std::endl;

print_tree(&root);

return 0;

}

void reset_node(Tnode* pnode)
{
pnode->word = "";
pnode->count = 0;
pnode->left = NULL;
pnode->right = NULL;
}

{
std::cout << "Please enter some words that you want to add to the
Tree" << std::endl;

std::string aword;
getline(std::cin, aword);

while(aword != "")
{
getline(std::cin, aword);
}
}

{
if(pnode->count == 0)
{
pnode->word = word;
}
else
{
if(word.compare(pnode->word) < 0)
{
if(pnode->left == NULL)
{
pnode->left = new Tnode;
reset_node(pnode->left);
}

}
else
{
if(pnode->right == NULL)
{
pnode->right = new Tnode;
reset_node(pnode->right);
}

}
}

++(pnode->count);
}

void print_tree(Tnode* pnode)
{
if(pnode->left)
{
print_tree(pnode->left);
}
std::cout << pnode->word << std::endl;

if(pnode->right)
{
print_tree(pnode->right);
}
}

D

#### Default User

arnuld said:
Oh.. I thought of std::string like a char pointer.

I'd strongly recommend that you read the Stroustrup sections on
std::string before you try to use it any further.

Brian

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

### Members online

No members online now.