Counting number of strings literals in double dimentional char array

R

ranjmis

Hi all,

Below is the code wherein I am initializing double dimentional array
inside main with string literals.
Now I want to display the strings using a function call to which I just
want to pass the array as argument with no other info like number of
strings.

Is there a way to achieve that?

Right now I have applied a workaround where I keep my last literal as
"" which acts as my end of literals.

--------------------------

#include<stdio.h>
#define NUM 20

void display(char input[][NUM])
{
char (*pc)[NUM];
int i=0;

pc=input;
for(i=0;strcmp(*pc,"")!=0;i++,pc++){
printf("%s\n",*pc);
}

}
int main()
{

char input[][NUM] = {"hi","from","ranjeet",""};

display(input);
}

----------------------
 
N

Nelu

ranjmis said:
Hi all,

Below is the code wherein I am initializing double dimentional array
inside main with string literals.
Now I want to display the strings using a function call to which I just
want to pass the array as argument with no other info like number of
strings.

Is there a way to achieve that?

Right now I have applied a workaround where I keep my last literal as
"" which acts as my end of literals.
<snip>

It's impossible to know the length of your array unless you specify the
length to the function or mark it in a certain way.
I'm not sure that this is valid everywhere but you can declare main
like this:
int main(int argc, char *argv[], char **env)
where env is an array of string that lists every environment variable.
There is no counter that tells you how many elements there are (like
argc for argv) but it's dimension is one larger than the number of
variables and the last one is set to NULL. You can go through the lines
one by one until you hit NULL.
 
W

Walter Roberson

Nelu said:
I'm not sure that this is valid everywhere but you can declare main
like this:
int main(int argc, char *argv[], char **env)
where env is an array of string that lists every environment variable.

That is not part of the C standard, but may be offered as an
extension by an implementation.

[It doesn't seem relevant to the user's question, though, since
the user already discussed adding a sentinal.]
 
N

Nelu

Walter said:
Nelu said:
I'm not sure that this is valid everywhere but you can declare main
like this:
int main(int argc, char *argv[], char **env)
where env is an array of string that lists every environment variable.

That is not part of the C standard, but may be offered as an
extension by an implementation.

[It doesn't seem relevant to the user's question, though, since
the user already discussed adding a sentinal.]

I just told him the options. I also think that using NULL is better
than using a zero length string.
 
J

Joe Estock

ranjmis said:
Hi all,

Below is the code wherein I am initializing double dimentional array
inside main with string literals.
Now I want to display the strings using a function call to which I just
want to pass the array as argument with no other info like number of
strings.

Is there a way to achieve that?

Right now I have applied a workaround where I keep my last literal as
"" which acts as my end of literals.

You really don't need this in your example below with my revisions.
void display(char input[][NUM])

Change the parameter of this function to a pointer to pointer of type char.
{
char (*pc)[NUM];
int i=0;

pc=input;
for(i=0;strcmp(*pc,"")!=0;i++,pc++){
printf("%s\n",*pc);
}

}

You will want to get rid of the above and replace it with the following:

void display(char **input)
{
size_t i;

for(i = 0; input != NULL; i++)
printf("%s\n", input);
}

int main()

main either accepts two arguments or no arguments. Since you aren't
using argc and argv you need to add void in place of them.
{

char input[][NUM] = {"hi","from","ranjeet",""};

Using an empty (zero length) string is going to throw all kinds of
problems into the mix if you aren't careful. The better way to declare
and initialize the above would be:

char *input[] = { "hi", "from", "ranjeet", NULL };

Using the above instead, we now know where the end of our array is
located. This makes looping through the array much easier.
display(input);

You declared main as returning an int (which is correct), however you
are not returning a value. Might want to add return(0); here.

Now that I've told you what changes to make, I'll tell you why. The
first change you will notice is that I declared display() as accepting
one parameter of type pointer to pointer of type char (char **). This is
an array of pointers to type char *. The reason for this change should
be obvious.

The next change will be declaring i as type size_t (you could replace
that with unsigned int if you wish, either way would work). Basically
you want an unsigned datatype here since you won't be accessing a
negative element of the array (e.g., input[-1] is invalid). Personal
preference I suppose.

Now this brings us to using NULL as the terminator for the array. Almost
every type of program which uses arrays like you are attempting to do
will use NULL as the terminator. This is easier to check for and much
faster than strcmp() and friends. NULL is also the safest bet to use as
a terminator since it is part of the C standard and thusly will always
be available.

Hope that clears things up for you,

Joe
 
K

Keith Thompson

Nelu said:
Walter said:
Nelu said:
I'm not sure that this is valid everywhere but you can declare main
like this:
int main(int argc, char *argv[], char **env)
where env is an array of string that lists every environment variable.

That is not part of the C standard, but may be offered as an
extension by an implementation.

[It doesn't seem relevant to the user's question, though, since
the user already discussed adding a sentinal.]

I just told him the options. I also think that using NULL is better
than using a zero length string.

Agreed. But note that an empty string "" is not a zero length array.
Its length *as an array* is 1 (because of the trailing '\0'), even
though strlen("")==0.
 
K

Keith Thompson

Joe Estock said:
Now that I've told you what changes to make, I'll tell you why. The
first change you will notice is that I declared display() as accepting
one parameter of type pointer to pointer of type char (char **). This
is an array of pointers to type char *. The reason for this change
should be obvious.
[...]

No, a char** is a pointer-to-pointer-to-char, *not* an array of any
kind. It can be used to point to the first element of an array of
pointers-to-char.

Arrays are not pointers. Pointers are not arrays.

See <http://www.c-faq.com/>, section 6, "Arrays and Pointers".
 
N

Nelu

Keith said:
Nelu said:
Walter said:
I'm not sure that this is valid everywhere but you can declare main
like this:
int main(int argc, char *argv[], char **env)
where env is an array of string that lists every environment variable.

That is not part of the C standard, but may be offered as an
extension by an implementation.

[It doesn't seem relevant to the user's question, though, since
the user already discussed adding a sentinal.]

I just told him the options. I also think that using NULL is better
than using a zero length string.

Agreed. But note that an empty string "" is not a zero length array.
Its length *as an array* is 1 (because of the trailing '\0'), even
though strlen("")==0.

Yes, zero length string and zero length array are two different things.
I've seen people making mistakes similar to this and even worse, people
treating NULL like a '\0' string.
 
J

Joe Estock

Keith said:
Now that I've told you what changes to make, I'll tell you why. The
first change you will notice is that I declared display() as accepting
one parameter of type pointer to pointer of type char (char **). This
is an array of pointers to type char *. The reason for this change
should be obvious.

[...]

No, a char** is a pointer-to-pointer-to-char, *not* an array of any
kind. It can be used to point to the first element of an array of
pointers-to-char.

Arrays are not pointers. Pointers are not arrays.

See <http://www.c-faq.com/>, section 6, "Arrays and Pointers".

Whoops, thanks for catching my mistake Keith. I was more focused on the
changes to the OP's source code than I was with what I was typing :)

Joe
 
K

Keith Thompson

pete said:
A string has "length".
An array has "size".

Perhaps, but the standard's terminology isn't consistent enough that
we can make much use of this. Consider variable *length* arrays.
Consider also that "size" often refers to the result of the sizeof
operator, not to the number of elements in an array.
 
R

ranjmis

Thanks Joe.
I was really looking for something better.
The solution is really clean and seems to be faster
 
C

CBFalconer

Nelu said:
ranjmis said:
Below is the code wherein I am initializing double dimentional
array inside main with string literals. Now I want to display
the strings using a function call to which I just want to pass
the array as argument with no other info like number of strings.

Is there a way to achieve that?

Right now I have applied a workaround where I keep my last
literal as "" which acts as my end of literals.
<snip>

It's impossible to know the length of your array unless you
specify the length to the function or mark it in a certain way.
I'm not sure that this is valid everywhere but you can declare
main like this:

int main(int argc, char *argv[], char **env)

where env is an array of string that lists every environment
variable. There is no counter that tells you how many elements
there are (like argc for argv) but it's dimension is one larger
than the number of variables and the last one is set to NULL.
You can go through the lines one by one until you hit NULL.

This is non-standard. The only approved method of interogating
environmental variables is with the getenv function, defined below
in N869:

7.20.4.5 The getenv function

Synopsis

[#1]
#include <stdlib.h>
char *getenv(const char *name);

Description

[#2] The getenv function searches an environment list,
provided by the host environment, for a string that matches
the string pointed to by name. The set of environment names
and the method for altering the environment list are
implementation-defined.

[#3] The implementation shall behave as if no library
function calls the getenv function.

Returns

[#4] The getenv function returns a pointer to a string
associated with the matched list member. The string pointed
to shall not be modified by the program, but may be
overwritten by a subsequent call to the getenv function. If
the specified name cannot be found, a null pointer is
returned.

which won't give you a count of environmental variables, whatever
they may be.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell.org/google/>
Also see <http://www.safalra.com/special/googlegroupsreply/>
 
B

Barry Schwarz

Hi all,

Below is the code wherein I am initializing double dimentional array
inside main with string literals.
Now I want to display the strings using a function call to which I just
want to pass the array as argument with no other info like number of
strings.

If you don't want to pass the number of strings, you could store it in
a global variable where the called function could find. The called
function cannot calculate the number of strings because it actually
receives a pointer. If the number of strings is not available
somewhere, then a sentinel value (like "") is a common solution.
Is there a way to achieve that?

Right now I have applied a workaround where I keep my last literal as
"" which acts as my end of literals.

--------------------------

#include<stdio.h>
#define NUM 20

void display(char input[][NUM])
{
char (*pc)[NUM];
int i=0;

pc=input;
for(i=0;strcmp(*pc,"")!=0;i++,pc++){
printf("%s\n",*pc);
}

}
int main()
{

char input[][NUM] = {"hi","from","ranjeet",""};

display(input);
}

----------------------


Remove del for email
 
B

Ben C

Right now I have applied a workaround where I keep my last literal as
Your "workaround" is a good idea and actually quite a common way of
doing this kind of thing. It's a similar idea to null-terminated
strings.

You can save having to bother with a 2D array if you use an array of
pointers:

const char *input[] = {"hi", "from", "ranjeet", NULL};

This way you might as well terminate the list with a null pointer rather
than with an empty string.

Then you can write your display function something like this:

void display(const char *input[])
{
const char **s;

assert(input);

for (s = input; *s; s++)
printf("%s\n", *s);
}
 

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,904
Latest member
HealthyVisionsCBDPrice

Latest Threads

Top