convert a string to all-lowercase string

  • Thread starter federico_bertola
  • Start date
F

federico_bertola

Hi everybody,
I have an array of chars that I want to make all lower

int Scan(char Search[])
{
char *cPtr;
cPtr = strtok (Search," -,.");

while (cPtr != NULL)
{
// Here I want to lower cPtr whith somithing like cPtr =
tolower(cPtr)
//but don't works
printf("%s ", cPtr);
cPtr = strtok (NULL, " -,.");
}
}

Help me please!
Thx a lot! :)
 
S

santosh

Hi everybody,
I have an array of chars that I want to make all lower

int Scan(char Search[])
{
char *cPtr;
cPtr = strtok (Search," -,.");

while (cPtr != NULL)
{
// Here I want to lower cPtr whith somithing like cPtr =
tolower(cPtr)
//but don't works
printf("%s ", cPtr);
cPtr = strtok (NULL, " -,.");
}
}

strtok() is a subtly complicated function to use. Just loop through
your array testing for an alphabetic character with isalpha() and if
so, check if it's already in lowercase with islower() and if not,
convert with tolower().
 
F

federico_bertola

err... hehe,
I understand what do you mean but if you can post a sample code please!
(I'm a newbye)
Thx for the help :)
 
S

santosh

err... hehe,
I understand what do you mean but if you can post a sample code please!
(I'm a newbye)
Thx for the help :)

#include <stdio.h>
#include <ctype.h>

int main(void) {
int c;

while((c = getchar()) != EOF) {
if(isalpha((unsigned char) c)) {
if(isupper((unsigned char) c))
c = tolower((unsigned char) c);
}
putchar(c);
}
return 0;
}
 
F

federico_bertola

santosh ha scritto:
#include <stdio.h>
#include <ctype.h>

int main(void) {
int c;

while((c = getchar()) != EOF) {
if(isalpha((unsigned char) c)) {
if(isupper((unsigned char) c))
c = tolower((unsigned char) c);
}
putchar(c);
}
return 0;
}

Thx again :)))
 
J

Jack Klein

Hi everybody,
I have an array of chars that I want to make all lower

int Scan(char Search[])
{
char *cPtr;
cPtr = strtok (Search," -,.");

while (cPtr != NULL)
{
// Here I want to lower cPtr whith somithing like cPtr =
tolower(cPtr)
//but don't works
printf("%s ", cPtr);
cPtr = strtok (NULL, " -,.");
}
}

strtok() is a subtly complicated function to use. Just loop through
your array testing for an alphabetic character with isalpha() and if
so, check if it's already in lowercase with islower() and if not,
convert with tolower().

The use of isalpha() and islower() functions is completely unnecessary
in this case.

islower() alone only returns non-zero if its argument is a lower case
alpha character.

But neither function is required. tolower(), for a valid argument,
returns a different value from the argument if and only if the
argument is an upper case alpha character with a lower case
equivalent, otherwise it returns its argument unchanged.

Note that the argument must be valid, however, namely an int with a
value of either EOF or in the range of 0 to UCHAR_MAX inclusive. On
implementations where char is signed, some characters might have
negative values and passing one of those to any of the to... or is...
functions produces undefined behavior.

The usual advice given here is to cast each character to unsigned char
when passing to the to... or is... functions. I don't particularly
like that approach, because some characters with negative values (such
as PC text mode "extended ASCII") will get changed that you probably
don't want changed.

The safest way to do this to only valid uppercase letters is something
like this (uncompiled and untested):

#include <ctype.h>

char *(string_to_lower char *s)
{
char *ret = s;

if (s)
{
while (*s)
{
if (*s > 0)
{
*s = tolower(*s);
}
++s;
}
}
return ret;
}
 
F

federico_bertola

santosh ha scritto:
#include <stdio.h>
#include <ctype.h>

int main(void) {
int c;

while((c = getchar()) != EOF) {
if(isalpha((unsigned char) c)) {
if(isupper((unsigned char) c))
c = tolower((unsigned char) c);
}
putchar(c);
}
return 0;
}

Thx again :)))
 
S

santosh

Jack said:
Hi everybody,
I have an array of chars that I want to make all lower

int Scan(char Search[])
{
char *cPtr;
cPtr = strtok (Search," -,.");

while (cPtr != NULL)
{
// Here I want to lower cPtr whith somithing like cPtr =
tolower(cPtr)
//but don't works
printf("%s ", cPtr);
cPtr = strtok (NULL, " -,.");
}
}

strtok() is a subtly complicated function to use. Just loop through
your array testing for an alphabetic character with isalpha() and if
so, check if it's already in lowercase with islower() and if not,
convert with tolower().

The use of isalpha() and islower() functions is completely unnecessary
in this case.

islower() alone only returns non-zero if its argument is a lower case
alpha character.

But neither function is required. tolower(), for a valid argument,
returns a different value from the argument if and only if the
argument is an upper case alpha character with a lower case
equivalent, otherwise it returns its argument unchanged.

Points noted. Thanks.
Note that the argument must be valid, however, namely an int with a
value of either EOF or in the range of 0 to UCHAR_MAX inclusive. On
implementations where char is signed, some characters might have
negative values and passing one of those to any of the to... or is...
functions produces undefined behavior.

The usual advice given here is to cast each character to unsigned char
when passing to the to... or is... functions. I don't particularly
like that approach, because some characters with negative values (such
as PC text mode "extended ASCII") will get changed that you probably
don't want changed.

The safest way to do this to only valid uppercase letters is something
like this (uncompiled and untested):

#include <ctype.h>

char *(string_to_lower char *s)
{
char *ret = s;

if (s)
{
while (*s)
{
if (*s > 0)
{
*s = tolower(*s);
}
++s;
}
}
return ret;
}

Thanks for the code.

PS: You probably meant to write:
char *string_to_lower(char *s)
 
F

Flash Gordon

santosh said:
#include <stdio.h>
#include <ctype.h>

int main(void) {
int c;

while((c = getchar()) != EOF) {
if(isalpha((unsigned char) c)) {
if(isupper((unsigned char) c))
c = tolower((unsigned char) c);

I would simplify the above three lines by deleting the tests. For
non-alpha and for lower case letters tolower will return its input.
}
putchar(c);

while((c = getchar()) != EOF)
putchar(tolower(c));

getchar returns the character already in the range of unsigned char, so
in this case you don't even need the cast. Much simpler.
 
A

Andrew Poelstra

#include <stdio.h>
#include <ctype.h>

int main(void) {
int c;

while((c = getchar()) != EOF) {
if(isalpha((unsigned char) c)) {
if(isupper((unsigned char) c))
c = tolower((unsigned char) c);
}
putchar(c);
}
return 0;
}

I wouldn't have that isupper() call in there; in ASCII at least, tolower
can be implemented as a single AND, and therefore would be more efficient
(and perhaps more clear) if you simply tested for an alpha and then did
tolower.
 
S

santosh

Andrew said:
I wouldn't have that isupper() call in there; in ASCII at least,

You mean under ISO C?
tolower can be implemented as a single AND, and therefore would be more efficient
(and perhaps more clear) if you simply tested for an alpha and then did tolower.

Yes, I should've done that. As an aside, Jack Klien has eliminated even
isalpha() in his method, which he's posted elsethread.
 
F

Frederick Gotham

posted:
Hi everybody,
I have an array of chars that I want to make all lower


How about:

#include <ctype.h>

inline void StringToLower(char *p)
{
while ( *p = tolower(*p) ) ++p;
}


From what I've read, it seems that "tolower" returns the original value if
it was unable to convert it to lowercase, so we should have no worries
about passing it numbers, lowercase letters, symbols, or a null character.


If I were to change the loop slightly, would it violate the "sequence
point" rule?

while( *p++ = tolower(*p) );
 
A

Andrew Poelstra

#include <ctype.h>

char *(string_to_lower char *s)
{
char *ret = s;

if (s)
{
while (*s)
{
if (*s > 0)
{
*s = tolower(*s);
}
++s;
}
}
return ret;
}

This is more compact (and doesn't start with "str", invading implementation
namespace):

char *lowercase_string (char *s)
{
if (s)
while (*s)
{
*s = (*s > 0) ? tolower (*s) : *s;
s++;
}
}
 
J

Jack Klein

Jack said:
(e-mail address removed) wrote:
Hi everybody,
I have an array of chars that I want to make all lower

int Scan(char Search[])
{
char *cPtr;
cPtr = strtok (Search," -,.");

while (cPtr != NULL)
{
// Here I want to lower cPtr whith somithing like cPtr =
tolower(cPtr)
//but don't works
printf("%s ", cPtr);
cPtr = strtok (NULL, " -,.");
}
}

strtok() is a subtly complicated function to use. Just loop through
your array testing for an alphabetic character with isalpha() and if
so, check if it's already in lowercase with islower() and if not,
convert with tolower().

The use of isalpha() and islower() functions is completely unnecessary
in this case.

islower() alone only returns non-zero if its argument is a lower case
alpha character.

But neither function is required. tolower(), for a valid argument,
returns a different value from the argument if and only if the
argument is an upper case alpha character with a lower case
equivalent, otherwise it returns its argument unchanged.

Points noted. Thanks.
Note that the argument must be valid, however, namely an int with a
value of either EOF or in the range of 0 to UCHAR_MAX inclusive. On
implementations where char is signed, some characters might have
negative values and passing one of those to any of the to... or is...
functions produces undefined behavior.

The usual advice given here is to cast each character to unsigned char
when passing to the to... or is... functions. I don't particularly
like that approach, because some characters with negative values (such
as PC text mode "extended ASCII") will get changed that you probably
don't want changed.

The safest way to do this to only valid uppercase letters is something
like this (uncompiled and untested):

#include <ctype.h>

char *(string_to_lower char *s)
{
char *ret = s;

if (s)
{
while (*s)
{
if (*s > 0)
{
*s = tolower(*s);
}
++s;
}
}
return ret;
}

Thanks for the code.

PS: You probably meant to write:
char *string_to_lower(char *s)

Yes, I probably did. Thanks.
 
J

Jack Klein

This is more compact (and doesn't start with "str", invading implementation
namespace):

Quibble: names beginning with "str", "is", "to", and (maybe, can't
remember, can't bother to look it up) "mem" are reserved at file scope
only when followed by another lower case letter.

Of course, I goofed, should have been str_to_lower.

And as santosh pointed out, I got the function definition garbled.

Happy Monday.
char *lowercase_string (char *s)
{
if (s)
while (*s)
{
*s = (*s > 0) ? tolower (*s) : *s;
s++;
}
}

And returning what? Must be Monday where you are, too!

I probably wouldn't write it that way myself, but I certainly wouldn't
in a follow-up to a thread from an obvious newbie. YMMV.
 
E

Eric Sosman

Andrew said:
I wouldn't have that isupper() call in there;

Nor would I; it is unnecessary.
in ASCII at least, tolower
can be implemented as a single AND,

You probably mean either that toupper() can be implemented
as a single AND, or that tolower() can be implemented as a
single OR. Either way, you're wrong: consider tolower('^') as
a counter-example.
and therefore would be more efficient
(and perhaps more clear) if you simply tested for an alpha and then did
tolower.

Even the isalpha() test is unnecessary.

Long ago in the Bad Old Days the world was beset by Evil
Implementations of toupper() and tolower() that only worked
correctly on lower- or upper-case arguments, things like

#define toupper(c) ((c) + 'A' - 'a') /* BADDD! */
#define tolower(c) ((c) + 'a' - 'A') /* WRONG! */

Code like this never really worked at all: it had a nasty way
of misbehaving on things like toupper((unsigned char)'ä'), for
example (that's a lower-case A with diaresis, if you're having
trouble seeing it). This kind of implementation became non-
conforming the very instant there was a Standard to conform to,
almost seventeen years ago.
 
E

Eric Sosman

Jack said:
The usual advice given here is to cast each character to unsigned char
when passing to the to... or is... functions. I don't particularly
like that approach, because some characters with negative values (such
as PC text mode "extended ASCII") will get changed that you probably
don't want changed.

If you'd rather have 'Ã' remain unchanged instead of
being replaced by 'ã', that's your choice -- but leaving
it unchanged doesn't agree with the Standard's notion of
"lower case."
The safest way to do this to only valid uppercase letters is something
like this (uncompiled and untested):

#include <ctype.h>

char *(string_to_lower char *s)
{
char *ret = s;

if (s)
{
while (*s)
{
if (*s > 0)
{
*s = tolower(*s);
}
++s;
}
}
return ret;
}

I cannot see any reason to call this "safer" than the
recommended alternative: Lose the test and add the cast.
That's the recipe that puts the argument in the form that
tolower() and all the other <ctype.h> functions expect. If
you like to call the library functions in screwball ways, it
is not their fault if you get unsatisfactory results.
 
K

Keith Thompson

santosh said:
#include <stdio.h>
#include <ctype.h>

int main(void) {
int c;

while((c = getchar()) != EOF) {
if(isalpha((unsigned char) c)) {
if(isupper((unsigned char) c))
c = tolower((unsigned char) c);
}
putchar(c);
}
return 0;
}

Note that this doesn't address the original question. The OP wanted
to convert a string to lower case; you're converting stdin to lower
case and writing it to stdout. (Perhaps this was intentional, to
avoid doing the OP's homework.)

Others have pointed out the redundancy of the isalpha() and isupper()
calls.
 
S

santosh

Keith said:
Note that this doesn't address the original question. The OP wanted
to convert a string to lower case; you're converting stdin to lower
case and writing it to stdout. (Perhaps this was intentional, to
avoid doing the OP's homework.)

Indeed, though in hindsight my post has, (justifiably), recieved so
many replies, I wonder if the OP is confused, (he admitted to being a
newbie).
Others have pointed out the redundancy of the isalpha() and isupper()
calls.

I knew that isupper() is redundant, but I retained it just to keep the
logic of the routine straightforward, (a tolower() on it's own would
need additional explanations to the OP).
 

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

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top