Topic: Howto make string upper, lower


Author: ncm@nospam.cantrip.org (Nathan Myers)
Date: 1998/02/01
Raw View
Stefan Gartz <Stefan.Gartz@abc.se> wrote:
>NM> Stefan Gartz <Stefan.Gartz@abc.se> wrote:
>NM> >How do I make a string upper or lower and using locale? >
>
>I have this working (almost right) in MS Visual c++ 5.0 on NT 4
>
>string Upper(const string &s)
>{
> string u = s;
> _USE(locale(), ctype<string::value_type>).toupper(u.begin(), u.end());
> // use_facet<string::value_type>(locale()).toupper(u.begin(),u.end());
> return u;
>}
>void main(void)
>{
> string s1,s2,s3;
>
> s1 = "some swedish letters";
>
> locale::global(locale::locale("Swedish"));
> s2 = Upper(s1); // This is nearly OK one letter is not rised
> // , may be some bug.
>
> setlocale( LC_ALL, "Swedish" );
> s3 = s1+" ";
> char p = (char *)s3.c_str();
> strupr(p); // This is OK all letters is raised.
>}

I don't know what strupr() does.  Anyway, the iterators for string
on MSVC++ just happen to be pointers, but the standard doesn't say
they must; so the code above is not portable outside MSVC++, and
perhaps not even from one release to the next of that.  The code
below is longer, but portable (modulo bugs).

>NM>   std::string
>NM>   upcase(
>NM>     const std::string& s,
>NM>     const std::locale& loc)
>NM>   {
>NM>     std::string result;
>NM>     char* buf = new char[s.size()];
>NM>     memcpy(buf,s.data(),s.size());
>NM>     try {
>NM>       std::use_facet< std::ctype<char> >(loc).
>NM>         toupper(buf, buf+s.size());
>NM>       result.assign(buf, s.size());
>NM>       delete [] buf;
>NM>     } catch (...) { delete [] buf; throw; }
>NM>     return result;
>NM>   }

Anyway, if you only care about Swedish, why bother using standard
locale facilities at all?  You can hardwire it to get the result
you want.

Nathan Myers
ncm@nospam.cantrip.org  http://www.cantrip.org/
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Stefan.Gartz@abc.se (Stefan Gartz)
Date: 1998/01/27
Raw View
How do I make a string upper or lower and using locale?

string s;
s=3D "=E5=E4=F6" // swedish lower
s.upper() //????
if (s =3D=3D "=C5=C4=D6")=20
 ;// swedish upper OK
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: ncm@nospam.cantrip.org (Nathan Myers)
Date: 1998/01/29
Raw View
Stefan Gartz <Stefan.Gartz@abc.se> wrote:
>How do I make a string upper or lower and using locale?
>
>string s;
>s=3D "=E5=E4=F6" // swedish lower
>s.upper() //????
>if (s =3D=3D "=C5=C4=D6")=20
> ;// swedish upper OK

I don't know what the text above was supposed to say,
but I can guess.  There are two answers to your question,
neither as simple as you might like.

The first answer is, write a function:

  std::string
  upcase(
    const std::string& s,
    const std::locale& loc)
  {
    std::string result;
    char* buf = new char[s.size()];
    memcpy(buf,s.data(),s.size());
    try {
      std::use_facet< std::ctype<char> >(loc).
        toupper(buf, buf+s.size());
      result.assign(buf, s.size());
      delete [] buf;
    } catch (...) { delete [] buf; throw; }
    return result;
  }

(This involves two allocations; std::string is not my favorite
part of the standard library.)  Unfortunately, this only works
for languages in which the upper-case representation is the same
length as the lower-case form.  I don't know what would happen
in other languages (e.g. German).

Think about what you're trying to do.  Do you really want to
store the up-cased string, or do you want to compare and sort
strings ignoring case?

Consider instead using a locale object as the Compare argument
to a container or algorithm template.  Then it's a "simple matter"
to construct a locale to use, with a collate<> facet that ignores
case.  Unfortunately I don't know of any systems that provide
standard locale files with this property; so you would need to
roll your own, for now.  But then it would be correct, and
portable to any language.

Nathan Myers
ncm@cantrip.org
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Stefan.Gartz@abc.se (Stefan Gartz)
Date: 1998/01/30
Raw View
NM> Stefan Gartz <Stefan.Gartz@abc.se> wrote:
NM> >How do I make a string upper or lower and using locale? >
NM> >string s;
NM> >s=3D "=E5=E4=F6" // swedish lower
NM> >s.upper() //????
NM> >if (s =3D=3D "=C5=C4=D6")=20
NM> > ;// swedish upper OK
NM>
I have this working (almost right) in MS Visual c++ 5.0 on NT 4

string Upper(const string &s)
{
 string u = s;
 _USE(locale(), ctype<string::value_type>).toupper(u.begin(), u.end());
 // _USE is a macro for MS Visual C++ 5.0 for Standard C++ Library:s use_facet
 // use_facet<string::value_type>(locale()).toupper(u.begin(),u.end());
 return u;
}
void main(void)
{
 string s1,s2,s3;

 s1 = "some swedish letters";

 locale::global(locale::locale("Swedish"));
 s2 = Upper(s1); // This is nearly OK one letter is not rised, may be some bug.


 setlocale( LC_ALL, "Swedish" );
 s3 = s1+" ";
 char p = (char *)s3.c_str();
 strupr(p); // This is OK all letters is raised.
}


NM> I don't know what the text above was supposed to say, but I can
NM> guess.  There are two answers to your question, neither as simple
NM> as you might like.
NM>
NM> The first answer is, write a function:
NM>
NM>   std::string
NM>   upcase(
NM>     const std::string& s,
NM>     const std::locale& loc)
NM>   {
NM>     std::string result;
NM>     char* buf = new char[s.size()];
NM>     memcpy(buf,s.data(),s.size());
NM>     try {
NM>       std::use_facet< std::ctype<char> >(loc).
NM>         toupper(buf, buf+s.size());
NM>       result.assign(buf, s.size());
NM>       delete [] buf;
NM>     } catch (...) { delete [] buf; throw; }
NM>     return result;
NM>   }
NM>
NM> (This involves two allocations; std::string is not my favorite
NM> part of the standard library.)  Unfortunately, this only works
NM> for languages in which the upper-case representation is the same
NM> length as the lower-case form.  I don't know what would happen in
NM> other languages (e.g. German).
NM>
NM> Think about what you're trying to do.  Do you really want to
NM> store the up-cased string, or do you want to compare and sort
NM> strings ignoring case?

I want to make the strings letters stored in uppercase.


[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]