C++ Primer ex 5.18

A

arnuld

it does not run and even does not even give me any clue to the problem in
its output :(

/* C++ Primer - 4/e
* chapter 5 - Expressions

* exercise 5.18
* STATEMENT
* write a programme that defines a vector of pointers to strings.
read the vector, printing each string and its corresponding size.

*/

#include <iostream>
#include <vector>
#include <string>

int main()
{
std::vector<std::string*> psvec;
std::string input_string;
std::string* ps;

while(std::cin >> input_string)
{
*ps = input_string;
psvec.push_back(ps++);
}

/* printing the strings pointed by the pointers in the vector*/
for(std::vector<std::string*>::const_iterator iter = psvec.begin();
iter != psvec.end(); ++iter)
{
std::cout << "string: " << **iter
<< " size: " << (*iter).size() /* error is here */
<< std::endl;
/* double-defrenced operator because it points to a pointer
rather than a value */
}

/* i was thinking of using "std::copy" from <algorithm> and
"ostream_iterator" from <sstream> from but was not able to
understand the peculiar mechanism of both of them */

return 0;
}

/* OUTPUT
/home/arnuld/programming/cpp $ g++ -ansi -pedantic -Wall -Wextra

ex_05-18.cpp ex_05-18.cpp: In function ‘int main()’: ex_05-18.cpp:32:
error: request for member ‘size’ in ‘iter.

__gnu_cxx::__normal_iterator<_Iterator, _Container>::eek:perator* [with
_Iterator = std::string* const*, _Container = std::vector<std::string*,
std::allocator<std::string*> >]()’, which is of non-class type
‘std::string* const’

/home/arnuld/programming/cpp $

*/
 
T

tragomaskhalos

it does not run and even does not even give me any clue to the problem in
its output :(

See code markups (without benefit of compiler, but I hope correct !)
int main()
{
std::vector<std::string*> psvec;
std::string input_string;
// WARNING: ps is uninitialised here ...
std::string* ps;

while(std::cin >> input_string)
{
// DISASTER IMMINENT: dereferencing uninitialised pointer
// You need to use dynamically created std::strings in here instead
*ps = input_string;
psvec.push_back(ps++);
}

/* printing the strings pointed by the pointers in the vector*/
for(std::vector<std::string*>::const_iterator iter = psvec.begin();
iter != psvec.end(); ++iter)
{
std::cout << "string: " << **iter
// PROBLEM: Type of *iter is const std::string *, so you need (*iter)-
 
J

James Kanze

it does not run and even does not even give me any clue to the problem in
its output :(
/* C++ Primer - 4/e
* chapter 5 - Expressions

* exercise 5.18
* STATEMENT
* write a programme that defines a vector of pointers to strings.
read the vector, printing each string and its corresponding size.
*/
#include <iostream>
#include <vector>
#include <string>
int main()
{
std::vector<std::string*> psvec;
std::string input_string;
std::string* ps;
while(std::cin >> input_string)
{
*ps = input_string;

What does ps point to here? Somehow, you're going to have to
get memory to which the pointer can point.
psvec.push_back(ps++);
}
/* printing the strings pointed by the pointers in the vector*/
for(std::vector<std::string*>::const_iterator iter = psvec.begin();
iter != psvec.end(); ++iter)
{
std::cout << "string: " << **iter
<< " size: " << (*iter).size() /* error is here */

What is the type of *iter?

C++ has a moderately strict type system. Whatever *iter
returns, it should have the value type of the array. What type
does the array contain? Is the . operator legal on such types?
What operators might be legal?
<< std::endl;
/* double-defrenced operator because it points to a pointer
rather than a value */
}
/* i was thinking of using "std::copy" from <algorithm> and
"ostream_iterator" from <sstream> from but was not able to
understand the peculiar mechanism of both of them */

You can't use it if you want to output the size as well. (Well,
actually you can, but doing so would require some funny
business, and is probably not a good idea.)
 
T

tom

it does not run and even does not even give me any clue to the problem in
its output :(

/* C++ Primer - 4/e
* chapter 5 - Expressions

* exercise 5.18
* STATEMENT
* write a programme that defines a vector of pointers to strings.
read the vector, printing each string and its corresponding size.

*/

#include <iostream>
#include <vector>
#include <string>

int main()
{
std::vector<std::string*> psvec;
std::string input_string;
std::string* ps;

while(std::cin >> input_string)
{
*ps = input_string;
psvec.push_back(ps++);
}

/* printing the strings pointed by the pointers in the vector*/
for(std::vector<std::string*>::const_iterator iter = psvec.begin();
iter != psvec.end(); ++iter)
{
std::cout << "string: " << **iter
<< " size: " << (*iter).size() /* error is here */
<< std::endl;
/* double-defrenced operator because it points to a pointer
rather than a value */
}

/* i was thinking of using "std::copy" from <algorithm> and
"ostream_iterator" from <sstream> from but was not able to
understand the peculiar mechanism of both of them */

return 0;

}

/* OUTPUT
/home/arnuld/programming/cpp $ g++ -ansi -pedantic -Wall -Wextra

ex_05-18.cpp ex_05-18.cpp: In function 'int main()': ex_05-18.cpp:32:
error: request for member 'size' in 'iter.

__gnu_cxx::__normal_iterator<_Iterator, _Container>::eek:perator* [with
_Iterator = std::string* const*, _Container = std::vector<std::string*,
std::allocator<std::string*> >]()', which is of non-class type
'std::string* const'

/home/arnuld/programming/cpp $

*/

fixed your program and post it below:

int main()
{
std::vector<std::string*> psvec;
//std::string input_string;
//std::string* ps;
std::string *pstring(NULL);
pstring = new string;
// modification: fix run-time error here to allocate space to store
input string
while(std::cin >> *pstring)
{
psvec.push_back(pstring);
pstring = new string;
}
delete pstring;


/* printing the strings pointed by the pointers in the vector*/
for(std::vector<std::string*>::const_iterator iter = psvec.begin();
iter != psvec.end(); ++iter)
{
std::cout << "string: " << **iter
<< " size: " << (*iter)->size() /* error is here */ //
modification: made here to get it compilied
<< std::endl;
/* double-defrenced operator because it points to a pointer
rather than a value */
}

//modification: clean up dynamically allocated memory
while(psvec.size()>0)
{
std::vector<std::string *>::iterator iter = psvec.begin();
delete *iter;
psvec.erase(iter);
}

/* i was thinking of using "std::copy" from <algorithm> and
"ostream_iterator" from <sstream> from but was not able to
understand the peculiar mechanism of both of them */


return 0;

}
 
J

Jerry Coffin

[ ... ]
#include <iostream>
#include <vector>
#include <string>

int main()
{
std::vector<std::string*> psvec;
std::string input_string;
std::string* ps;

As has already been pointed out, this has type 'std::string *', but it's
not really a pointer to a string -- it's just an unitialized pointer.
while(std::cin >> input_string)
{
*ps = input_string;

This really needs to allocate a new string and copy the input_string
into the new string, something like:

ps = new string(input_string);

As it stands right now, it's _trying_ to take wherever the uninitialized
pointer happens to point at, and treat it as if there was a string
there. If you're lucky, it'll point to somewhere that's not readable or
writable, so your program will die immediately when you try to do that
-- but chances of being that lucky aren't very high. The alternative is
that it sort of seems to work for a while, overwriting memory that
doesn't belong to it. That inevitably leads to eventual problems, but
it's hard to predict when they'll become visible -- Murphy's law being
what it is, you'll usually find out about it by the program dying a
horrible death just as you're showing it to the person who's in the best
position to fire you...
/* printing the strings pointed by the pointers in the vector*/
for(std::vector<std::string*>::const_iterator iter = psvec.begin();
iter != psvec.end(); ++iter)
{
std::cout << "string: " << **iter
<< " size: " << (*iter).size() /* error is here */
<< std::endl;
/* double-defrenced operator because it points to a pointer
rather than a value */
}

/* i was thinking of using "std::copy" from <algorithm> and
"ostream_iterator" from <sstream> from but was not able to
understand the peculiar mechanism of both of them */

They're going to be pretty tough to apply in a case like this -- for the
most part, the standard containers and algorithms expect to work with
value-like objects, not with pointers. By value-like objects, I mean
things that it's free to copy, assign, etc. There's an implicit
assumption that such operations are also relatively cheap.
 
B

BobR

arnuld said:
/* i was thinking of using "std::copy" from <algorithm> and
"ostream_iterator" from <sstream> from but was not able to
understand the peculiar mechanism of both of them */


----- Original Message -----
From: James Kanze <[email protected]>
Newsgroups: comp.lang.c++
Sent: Tuesday, July 24, 2007 2:38 AM
Subject: Re: any improvements for this programme

...[SNIPPED]........
yes it works. dinot know that "ostream_iterator" is defined in
"<sstream>" header.

The <sstream> header is for the ostringstream.

ostream_iterator is defined in <iterator>.

(But any standard header is allowed to include any other,
and <iterator> is likely included in a header you've already included.)

END ----- Original Message -----


Did you forget?
 

Ask a Question

Want to reply to this thread or ask your own question?

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.

Ask a Question

Similar Threads

C++ Primer ex 3.14 8
C++ Primer ex 9.27 4
C++ Primer ex 4.30 10
C++ Primer ex 3.24 (bitset class) 5
C++ Primer ex 7.14 2
C++ Primer ex 9.14 11
C++ Primer exercise 3.13 17
C++ Primer ex 7.6 17

Members online

Forum statistics

Threads
473,962
Messages
2,570,134
Members
46,690
Latest member
MacGyver

Latest Threads

Top