On Jul 19, 2:35 pm, arnuld <geek.arn...@gmail.comwrote:
i have solved it.
No you haven't, but you've run into a very subtle issue.
any suggestions for improving the code:
/* C++ Primer - 4/e
* chapter 3
* exercise 3.14
* STATEMENT
read some text into a vector,storing each word as an elelment in
the vector. transform each word into the uppercase letter. print the
transofrmed elelments from the vector as eight words per line.
*/
#include <iostream>
#include <vector>
#include <string>
You're missing at least one include.
int main()
{
std::cout << "please enter some words seperated by newlines" <<
std::endl;
std::string a_word;
std::vector<std::stringsvec;
while(std::cin >a_word)
{
svec.push_back(a_word);
}
for(std::vector<std::string>::iterator iter=svec.begin(); iter !=
svec.end(); ++iter)
{
for(std::string::size_type ix=0; ix != (*iter).size(); ++ix)
{
((*iter)[ix]) = toupper((*iter)[ix]);
/* i call it the MESSY solution.
isn't there anything better ? */
I call it a wrong solution. On my system, if the user enters an
accented character, it passes a negative value to "toupper".
For the one argument version of toupper (declared in <ctype.h>),
"the argument is an int, the value of which shall be
representable as an unsigned char or shall equal the value of
the macro EOF." This is a pre-condition; violating it results
in undefined behavior. At the very least, you need to write:
(*iter)[ ix ] = toupper( static_cast< unsigned char >( (*iter)
[ ix ] ) ;
(In practice, of course, I'd recommend using string iterators
for the inner loop as well. It's more C++'ish.)
As you can see by the name of the header, the single argument
version of toupper is in fact a C function (included by
reference in C++). The C++ variants are in <locale(and have
been designed to be particularly complicated to use:-)). In
C++, there is a convenience function, std::toupper, but most of
the time, you'll probably want to obtain a ctype facet, and work
with that:
std::ctype< char const& ctype
= std::use_facet< std::ctype< char ( std::locale() ) ;
There's a ctype::toupper which works on strings, but only on
char[] strings. (Don't ask me how they justify that.) So once
again, you're stuck with a loop. Or you embed the call in a
functional object, and use std::transform; this occurs so often
in my own code that I have such functional objects in my
toolbox, and would simply write:
std::transform( iter->begin(), iter->end(),
iter->begin(),
CTypeToUpper() ) ;
Writing a robust version of such a functional object is trickier
than it looks, because you have to be concerned with the
lifetime of the facet (e.g. if the locale is a temporary, or if
someone changes it during the lifetime of the functional
object); something sufficient for a program like yours (and most
programs, in fact), however, shouldn't be that difficult, and
would serve as an interesting introduction to <locale>.
(Implementing one which uses the <ctype.hone argument form of
toupper is even easier. Just don't forget the coversion to
unsigned char.)
--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34