length of the array of pointers, using strlen in C

Jan 28, 2023 at 3:27pm
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 Jan 28, 2023 at 3:33pm
Jan 28, 2023 at 3:31pm
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 Jan 28, 2023 at 3:32pm
Jan 28, 2023 at 3:44pm
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 Jan 28, 2023 at 3:45pm
Jan 28, 2023 at 3:57pm
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 Jan 28, 2023 at 4:02pm
Jan 28, 2023 at 4:05pm
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;
        }
    }
Jan 28, 2023 at 4:07pm
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 Jan 28, 2023 at 4:08pm
Jan 28, 2023 at 4:08pm
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 "" ?
Jan 28, 2023 at 4:13pm
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 Jan 28, 2023 at 4:16pm
Jan 28, 2023 at 4:15pm
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 Jan 28, 2023 at 4:20pm
Jan 28, 2023 at 4:16pm
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 ??
Jan 28, 2023 at 4:18pm
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++
Jan 28, 2023 at 4:21pm
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 Jan 28, 2023 at 4:26pm
Jan 28, 2023 at 4:29pm
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...
Jan 28, 2023 at 4:33pm
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]));

Jan 28, 2023 at 4:37pm
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..
Jan 28, 2023 at 5:05pm
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...

Jan 28, 2023 at 5:23pm
Sure, but strlen expresses intent better.
Topic archived. No new replies allowed.