length of the array of pointers, using strlen in C

Hello.. How do I find the length of this array of pointers?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
  char *gCreditsEn[] =
{
	"Title",
	"Game created by:",
	"Game Design:",
	"Music by:",
	"Sounds by:",
	"Game engine:",
	"Game Testers:",
	"",
	"",
	"",
	"Thank you for playing..."
};


if I do:

 
strlen(*gCreditsEn) - 1;


I get 8, even if I add 300 blank lines after the string "Game Testers:".

I think the right question is how do I calculate the length including even the new lines "" ?

And how do I calculate it at the run time in a loop like this:

1
2
3
4
5
for (unsigned int j = gStartLine, k = 0; j < strlen(*gCreditsEn) - 1; j++, k += distBetweenLines)
    {
         ....
          .....
    }
Last edited on
EDIT:

without create a macro:

1
2
3
4
5
6
7
8
#define LINES   11

for (unsigned int j = gStartLine, k = 0; j < LINES; j++, k += distBetweenLines)
    {
         ....
          .....
    }
Last edited on
note: this is a self inflicted problem. Simply putting the length in the array solves it.

#define usefullynamednumber 5
char* foo[usefullynamednumber] = ... etc

and now, forever, you know its length. If you add or remove frome it, change the value. A little more work for the programmer up front, but a lot less weirdness every time you use the thing. A little nicer, you can use an enum to name each index:

enum eforfoo {title, name, date, whatever, efmax};
char* foo[efmax]= {...}; //this auto increments, just add entries to the enum before the last one that gives its size and recompile.
....
printf(.. ,foo[title] ..);
Last edited on
Thank you jonnin I tried even this .. and I know it works, but I don't want to everytime I add a new line to change the MACRO number, I just want it to change using the strlen function, but this "" return <-- nothing from nothing isn't it?

So i need to build something that tells the strlen function when I have the empty quotation to count it as 1 string. Otherwise is simply enough to do this

1
2
3
4
5
6
7
8
#define LINES 3

char gCreditsEn[LINES][MAX_PATH] =
{
	"Title",
	"",
	"Thank you for playing..."
};


and then the "" will count as well.
Last edited on
and now the loop is simply than the first time

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
for (unsigned int j = gStartLine, k = 0; j < LINES; j++, k += distBetweenLines)
    {
if (i >= endPoint)
        {
            if (i <= startPoint - k)
            {
                if (gChangeLang == 0)
                {
                    BlitStringToBuffer(gCreditsEn[j], &g6x7Font, &TextColor, H_CENTER_SCREEN - ((uint16_t)(strlen(gCreditsEn[j]) * 6) / 2), (uint16_t)(i + k), 0);
                }
                else
                {
                    BlitStringToBuffer(gCreditsRo[j], &g6x7Font, &TextColor, H_CENTER_SCREEN - ((uint16_t)(strlen(gCreditsRo[j]) * 6) / 2), (uint16_t)(i + k), 0);
                }
            }
            else break;
        }
    }
I don't understand. How could strlen(*gCreditsEn) - 1 == 8?

strlen(*gCreditsEn) - 1
strlen("Title") - 1
5 - 1
4

It obviously tells you nothing of the length of the array of pointers.

Just use C++ types.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
const std::vector<std::string> gCreditsEn =
{
	"Title",
	"Game created by:",
	"Game Design:",
	"Music by:",
	"Sounds by:",
	"Game engine:",
	"Game Testers:",
	"",
	"",
	"",
	"Thank you for playing..."
};
Last edited on
but I don't want to use this in the code:

 
#define LINES 3 



Is there another way to do it ???

is the _countof() MACRO counts even the empty "" ?
if I do:

strlen(*gCreditsEn) - 1;

I get 8,
This makes no sense. *gCreditsEn means gCreditsEn[0]. gCreditsEn[0]'s string length is 5 (6 if you include the null pointer). Show a minimal example that reproduces your issue.

Also, that's not standard C++. String literal pointers need to be const. (Edit: I suppose you're writing in C? Still, you should use const.)
Last edited on
First off, you're going to get warnings for trying to assign const char *s to an array of char *. Change line 1 to const char *.

Your best bet is to use a std::vector. A vector will keep track of the number of lines automatically.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <vector>
#include <iostream>
std::vector<const char*> gCreditsEn =
{
	"Title",
	"Game created by:",
	"Game Design:",
	"Music by:",
	"Sounds by:",
	"Game engine:",
	"Game Testers:",
	"",
	"",
	"",
	"Thank you for playing..."
};

int main()
{
	std::cout << "Number of lines = " << gCreditsEn.size();
        for (size_t i = 0; i<gCreditsEn.size(); i++)
		std::cout << gCreditsEn[i] << std::endl;
}

Last edited on
I mean the number of the strings not the "Title" name

1
2
3
4
5
6
7
8
9
10
11
12
13
14
char *gCreditsEn[] =
{
	"Title", //0
	"Game created by:", //1
	"Game Design:", //2
	"Music by:", //3
	"Sounds by:", //4
	"Game engine:", //5
	"Game Testers:", //6
	"", //7
	"", //8
	"", //9
	"Thank you for playing..." //10
};


without the 7, 8, 9 there are 8 lines in the array of the pointers..
But yea.. maybe I am wrong to calculate how many strings are with strlen.
Now I realized I did a mistake.

Well then the question is how do I know at run time how many strings are in the array of the pointers without using a MACRO and write it at Compile time ??
Yeah.. I know maybe is simply with C++ types but I only use C.. the title of the question was how to do that in C not C++
Macros are the crutch that C uses to get by due to it being a duct-taped-together language used to avoid writing directly in assembly.

The following does not use a macro.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <stdio.h>
#include <string.h>

const char *gCreditsEn[] =
{
	"Title", //0
	"Game created by:", //1
	"Game Design:", //2
	"Music by:", //3
	"Sounds by:", //4
	"Game engine:", //5
	"Game Testers:", //6
	"", //7
	"", //8
	"", //9
	"Thank you for playing..." //10
};

int main(void)
{
    int num_lines = sizeof(gCreditsEn) / sizeof(char*);
    
    for (int i = 0; i < num_lines ; i++)
    {
        if (strlen(gCreditsEn[i]) > 0)
        {
            printf("%s\n", gCreditsEn[i]);
        }
        else
        {
            printf("[empty]\n");
        }
    }
    return 0;
}


I'd put "[C] rest of title" or "C - rest of title" as your title so that people immediately read the "C" part first. That way you'll get less people suggesting you to use vector<string> and such.
Last edited on
Okay that's what I was looking for. Thanks Ganado.
That doesn't mean the other guys don't know the answer, is just me being NOT very explicitly in what I want to obtain , and this sizeof(gCreditsEn) / sizeof(char*); I wrote it soo many times in other code, I don't know what's in my had trying to find the elements of the array of pointers using strlen. Dohh, maybe I need to take a brake sometims :D

Thank you all...
The strlen() function gives you the size of the string.

If you want to know how many strings are in your array you will need to use sizeof, something like:

printf("%zu\n", sizeof(gCreditsEn) / sizeof(gCreditsEn[0]));

Yeah... after Ganado waked me up a bit.. I realized I did a mistake with strlen that tells you the length of a string.
Many thanks..
You don't need to use possibly expensive strlen() to see if a string is empty or not. If you have the pointer to the string then just test the dereferenced pointer for not 0 if the string is not empty. Consider:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <stdio.h>
#include <string.h>

const char* gCreditsEn[] =
{
    "Title", //0
    "Game created by:", //1
    "Game Design:", //2
    "Music by:", //3
    "Sounds by:", //4
    "Game engine:", //5
    "Game Testers:", //6
    "", //7
    "", //8
    "", //9
    "Thank you for playing..." //10
};

int main(void) {
    const int num_lines = sizeof(gCreditsEn) / sizeof(char*);

    for (int i = 0; i < num_lines; ++i)
        printf("%s\n", *gCreditsEn[i] ? gCreditsEn[i] : "[empty]");
}


which displays:


Title
Game created by:
Game Design:
Music by:
Sounds by:
Game engine:
Game Testers:
[empty]
[empty]
[empty]
Thank you for playing...

Sure, but strlen expresses intent better.
Topic archived. No new replies allowed.