length of strings in a two dimensional array

D

dr.oktopus

Hello,
here I am talking about having good habits in code writing.
I have a simple problem: have two messages that represent
the same string, one in lowercase and the other in uppercase
letter. Under some circustamces, I want to print the first or
the second, so I couple them inside an array and use a
variable "allcaps" as index.
And I have to precompute the length of the strings, that are CONSTANT
strings.

A solution is:

const char *messages[2] = { "this is lowercase string", "this is
uppercase string" };

and

#define MESSAGE_LEN (strlen(messages[0])

But what if you prefer, as good habits could suggest, to rewrite
all using only arrays and the sizeof operator?

const char message_lo[] = "this is lowercase";
const char message_up[] = "this is uppercase";

#define MESSAGE_LEN (sizeof(message_lo) - 1)

const char messages[2][MESSAGE_LEN] = { &message_lo, &message_hi };

What is better? (I think the answer is: "none")
Thanks,
willy
 
M

Morris Keesan

Hello,
here I am talking about having good habits in code writing.
I have a simple problem: have two messages that represent
the same string, one in lowercase and the other in uppercase
letter. Under some circustamces, I want to print the first or
the second, so I couple them inside an array and use a
variable "allcaps" as index.
And I have to precompute the length of the strings, that are CONSTANT
strings.

A solution is:

const char *messages[2] = { "this is lowercase string", "this is
uppercase string" };

and

#define MESSAGE_LEN (strlen(messages[0])

Besides the missing close parenthesis: defining MESSAGE_LEN this way,
you're not precomputing the length of the strings. Every time you write
MESSAGE_LEN in your code, this will result in a call to strlen().
But what if you prefer, as good habits could suggest, to rewrite
all using only arrays and the sizeof operator?

const char message_lo[] = "this is lowercase";
const char message_up[] = "this is uppercase";

#define MESSAGE_LEN (sizeof(message_lo) - 1)

const char messages[2][MESSAGE_LEN] = { &message_lo, &message_hi };

What is better? (I think the answer is: "none")

I prefer the second approach, because then MESSAGE_LEN really is a
constant, and you compute it at compile time rather than while the
program is running. If it were me, I would also put in somewhere
a line that says
assert(sizeof message_lo == sizeof message_up);


[Note how, in answering your message, I've included all of the context
that a reader of my message needs in order to understand what I'm saying,
rather than assuming that said reader is using Google groups and has easy
access to your message.]
 
B

Barry Schwarz

Hello,
here I am talking about having good habits in code writing.
I have a simple problem: have two messages that represent
the same string, one in lowercase and the other in uppercase
letter. Under some circustamces, I want to print the first or
the second, so I couple them inside an array and use a
variable "allcaps" as index.
And I have to precompute the length of the strings, that are CONSTANT
strings.

A solution is:

const char *messages[2] = { "this is lowercase string", "this is
uppercase string" };

and

#define MESSAGE_LEN (strlen(messages[0])

But what if you prefer, as good habits could suggest, to rewrite
all using only arrays and the sizeof operator?

const char message_lo[] = "this is lowercase";
const char message_up[] = "this is uppercase";

#define MESSAGE_LEN (sizeof(message_lo) - 1)

const char messages[2][MESSAGE_LEN] = { &message_lo, &message_hi };

Of course this is illegal since no part of messages contains any
address. Did you perhaps mean to use #define instead of const char?

And if you do, you probably need to remove the -1 from the computation
of MESSAGE_LEN. Your stated goal is to have strings and they need the
terminating '\0'.
 
D

dr.oktopus

const char messages[2][MESSAGE_LEN] = { &message_lo, &message_hi };

Of course this is illegal since no part of messages contains any
address.  Did you perhaps mean to use #define instead of const char?  

Using something like:

#define message_lo "this is lowercase"
#define message_hi "this is uppercase"

prevents me to use the sizeof operator, so we return at the start
point.
And if you do, you probably need to remove the -1 from the computation
of MESSAGE_LEN.  Your stated goal is to have strings and they need the
terminating '\0'.

No, really I don't need it. I use strings but output is not done via
printf or similar.
 
J

James Kuyper

const char messages[2][MESSAGE_LEN] = { &message_lo, &message_hi };

Of course this is illegal since no part of messages contains any
address. �Did you perhaps mean to use #define instead of const char? �

Pay attention to the fact that this code is a constraint violation. It
doesn't matter what problems you might have with the alternative
approaches - this approach can not work, so you must choose one of the
alternatives.
Using something like:

#define message_lo "this is lowercase"
#define message_hi "this is uppercase"

prevents me to use the sizeof operator, so we return at the start
point.

With the above #defines, nothing prevents you from using the expression
"sizeof message_lo"; the expression is an integer constant expression
which may be used for, among other things, the following uses:

#define MESSAGE_LEN (sizeof message_lo - 1)
const char messages[2][MESSAGE_LEN] =
{message_lo, message_high};

Note, among other things, the absense of the '&' operator from this
re-write.
 
I

Ian Collins

const char messages[2][MESSAGE_LEN] = {&message_lo,&message_hi };

Of course this is illegal since no part of messages contains any
address. �Did you perhaps mean to use #define instead of const char? �

Pay attention to the fact that this code is a constraint violation. It
doesn't matter what problems you might have with the alternative
approaches - this approach can not work, so you must choose one of the
alternatives.
Using something like:

#define message_lo "this is lowercase"
#define message_hi "this is uppercase"

prevents me to use the sizeof operator, so we return at the start
point.

With the above #defines, nothing prevents you from using the expression
"sizeof message_lo"; the expression is an integer constant expression
which may be used for, among other things, the following uses:

#define MESSAGE_LEN (sizeof message_lo - 1)

Did you intend to loose the trailing '\0'?
 
J

James Kuyper

Did you intend to loose the trailing '\0'?

Yes, since dr. oktopus has explicitly stated that he wants to lose the
trailing '\0'. He's working with fixed-length strings, rather than
null-terminated strings (NTS). That is a legitimate choice, though not a
convenient one in C. It means he can't use any of the NTS utilities in
the C standard library.
 
E

Eric Sosman

Hello,
here I am talking about having good habits in code writing.
I have a simple problem: have two messages that represent
the same string, one in lowercase and the other in uppercase
letter. Under some circustamces, I want to print the first or
the second, so I couple them inside an array and use a
variable "allcaps" as index.
And I have to precompute the length of the strings, that are CONSTANT
strings.

A solution is:

const char *messages[2] = { "this is lowercase string", "this is
uppercase string" };

Ah. This is obviously some strange usage of the word "uppercase"
that I hadn't previously been aware of.
and

#define MESSAGE_LEN (strlen(messages[0])

Missing a parenthesis, and not a "CONSTANT" in any event.
But what if you prefer, as good habits could suggest, to rewrite
all using only arrays and the sizeof operator?

const char message_lo[] = "this is lowercase";
const char message_up[] = "this is uppercase";

#define MESSAGE_LEN (sizeof(message_lo) - 1)

const char messages[2][MESSAGE_LEN] = {&message_lo,&message_hi };

What is better? (I think the answer is: "none")

Neither is much good, and the second won't even compile.

It's not clear why you're so worried about CONSTANTs or about
having the strings in an array, but one possibility is

#define LOWER "this is lowercase string"
#define UPPER "THIS IS CAPITALIZED STRING"
#define MESSAGE_LEN (sizeof LOWER > sizeof UPPER \
? sizeof LOWER : sizeof UPPER)
const char messages[][MESSAGE_LEN] = { LOWER, UPPER };

I don't know whether you'll find this useful, because I don't
really understand why you've adopted all these strictures, nor
what others may lurk unposted.
 
M

Mel Smith

Hi:

I'm Mr. Butinsky here but since my language (xHarbour) is really a
slightly higher level of C, here is the xHarbour solution:

Function PrintUpperLower(nIndex)

// Here we make a 'static' array which is created at compile time
// and is only created once

STATIC aMessages := {"this is a lowercase string","THIS IS AN
UPPERCASE STRING"}

// now do your printing however you can, e.g.:
? aMessages[nIndex] // and the printing happens at the bnext
place on the screen

// or
@ 12,10 SAY aMessages[nIndex] // to print on line 12, column 10
of the screen

// or use a hardcopy printing routine available to you


RETURN NIL


-Mel Smith
 
D

dr.oktopus

Hello,
here I am talking about having good habits in code writing.
I have a simple problem: have two messages that represent
the same string, one in lowercase and the other in uppercase
letter. Under some circustamces, I want to print the first or
the second, so I couple them inside an array and use a
variable "allcaps" as index.
And I have to precompute the length of the strings, that are CONSTANT
strings.
A solution is:
const char *messages[2] = { "this is lowercase string", "this is
uppercase string" };

     Ah. This is obviously some strange usage of the word "uppercase"
that I hadn't previously been aware of.

a better example:

#define message_lo "the quick brown fox jumps over the lazy dog"
#define message_hi "THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG"

the point is that the strings have the same length
 
D

dr.oktopus

With the above #defines, nothing prevents you from using the expression
"sizeof message_lo";

Is guaranteed that C will not apply that sizeof as if it would be
a sizeof(char *)?
 
B

Ben Pfaff

dr.oktopus said:
Is guaranteed that C will not apply that sizeof as if it would be
a sizeof(char *)?

It's guaranteed. A literal string has type "(unmodifiable) array
of char". It is only converted to a pointer in the usual
contexts where arrays are converted to pointers.
 
P

Peter Nilsson

What circumstances?
Why?
that are CONSTANT strings.

A solution is:

const char *messages[2] = { "this is lowercase string",
"this is uppercase string" };

Ah. This is obviously some strange usage of the
word "uppercase" that I hadn't previously been aware of.

a better example:

#define message_lo "the quick brown fox jumps over the lazy dog"
#define message_hi "THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG"

the point is that the strings have the same length

You failed address Eric's other queries. The ones everyone else
has too. To summarise, you appear to have a problem X. You think
Y and Z are possible solutions. So you ask about Y and Z, and if
there are better ones, but fail to elaborate on what problem X
really is.

Given your limited spec, I can't see why you don't just do...

printf("%s", allcaps
? "the quick brown fox jumps over the lazy dog"
: "THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG");

If you want to centralise strings in one source, fine, but the
solution is still rather trivial and incidental. It's not worth
spending a week pondering aesthetics. What matters more is that
your code is consistent across the whole project.
 
J

James Kuyper

Is guaranteed that C will not apply that sizeof as if it would be
a sizeof(char *)?

Yes. A string literal in your source code is an expression with the type
"array of char". In most contexts, a expression with an array type is
automatically converted into a pointer to the first member of that
array, but there are three exceptions:

1. When the array is the operand of the sizeof operator.
2. When the array is the right operand of the unary '&' operator.
3. When the array is a string literal, used as an initializer for an array.
 
E

Eric Sosman

Hello,
here I am talking about having good habits in code writing.
I have a simple problem: have two messages that represent
the same string, one in lowercase and the other in uppercase
letter. Under some circustamces, I want to print the first or
the second, so I couple them inside an array and use a
variable "allcaps" as index.
And I have to precompute the length of the strings, that are CONSTANT
strings.
A solution is:
const char *messages[2] = { "this is lowercase string", "this is
uppercase string" };

Ah. This is obviously some strange usage of the word "uppercase"
that I hadn't previously been aware of.

a better example:

#define message_lo "the quick brown fox jumps over the lazy dog"
#define message_hi "THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG"

the point is that the strings have the same length

.... in which case the `?:' expression I wrote will still give the
correct answer. The point is that if you want the strings themselves
in an array, both array elements must have the same *known* length.
That is, you can't do

const char messages[2][] = { "hello", "HELLO" };

but must instead do

const char messages[2][LENGTH] = ...
or
const char messages[][LENGTH] = ...

where LENGTH is an integer constant expression.
 
D

dr.oktopus

Given your limited spec, I can't see why you don't just do...

  printf("%s", allcaps
                 ? "the quick brown fox jumps over the lazy dog"
                 : "THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG");

Because I can't. Strings are involved in a series of write() system
calls.
 
E

Eric Sosman

Ah. This is obviously some strange and unusual usage of the
identifier `allcaps' that I hadn't previously been aware of.
Because I can't. Strings are involved in a series of write() system
calls.

write(fd,
allcaps ? "THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG"
: "the quick brown fox jumps over the lazy dog",
sizeof "The mixed-case Fox jumped over the lazy Dog" - 1);
 

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,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top