lower case to upper case

J

Janice

char* line = "abcd";
How to convert the line to upper case and print?
Any option for printf to do this?
Thanx
 
R

Ravi Uday

Janice said:
char* line = "abcd";
How to convert the line to upper case and print?
Any option for printf to do this?
Thanx

Not sure if there is a exclusive function in 'C' to do it
but tivially you could do:

- Get each character one by one from the input array/string.
- Check whether the character is lower/upper using 'islower'or 'isupper'
functions
- If character is upper case, then Add 32 to get its lower case
equivalent or
- If character is lower case Subtract 32 to get its upper case.
- Store or print the converted characters.

You might want to do error checking on the input array too if they are
valid alphabets !

- Ravi
 
J

Joona I Palaste

Not sure if there is a exclusive function in 'C' to do it

There is. Check out toupper().
but tivially you could do:
- Get each character one by one from the input array/string.
- Check whether the character is lower/upper using 'islower'or 'isupper'
functions
- If character is upper case, then Add 32 to get its lower case
equivalent or
- If character is lower case Subtract 32 to get its upper case.
- Store or print the converted characters.

Bzzzt. No one told you you were using ASCII, ISO-8859-1 or any other
charset where upper and lower case are 32 bytes apart.
 
Z

Zoran Cutura

Ravi Uday said:
Not sure if there is a exclusive function in 'C' to do it
but tivially you could do:

- Get each character one by one from the input array/string.
- Check whether the character is lower/upper using 'islower'or 'isupper'
functions
- If character is upper case, then Add 32 to get its lower case
equivalent or
- If character is lower case Subtract 32 to get its upper case.
- Store or print the converted characters.

You might want to do error checking on the input array too if they are
valid alphabets !


ever heard of tolower/toupper?

Your suggestions are not portable and will only function on a machine
where all lower case characters are represented by a value that is by 32
bigger than the according upper case characters representation. As this
need not actually be the case the standard provides you with functions
that need to be supported by your implementations, which makes usage of
them portable.
 
C

CBFalconer

Janice said:
char* line = "abcd";
How to convert the line to upper case and print?
Any option for printf to do this?

You can't and no. However if you had defined line as:

char line[] = "abcd";

you would have been able to convert it. Now you should spend some
time thinking about what the difference is. It is fundamental.
 
M

Mark A. Odell

Janice said:
char* line = "abcd";

Pointer mis-match, char *line should not point to a const char * "abcd".
What if "abcd" is placed into non-writable memory?
How to convert the line to upper case and print?

Use a writable array, like CBFalconer suggests, then call toupper() on the
array.
Any option for printf to do this?

printf("%s\n", name-of-writable-array);
Thanks
 
E

Eric Sosman

Mark said:
Pointer mis-match, char *line should not point to a const char * "abcd".
What if "abcd" is placed into non-writable memory?

No mismatch. The literal creates an array of ordinary
`char', not `const'-qualified. True, that array cannot be
written safely, but its type is non-`const' anyhow.
Use a writable array, like CBFalconer suggests, then call toupper() on the
array.

The argument to toupper() is an `int', not an array.
And there is no need for a writeable array anyhow:

char *line = "abcd";
while (*line != '\0')
putchar (toupper( (unsigned char)*line++ ));

(The `(unsigned char)' cast guards against the possibility
that negative-valued characters might appear in the string.
In this particular example all the characters have positive
values, but get in the habit of using the cast anyhow.)
 
M

Mark A. Odell

No mismatch. The literal creates an array of ordinary
`char', not `const'-qualified. True, that array cannot be
written safely, but its type is non-`const' anyhow.

You're rigth, sadly. What an awful choice. I still find bugs like this
where people assume a char * is writable (as one might expect) but where
the pointer points to a string literal. Wouldn't it have been better to
have string literals be of type const char *?
 
K

Keith Thompson

CBFalconer said:
Janice said:
char* line = "abcd";
How to convert the line to upper case and print?
Any option for printf to do this?

You can't and no. However if you had defined line as:

char line[] = "abcd";

you would have been able to convert it. Now you should spend some
time thinking about what the difference is. It is fundamental.

That depends on whether "convert" means to convert it in-place, or to
create a converted copy. The problem statement doesn't make this
clear.
 
E

Eric Sosman

Mark said:
You're rigth, sadly. What an awful choice. I still find bugs like this
where people assume a char * is writable (as one might expect) but where
the pointer points to a string literal. Wouldn't it have been better to
have string literals be of type const char *?

According to the Rationale, string literals have this
peculiar property to avoid breaking existing code:

[...] string literals do not have the type /array
of const char/ in order to avoid the problems of
pointer type checking, particularly with library
functions, since assigning a /pointer to const char/
to a plain /pointer to char/ is not valid. [...]

As an example of how `const' literals could break
perfectly good existing code, consider this pre-C89 program:

#include <stdio.h>

greet(whom)
char *whom;
{
printf ("Hello, %s!\n", whom);
}

int main() {
greet ("world");
return 0;
}

Note that greet() takes a plain `char*' argument, because
a pre-C89 coder had no way to write a `const' qualifier: the
keyword was added to the language (along with `void' and some
other "new stuff") by the ANSI committee. Now, what would
have happened if the committee had made string literals be
`const char[]'? The call to greet() in main() would have
become illegal, because you can't convert `const char*' to
plain `char*' without a cast.

Now multiply this trivial example by the twenty or so
years' worth of C code in existence before the new Standard
came along. If every string-accepting function in the entire
corpus of existing code had suddenly started refusing to accept
string literals as arguments, the new Standard might have had
some slight difficulty in gaining acceptance ...

Hindsight often tells us how things ought to have been
done differently, but it's not always possible to undo them.

The Clacking Keyboard writes: and having writ,
Clacks on: nor all thy Prototypes nor Wit
Shall rewind() it to fgets() half a Line,
Nor all thy Tears re-Const a Char of it.
 
C

CBFalconer

Mark A. Odell said:
You're rigth, sadly. What an awful choice. I still find bugs like
this where people assume a char * is writable (as one might expect)
but where the pointer points to a string literal. Wouldn't it have
been better to have string literals be of type const char *?

Yes, except that by the time 'const' was added to the language
(circa 1989) there were 15 or so years of previous practice that
needed 'not breaking'.

If you are using gcc you can get the effect with -Wwrite-strings.
 
P

pete

Keith said:
CBFalconer said:
Janice said:
char* line = "abcd";
How to convert the line to upper case and print?
Any option for printf to do this?

You can't and no. However if you had defined line as:

char line[] = "abcd";

you would have been able to convert it. Now you should spend some
time thinking about what the difference is. It is fundamental.

That depends on whether "convert" means to convert it in-place, or to
create a converted copy. The problem statement doesn't make this
clear.

It may mean to have the converted values
written to the standard output stream.

/* BEGIN new.c */

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

int main(void)
{
char *line = "abcd";

while(*line != '\0') {
putchar(toupper(*line));
++line;
}
putchar('\n');
return 0;
}

/* END new.c */
 
M

Mark L Pappin

Eric Sosman said:
Mark A. Odell wrote:

(Or even "array of const char".)
According to the Rationale, string literals have this peculiar
property to avoid breaking existing code

[snippage]

And this (almost useless, but certainly valid on a platform lacking
"const" ... like, say, that the Rationale uses to justify non-const
string literals) pre-C89 program is broken by that Standard:

main() {
char* const = "Hello, World!";
puts(const);
}

The "avoid breaking existing code" argument is trotted out all the
time in the Rationale, and it's bogus:

- If there is no existing standard, then defining anything that
conflicts with any existing usage anywhere will break existing code.
C89 broke existing code.

- If the new standard updates an old one, then defining anything other
than previously-undefined areas will break existing code.
C99 broke existing code.

C89 made sting literals non-const, and C99 didn't fix it, which
contributes to poor code now and in the future.

But don't blame "existing code" for it.
It's the fault of the Standard-setters alone.

<steps off soapbox>

mlp
 
L

Lawrence Kirby

Eric Sosman said:
Mark A. Odell wrote:

(Or even "array of const char".)
According to the Rationale, string literals have this peculiar
property to avoid breaking existing code

[snippage]

And this (almost useless, but certainly valid on a platform lacking
"const" ... like, say, that the Rationale uses to justify non-const
string literals) pre-C89 program is broken by that Standard:

main() {
char* const = "Hello, World!";
puts(const);
}

The "avoid breaking existing code" argument is trotted out all the
time in the Rationale, and it's bogus:

It may be bogus in some circumstances but it is certainly not inherently
bogus. Your example above is likely to affect a minority of programs, I
don't recall a massive outcry about this, which there would have been if
it broke a lot of code.

Also consider that it would be fairly trivial to fix this automatically
even for huge program sources: write a program that searches for the
word "const" in the context of an identifier and changes it to a valid
identifier that doesn't clash with others in the program.

The only difficulty would be if the identifier const was used in non-local
interface specifications e.g. in libraries.
- If there is no existing standard, then defining anything that
conflicts with any existing usage anywhere will break existing code.
C89 broke existing code.

Yes, but there's a matter of degree. Something that affects odd bits of
code here and there is not the same problem as something that affects
nearly the whole body of existing code. The fact is that code such as

char *str = "string";

was the normal, correct, mainstream way of doing things pre-C89.

Although there was no standards body ratified standard before C89, there
was still K&R 1 which provided an effective baseline for all C compiler
writers.
- If the new standard updates an old one, then defining anything other
than previously-undefined areas will break existing code.
C99 broke existing code.

C89 made sting literals non-const, and C99 didn't fix it, which
contributes to poor code now and in the future.

But don't blame "existing code" for it.
It's the fault of the Standard-setters alone.

There is no way that the standard committee could have made this change,
it breaks too much. C is if anything a pragmatic language, and one of its
big assets is the amount of C code that is already out there.

Lawrence
 
E

Eric Sosman

Mark said:
Eric Sosman said:
Mark A. Odell wrote:


(Or even "array of const char".)

According to the Rationale, string literals have this peculiar
property to avoid breaking existing code

[snippage]

And this (almost useless, but certainly valid on a platform lacking
"const" ... like, say, that the Rationale uses to justify non-const
string literals) pre-C89 program is broken by that Standard:

main() {
char* const = "Hello, World!";
puts(const);
}

Does this mean you think the ANSI committee should not
have invented the `const' keyword at all?

Or does this mean you can't distinguish between "some
small amount of breakage" and "massive, overwhelming, universal
bloodbath?"

Rummage through any corpus of pre-Standard C -- early Unix
distributions, for example -- and count the number of uses of
`const' as an identifier. Then count the number of times a
string literal is passed to a function expecting a `char*'.
The "avoid breaking existing code" argument is trotted out all the
time in the Rationale, and it's bogus:

- If there is no existing standard, then defining anything that
conflicts with any existing usage anywhere will break existing code.
C89 broke existing code.

Some amount of breakage was inevitable, since pre-Standard
C implementations disagreed on the meaning attached to the
same constructions. What value should sprintf() return? Some
pre-C89 implementations returned a count, others returned a
pointer. On a 32-bit system, what should be the value and
type of 0x80000000? Some implementations produced a negative
`int', others an `unsigned int'. Should `far' be a keyword?
- If the new standard updates an old one, then defining anything other
than previously-undefined areas will break existing code.
C99 broke existing code.

It is conceivable that C99 broke existing code. Anybody
who used `restrict' as an identifier is in for some effort.
Anybody who expected `//*' to mean "slash, followed by start
of comment" will be unpleasantly surprised. And so on.

Question: How many instances of these and other breakages
have you personally encountered (excluding uses specifically
contrived after the fact to illustrate the change)? Have you
actually encountered even one such instance of breakage?
C89 made sting literals non-const, and C99 didn't fix it, which
contributes to poor code now and in the future.

But don't blame "existing code" for it.
It's the fault of the Standard-setters alone.

"There is nothing more difficult to take in hand,
more perilous to conduct, or more uncertain in its
success than to take the lead in the introduction
of a new order of things."
-- Niccolò Macchiavelli, 1513

"So down with them! So down with them!
Reform's a hated ogress!
So down with them! So down with them!
Down with the Flowers of Progress!"
-- W.S. Gilbert, 1893
 
R

Richard Bos

Eric Sosman said:
Hindsight often tells us how things ought to have been
done differently, but it's not always possible to undo them.

The Clacking Keyboard writes: and having writ,
Clacks on: nor all thy Prototypes nor Wit
Shall rewind() it to fgets() half a Line,
Nor all thy Tears re-Const a Char of it.

*Applause*

Richard
 
R

Richard Bos

Eric Sosman said:
It is conceivable that C99 broke existing code. Anybody
who used `restrict' as an identifier is in for some effort.

*cough* inline. Worst trivial change in the C99 Standard, easily.
There's no good reason for it to be included at all (Geez, it was 1999 -
get an optimising compiler already!), and it meant that I had to change
a habit I'd used in all my textfile-reading programs. Input/output files
were called infile/outfile; filenames usually inname/outname; and line
buffers (you guessed it) inline/outline. Ow.

Richard
 

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,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top