according to MS, stricmp is deprecated

Discussion in 'C++' started by Lynn McGuire, Apr 25, 2013.

  1. Lynn McGuire

    Lynn McGuire Guest

    According to Microsoft Visual C++ 2005, stricmp
    is deprecated and they want us to use _stricmp.

    Does anyone know why?

    Does anyone recommend a good replacement?

    Thanks,
    Lynn McGuire
     
    Lynn McGuire, Apr 25, 2013
    #1
    1. Advertising

  2. Lynn McGuire

    Lynn McGuire Guest

    On 4/25/2013 3:32 PM, Lynn McGuire wrote:
    > According to Microsoft Visual C++ 2005, stricmp
    > is deprecated and they want us to use _stricmp.
    >
    > Does anyone know why?
    >
    > Does anyone recommend a good replacement?
    >
    > Thanks,
    > Lynn McGuire


    BTW, here is the MS note about stricmp:
    http://msdn.microsoft.com/en-us/library/ms235365(v=vs.80).aspx

    Thanks,
    Lynn
     
    Lynn McGuire, Apr 25, 2013
    #2
    1. Advertising

  3. Lynn McGuire

    Lynn McGuire Guest

    On 4/25/2013 3:59 PM, Robert Wessel wrote:
    > On Thu, 25 Apr 2013 15:32:53 -0500, Lynn McGuire <>
    > wrote:
    >
    >> According to Microsoft Visual C++ 2005, stricmp
    >> is deprecated and they want us to use _stricmp.
    >>
    >> Does anyone know why?
    >>
    >> Does anyone recommend a good replacement?

    >
    >
    > As the MS note says, stricmp() is not a standard C function. As it
    > uses a namespace (functions starting with "str") reserved for the
    > standard, they removed it (sort of). Although MS mentions that it's a
    > Posix function, I don't think that's actually true.
    >
    > If you're programming for Windows, use the version with the
    > underscore. If you port to a *nix system, you'll probably want to use
    > strcasecmp instead, although some do provide a (_)stricmp function.


    This particular code runs on both Windows and
    Unix. I was hoping that that MS supported a
    strcasecmp function but VS 2005 does not.

    Thanks,
    Lynn
     
    Lynn McGuire, Apr 25, 2013
    #3
  4. Lynn McGuire

    Lynn McGuire Guest

    On 4/25/2013 4:13 PM, Paavo Helde wrote:
    > Lynn McGuire <> wrote in news:klc3t0$4b0$:
    >
    >> On 4/25/2013 3:32 PM, Lynn McGuire wrote:
    >>> According to Microsoft Visual C++ 2005, stricmp
    >>> is deprecated and they want us to use _stricmp.
    >>>
    >>> Does anyone know why?
    >>>
    >>> Does anyone recommend a good replacement?
    >>>
    >>> Thanks,
    >>> Lynn McGuire

    >>
    >> BTW, here is the MS note about stricmp:
    >> http://msdn.microsoft.com/en-us/library/ms235365(v=vs.80).aspx

    >
    > In general these 'deprecated' warnings seem to be yet another attempt by MS
    > to force people in writing unportable code. In the case of stricmp()
    > however it is an overkill as stricmp() itself is already unportable (the
    > POSIX name is strcasecmp()).
    >
    > The best way to fight with this is to use:
    >
    > #ifdef _MSC_VER
    > inline int strcasecmp(const char* a, const char* b) {
    > return _stricmp(a, b);
    > }
    > #endif
    >
    > and use strcasecmp() in your code. This will make it *more* portable!
    >
    > Cheers
    > Paavo


    Thanks, I like that !

    Lynn
     
    Lynn McGuire, Apr 25, 2013
    #4
  5. Lynn McGuire

    James Kanze Guest

    On Thursday, April 25, 2013 9:32:53 PM UTC+1, Lynn McGuire wrote:
    > According to Microsoft Visual C++ 2005, stricmp


    > is deprecated and they want us to use _stricmp.
    > Does anyone know why?


    My immediate reaction would be: how do you deprecate something that
    never existed? There isn't, and never has been, such a function in
    standard C or C++. It is, never the less, a wide spread extension; many
    implementations even put it in <string.h> (which is in violation of the
    standard). In the case of Microsoft, I think that they are simply
    trying to clean up <string.h>, by removing all functions which aren't
    allowed to be their, and renaming them with names the standard allows
    implementations to use.

    > Does anyone recommend a good replacement?


    The error message gives one. Since any use is implementation dependent.
    (Even when several implementations provide it, you have no guarantee
    that they will provide the same semantics.)

    --
    James
     
    James Kanze, Apr 27, 2013
    #5
  6. Lynn McGuire

    Geoff Guest

    On Thu, 25 Apr 2013 16:02:03 -0500, Lynn McGuire <>
    wrote:

    >On 4/25/2013 3:59 PM, Robert Wessel wrote:
    >> On Thu, 25 Apr 2013 15:32:53 -0500, Lynn McGuire <>
    >> wrote:
    >>
    >>> According to Microsoft Visual C++ 2005, stricmp
    >>> is deprecated and they want us to use _stricmp.
    >>>
    >>> Does anyone know why?
    >>>
    >>> Does anyone recommend a good replacement?

    >>
    >>
    >> As the MS note says, stricmp() is not a standard C function. As it
    >> uses a namespace (functions starting with "str") reserved for the
    >> standard, they removed it (sort of). Although MS mentions that it's a
    >> Posix function, I don't think that's actually true.
    >>
    >> If you're programming for Windows, use the version with the
    >> underscore. If you port to a *nix system, you'll probably want to use
    >> strcasecmp instead, although some do provide a (_)stricmp function.

    >
    >This particular code runs on both Windows and
    >Unix. I was hoping that that MS supported a
    >strcasecmp function but VS 2005 does not.
    >
    >Thanks,
    >Lynn
    >
    >


    I've been using this for years on a project that works in Windows and
    Linux. (VS 6.0 to VS 2010 and a long list of GCC versions.

    /* old non-standard lib function to new non-standard lib function */
    #ifdef _WIN32
    #define stricmp _stricmp
    #endif
     
    Geoff, Apr 28, 2013
    #6
  7. Lynn McGuire

    Geoff Guest

    On Thu, 25 Apr 2013 16:02:03 -0500, Lynn McGuire <>
    wrote:

    >On 4/25/2013 3:59 PM, Robert Wessel wrote:
    >> On Thu, 25 Apr 2013 15:32:53 -0500, Lynn McGuire <>
    >> wrote:
    >>
    >>> According to Microsoft Visual C++ 2005, stricmp
    >>> is deprecated and they want us to use _stricmp.
    >>>
    >>> Does anyone know why?
    >>>
    >>> Does anyone recommend a good replacement?

    >>
    >>
    >> As the MS note says, stricmp() is not a standard C function. As it
    >> uses a namespace (functions starting with "str") reserved for the
    >> standard, they removed it (sort of). Although MS mentions that it's a
    >> Posix function, I don't think that's actually true.
    >>
    >> If you're programming for Windows, use the version with the
    >> underscore. If you port to a *nix system, you'll probably want to use
    >> strcasecmp instead, although some do provide a (_)stricmp function.

    >
    >This particular code runs on both Windows and
    >Unix. I was hoping that that MS supported a
    >strcasecmp function but VS 2005 does not.
    >
    >Thanks,
    >Lynn
    >
    >

    That is fixable.

    #ifdef _WIN32
    #include <ctype.h>

    int strcasecmp(const char *s1, const char *s2)
    {
    const unsigned char
    *uc1 = (const unsigned char *)s1,
    *uc2 = (const unsigned char *)s2;

    while (tolower(*uc1) == tolower(*uc2++))
    if (*uc1++ == '\0')
    return (0);
    return (tolower(*uc1) - tolower(*--uc2));
    }
    #endif

    I don't know if this conforms to the current standard for strcasecmp.
     
    Geoff, Apr 28, 2013
    #7
  8. Lynn McGuire

    Geoff Guest

    On Sun, 28 Apr 2013 01:23:20 -0500, Paavo Helde
    <> wrote:

    >What's wrong with an inline forwarding function?


    Nothing. As it is, I got off my ass this weekend and eliminated the
    rename and implemented the strcasecmp function within the application,
    conditional on _WIN32 as I posted here earlier. A hack is a hack and
    it was time to eliminate that one.

    Since we're in comp.lang.c++, what do you think of this implementation
    of a case-insensitive compare of C++ strings?

    int stringcasecmp(const std::string s1, const std::string s2)
    {
    std::string us1 = s1;
    std::string us2 = s2;
    std::transform(us1.begin(), us1.end(), us1.begin(), ::tolower);
    std::transform(us2.begin(), us2.end(), us2.begin(), ::tolower);
    return us1.compare(us2);
    }

    Improvements?
     
    Geoff, Apr 29, 2013
    #8
  9. Lynn McGuire

    Geoff Guest

    On Mon, 29 Apr 2013 17:24:52 GMT, (Scott Lurndal)
    wrote:

    >Geoff <> writes:
    >>On Sun, 28 Apr 2013 01:23:20 -0500, Paavo Helde
    >><> wrote:
    >>
    >>>What's wrong with an inline forwarding function?

    >>
    >>Nothing. As it is, I got off my ass this weekend and eliminated the
    >>rename and implemented the strcasecmp function within the application,
    >>conditional on _WIN32 as I posted here earlier. A hack is a hack and
    >>it was time to eliminate that one.
    >>
    >>Since we're in comp.lang.c++, what do you think of this implementation
    >>of a case-insensitive compare of C++ strings?
    >>
    >>int stringcasecmp(const std::string s1, const std::string s2)
    >>{
    >> std::string us1 = s1;
    >> std::string us2 = s2;
    >> std::transform(us1.begin(), us1.end(), us1.begin(), ::tolower);
    >> std::transform(us2.begin(), us2.end(), us2.begin(), ::tolower);
    >> return us1.compare(us2);
    >>}
    >>
    >>Improvements?

    >
    >Why wouldn't you add
    >
    > int casecompare(const string &str) const
    > int casecompare(size_t, size_t, const string &) const;
    > int casecompare(size_t, size_t, const char *) const;
    >
    > et alia (analogs to std::string::compare methods)
    >
    >members to std::string?
    >
    > std::string s;
    > std::string t;
    >
    > if (s.casecompare(t) == 0) ...
    > if (s.casecompare(1, std::string::npos, "Testing") == 0) ...


    Indeed I would. Do you have any recommendations for how to implement
    them?
     
    Geoff, Apr 29, 2013
    #9
  10. Lynn McGuire

    Geoff Guest

    On Mon, 29 Apr 2013 12:57:51 -0500, Paavo Helde
    <> wrote:

    >Geoff <> wrote in
    >news::
    >
    >> On Sun, 28 Apr 2013 01:23:20 -0500, Paavo Helde
    >> <> wrote:
    >>
    >>>What's wrong with an inline forwarding function?

    >>
    >> Nothing. As it is, I got off my ass this weekend and eliminated the
    >> rename and implemented the strcasecmp function within the application,
    >> conditional on _WIN32 as I posted here earlier. A hack is a hack and
    >> it was time to eliminate that one.
    >>
    >> Since we're in comp.lang.c++, what do you think of this implementation
    >> of a case-insensitive compare of C++ strings?
    >>
    >> int stringcasecmp(const std::string s1, const std::string s2)
    >> {
    >> std::string us1 = s1;
    >> std::string us2 = s2;
    >> std::transform(us1.begin(), us1.end(), us1.begin(), ::tolower);
    >> std::transform(us2.begin(), us2.end(), us2.begin(), ::tolower);
    >> return us1.compare(us2);
    >> }

    >
    >This calls C function tolower(int), which has undefined behavior in case
    >of negative arguments. As the plain char type used by std::string is
    >often a signed type it can easily contain negative values. So this
    >implementation seems quite dangerous.
    >
    >Even if the correct C++ std::tolower() function were used, it could not
    >properly support multibyte characters like UTF-8 encoding. I am even not
    >talking about comparing German ß and SS.
    >
    >It also makes copies of the both strings (twice, as the parameters are
    >not references), then makes two passes through both strings, which may
    >become suboptimal if the strings do not fit in the cpu caches.
    >
    >As the above function basically works only for ASCII (never seen EBCDIC
    >in real life), it would be best to acknowledge this; then calling the
    >locale-specific ::tolower would be wrong and also not necessary. Improved
    >version:
    >
    >int strcasecmp_ascii(const std::string& s1, const std::string& s2)
    >{
    > const std::string::size_type n = std::min(s1.length(), s2.length());
    > for (std::string::size_type i = 0; i<n; ++i) {
    > char c1 = s1, c2=s2;
    > if (c1>='A' && c1<='Z') {
    > c1+=32;
    > }
    > if (c2>='A' && c2<='Z') {
    > c2+=32;
    > }
    > if (c1<c2) {
    > return -1;
    > } else if (c1>c2) {
    > return 1;
    > }
    > }
    > return s1.length()>n? 1: (s2.length()>n? -1: 0);
    >}


    I wouldn't call that an improvement.

    I would modify mine to eliminate your objections about unnecessary
    copies of the strings. The goal was to make it non destructive of the
    original strings.

    //headers needed for implementing this function
    #include <string>
    #include <algorithm>
    #include <locale.h>

    int stringcasecmp(std::string s1, std::string s2)
    {
    std::transform(s1.begin(), s1.end(), s1.begin(), ::tolower);
    std::transform(s2.begin(), s2.end(), s2.begin(), ::tolower);
    return s1.compare(s2);
    }

    Which makes it work if the locale is set to a language other than
    English. Since any program at any given time is perforce confined to a
    given locale, I don't see a problem with using tolower in this
    specific instance. The original goal of this function was to apply the
    admittedly flawed principles of C's strcasecmp() to C++ strings and
    strcasecmp calls tolower() and I have never seen one that solves the
    general locale-independent problem. Your concern about UTF and signed
    char types is worrisome and I don't have an immediate solution.

    You make a cogent argument for a general solution to the problem but
    you don't offer one. Since the standard doesn't provide a case
    insensitive compare member, perhaps there is no satisfactory general
    solution.
     
    Geoff, Apr 29, 2013
    #10
  11. Lynn McGuire

    Geoff Guest

    On Mon, 29 Apr 2013 16:08:57 -0500, Paavo Helde
    <> wrote:

    >Geoff <> wrote in
    >news::
    >
    >> On Mon, 29 Apr 2013 12:57:51 -0500, Paavo Helde
    >> <> wrote:
    >>
    >>>Geoff <> wrote in
    >>>news::
    >>>
    >>>> On Sun, 28 Apr 2013 01:23:20 -0500, Paavo Helde
    >>>> <> wrote:
    >>>>
    >>>>>What's wrong with an inline forwarding function?
    >>>>
    >>>> Nothing. As it is, I got off my ass this weekend and eliminated the
    >>>> rename and implemented the strcasecmp function within the
    >>>> application, conditional on _WIN32 as I posted here earlier. A hack
    >>>> is a hack and it was time to eliminate that one.
    >>>>
    >>>> Since we're in comp.lang.c++, what do you think of this
    >>>> implementation of a case-insensitive compare of C++ strings?
    >>>>
    >>>> int stringcasecmp(const std::string s1, const std::string s2)
    >>>> {
    >>>> std::string us1 = s1;
    >>>> std::string us2 = s2;
    >>>> std::transform(us1.begin(), us1.end(), us1.begin(), ::tolower);
    >>>> std::transform(us2.begin(), us2.end(), us2.begin(), ::tolower);
    >>>> return us1.compare(us2);
    >>>> }
    >>>
    >>>This calls C function tolower(int), which has undefined behavior in
    >>>case of negative arguments. As the plain char type used by std::string
    >>>is often a signed type it can easily contain negative values. So this
    >>>implementation seems quite dangerous.
    >>>
    >>>Even if the correct C++ std::tolower() function were used, it could
    >>>not properly support multibyte characters like UTF-8 encoding. I am
    >>>even not talking about comparing German ß and SS.
    >>>
    >>>It also makes copies of the both strings (twice, as the parameters are
    >>>not references), then makes two passes through both strings, which may
    >>>become suboptimal if the strings do not fit in the cpu caches.
    >>>
    >>>As the above function basically works only for ASCII (never seen
    >>>EBCDIC in real life), it would be best to acknowledge this; then
    >>>calling the locale-specific ::tolower would be wrong and also not
    >>>necessary. Improved version:
    >>>
    >>>int strcasecmp_ascii(const std::string& s1, const std::string& s2)
    >>>{
    >>> const std::string::size_type n = std::min(s1.length(), s2.length());
    >>> for (std::string::size_type i = 0; i<n; ++i) {
    >>> char c1 = s1, c2=s2;
    >>> if (c1>='A' && c1<='Z') {
    >>> c1+=32;
    >>> }
    >>> if (c2>='A' && c2<='Z') {
    >>> c2+=32;
    >>> }
    >>> if (c1<c2) {
    >>> return -1;
    >>> } else if (c1>c2) {
    >>> return 1;
    >>> }
    >>> }
    >>> return s1.length()>n? 1: (s2.length()>n? -1: 0);
    >>>}

    >>
    >> I wouldn't call that an improvement.
    >>
    >> I would modify mine to eliminate your objections about unnecessary
    >> copies of the strings. The goal was to make it non destructive of the
    >> original strings.
    >>
    >> //headers needed for implementing this function
    >> #include <string>
    >> #include <algorithm>
    >> #include <locale.h>
    >>
    >> int stringcasecmp(std::string s1, std::string s2)
    >> {
    >> std::transform(s1.begin(), s1.end(), s1.begin(), ::tolower);
    >> std::transform(s2.begin(), s2.end(), s2.begin(), ::tolower);
    >> return s1.compare(s2);
    >> }

    >
    >This is still ignoring the undefined behavior of ::tolower with negative
    >values. See http://www.unix.com/man-page/POSIX/3posix/tolower/.
    >
    >> You make a cogent argument for a general solution to the problem but
    >> you don't offer one.

    >
    >I'm not quite sure what the problem is. If it is just implementing
    >strcasecmp() on Windows, then one can just forward to _stricmp() or
    >better yet to _wcsicmp().


    This advice is amusing because Microsoft's _stricmp() and _wcsicmp()
    both use ascii and wide versions of tolower().

    >
    >If it is about implementing it without using the C portion of the C++
    >standard then you have failed as ::tolower is a C function as well.
    >


    No, it's not about that at all.

    >If it is about providing a general solution of case insensitive string
    >comparison then this has been already long done as strcasecmp() is part
    >of POSIX.
    >


    This is also amusing because the POSIX documentation states it is both
    locale specific and depends on the tolower conversion.

    http://pubs.opengroup.org/onlinepubs/9699919799/

    "...

    The strcasecmp() and strncasecmp() functions use the current locale to
    determine the case of the characters.

    The strcasecmp_l() and strncasecmp_l() functions use the locale
    represented by locale to determine the case of the characters.

    When the LC_CTYPE category of the locale being used is from the POSIX
    locale, these functions shall behave as if the strings had been
    converted to lowercase and then a byte comparison performed.
    Otherwise, the results are unspecified.

    The behavior is undefined if the locale argument to strcasecmp_l() or
    strncasecmp_l() is the special locale object LC_GLOBAL_LOCALE or is
    not a valid locale object handle."

    All the implementations strcasecmp() I have been able to find trace
    their parentage to BSD 4.3 from 1993 to wit:

    int strcasecmp(const char *s1, const char *s2)
    {
    const unsigned char
    *uc1 = (const unsigned char *)s1,
    *uc2 = (const unsigned char *)s2;

    while (tolower(*uc1) == tolower(*uc2++))
    if (*uc1++ == '\0')
    return (0);
    return (tolower(*uc1) - tolower(*--uc2));
    }
     
    Geoff, Apr 30, 2013
    #11
  12. Lynn McGuire

    James Kanze Guest

    On Monday, April 29, 2013 6:15:36 PM UTC+1, Geoff wrote:
    > On Sun, 28 Apr 2013 01:23:20 -0500, Paavo Helde
    > <> wrote:


    > >What's wrong with an inline forwarding function?


    > Nothing. As it is, I got off my ass this weekend and eliminated the
    > rename and implemented the strcasecmp function within the application,
    > conditional on _WIN32 as I posted here earlier. A hack is a hack and
    > it was time to eliminate that one.


    > Since we're in comp.lang.c++, what do you think of this implementation
    > of a case-insensitive compare of C++ strings?


    > int stringcasecmp(const std::string s1, const std::string s2)
    > {
    > std::string us1 = s1;
    > std::string us2 = s2;
    > std::transform(us1.begin(), us1.end(), us1.begin(), ::tolower);
    > std::transform(us2.begin(), us2.end(), us2.begin(), ::tolower);
    > return us1.compare(us2);
    > }


    For starters, it has undefined behavior: you can't call
    ::tolower on a char.

    Performance-wise, of course: is there really any reason to build
    two new strings? Wouldn't it be a lot better if you did the
    transformations on the fly? (I'm supposing the fact that you
    use pass by value, rather than references, is an oversight.)

    And perhaps above all: what is the program really supposed to
    do? (In most contexts, today, I would want it to handle UTF-8.
    Obviously, this one doesn't, but what about "MASSE" vs. "Maße"?)
    Shouldn't it be locale sensitive?

    Part of the problem (and perhaps the reason why C and C++ didn't
    adopt anything similar) is because case-insensitive compare
    isn't really a well defined concept.

    --
    James
     
    James Kanze, Apr 30, 2013
    #12
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Barney Barumba
    Replies:
    0
    Views:
    565
    Barney Barumba
    Jul 23, 2003
  2. William  Krick

    comparing two strcasecmp (stricmp) implementations

    William Krick, Nov 10, 2005, in forum: C Programming
    Replies:
    88
    Views:
    2,628
  3. jamihuq
    Replies:
    18
    Views:
    1,739
  4. xuatla
    Replies:
    11
    Views:
    750
    Robbie Hatley
    Sep 26, 2005
  5. Michael Sgier

    stricmp

    Michael Sgier, Jul 6, 2006, in forum: C++
    Replies:
    2
    Views:
    639
    Walt Stoneburner
    Jul 7, 2006
Loading...

Share This Page