1

Please someone who knows c for 100 years to explain to me what am I looking at here. Am I taking the right route to learning c as a career? WOW what is this I really would like to know what is going on here

#include <stdio.h>
#include <string.h>

int main() {

char *checkArr[1000] = {"This is very good", 
                        "text that has been",
                        "put into a file for", 
                        "the purposes of", 
                        "being an example.", NULL};
int size2 = strlen(checkArr);
printf("Check Array size: %d\n", size2);

for (int i =0; i < strlen(checkArr); i++){
    printf("%s\n", checkArr[i]);
}

char *checkArr2[1000] = {"This is very good", 
                        "text that has been",
                        "put into a file for", 
                        NULL, 
                        NULL, NULL};
int size3 = strlen(checkArr2);
printf("Check Array size: %d\n", size3);

for (int i =0; i < strlen(checkArr2); i++){
    printf("%s\n", checkArr2[i]);
}

for (int i =0; i < strlen(checkArr2); i++){
    printf("%s\n", checkArr2[i]);
}

char *checkArr3[1000] = {"This is very good", 
                        "text that has been",};
int size4 = strlen(checkArr3);
printf("Check Array size: %d\n", size4);

for (int i =0; i < strlen(checkArr3); i++){
    printf("%s\n", checkArr3[i]);
}

char *checkArr4[1000] = {"This is very good", 
                        "text that has been",
                        NULL, 
                        NULL, 
                        NULL, NULL};
int size5 = strlen(checkArr4);
printf("Check Array size: %d\n", size5);

for (int i =0; i < strlen(checkArr4); i++){
    printf("%s\n", checkArr4[i]);
}

    return 0;
}

Explain this below please, stdout

Check Array size: 5
This is very good
text that has been
put into a file for
the purposes of
being an example.
Check Array size: 5
This is very good
text that has been
put into a file for
(null)
(null)
This is very good
text that has been
put into a file for
(null)
(null)
Check Array size: 5
This is very good
text that has been
(null)
(null)
(null)
Check Array size: 5
This is very good
text that has been
(null)
(null)
(null)

How is this possible. How can all these arrays have the same size length???

20
  • 1
    Your code does not compile. Commented Mar 14, 2021 at 20:40
  • 3
    Where did you get this code from? It's a bit of a hack to use strlen on an array of strings. Would not recommend it. Commented Mar 14, 2021 at 20:42
  • 7
    Side note: C has only been around for 50 years :-) Commented Mar 14, 2021 at 20:51
  • 2
    [As others have mentioned], you are calling strlen to get the number of array elements. This doesn't compile. You are using the strlen return value as the count of the number of array elements, so this won't work. Do: #define COUNTOF(_arr) (sizeof(_arr) / sizeof(_arr[0])) and replace all the (e.g.) strlen(checkArray) with COUNTOF(checkArray) Commented Mar 14, 2021 at 20:59
  • 2
    " someone who knows c for 100 years" - I am not quite old enough yet. Nor is C. BTW - Please could you not delete previous questions - they may be useful to others in the future Commented Mar 14, 2021 at 21:03

2 Answers 2

1

strlen() gives you the length of a single string. So when you

    char *checkArr[1000] = {"This is very good", 
                            ...,
                            NULL};
    int size = strlen(checkArr);

You are asking strlen() to measure an array of strings - which is not what it does. Your compilter will complain:

main.c:16:20: warning: passing argument 1 of ‘strlen’ from incompatible pointer type [-Wincompatible-pointer-types]

    int size = strlen(checkArr);

And it is right - you are passing a pointer to the wrong thing. If you had done this:

    char *checkArr[1000] = {"This is very good", 
                            ...,
                            NULL};
    int size_of_string_0 = strlen(checkArr[0]);

Then that would have worked - but it isn't what you are trying to measure.

So then the question is, what are you trying to measure?

If what you want to measure is the length of the array then it will always be 1000 in your example because that's the size you defined it to be. You can measure that with:

    char *checkArr[1000] = {"This is very good", 
                            ...,
                            NULL};
    int size_of_array = sizeof(checkArr)/sizeof(checkArr[0]); // will be 1000

If what you want to measure is the number of things that you initialise the array with then you need to count those yourself. All the ones you don't initialize are set to a default value so all 1000 of them exist but there is no way to know which ones you initialised manually and which were done for you.

If what you want to meansure is the length of an array of pointers until the first NULL pointer then you need to count those entries yourself. But you can do that - you need to write your own function. Something like:

// I use size_t instead of int.  For why, see:
// https://stackoverflow.com/questions/131803/unsigned-int-vs-size-t
size_t arrlen(char **checkArr) {
    size_t len = 0;
    for (;*checkArr != NULL; checkArr++)
        len++;
    return len;
}

So then all you need to do is make sure all you arrays of pointers have a value set to NULL.

Here is the whole code:

#include <stdio.h>
#include <string.h>

size_t arrlen(char **checkArr) {
    size_t len = 0;
    for (;*checkArr != NULL; checkArr++)
        len++;
    return len;
}

int main() {
    char *checkArr[1000] = {"This is very good", 
                            "text that has been",
                            "put into a file for", 
                            "the purposes of", 
                            "being an example.",
                            NULL};
    int size2 = arrlen(checkArr);
    printf("Check Array size: %d\n", size2);
    for (int i =0; i < arrlen(checkArr); i++){
        printf("%s\n", checkArr[i]);
    }
    puts("");
    
    char *checkArr2[1000] = {"This is very good", 
                            "text that has been",
                            "put into a file for", 
                            NULL, 
                            "being an example.",
                            NULL};
    int size3 = arrlen(checkArr2);
    printf("Check Array size: %d\n", size3);
    for (int i =0; i < arrlen(checkArr2); i++){
        printf("%s\n", checkArr2[i]);
    }
    puts("");
    
    char *checkArr3[1000] = {"This is very good", 
                             "text that has been",
                             NULL};
    int size4 = arrlen(checkArr3);
    printf("Check Array size: %d\n", size4);
    for (int i =0; i < arrlen(checkArr3); i++){
        printf("%s\n", checkArr3[i]);
    }
    puts("");
    
    char *checkArr4[1000] = {"This is very good", 
                            "text that has been",
                            NULL, 
                            "the purposes of", 
                            "being an example.",
                            NULL};
    int size5 = arrlen(checkArr4);
    printf("Check Array size: %d\n", size5);
    for (int i =0; i < arrlen(checkArr4); i++){
        printf("%s\n", checkArr4[i]);
    }
    puts("");
    
    return 0;
}

Try it here: https://onlinegdb.com/r1QOTg2m_

If you want to count the number of items that are not NULL even if some are null then you need to pass in the size of the initialized items and have the loop check each of those for NULL. Something like:

#include <stdio.h>
#include <string.h>

size_t arritems(char *checkArr[], size_t size) {
    int count = 0;
    for (size_t len = 0; len<size; len++)
        if(checkArr[len] != NULL) {
            count++;
    }
    return count;
}

int main() {
    char *checkArr[1000] = {"This is very good", 
                            "text that has been",
                            "put into a file for", 
                            "the purposes of", 
                            "being an example.",
                            NULL};
    int size2 = arritems(checkArr,6);
    printf("Check Array size: %d\n", size2);

    char *checkArr2[1000] = {"This is very good", 
                            "text that has been",
                            "put into a file for", 
                            NULL, 
                            "being an example.",
                            NULL};
    int size3 = arritems(checkArr2,6);
    printf("Check Array size: %d\n", size3);

    char *checkArr3[1000] = {"This is very good", 
                             "text that has been",
                             NULL};
    int size4 = arritems(checkArr3,3);
    printf("Check Array size: %d\n", size4);

    char *checkArr4[1000] = {"This is very good", 
                            "text that has been",
                            NULL, 
                            "the purposes of", 
                            "being an example.",
                            NULL};
    int size5 = arritems(checkArr4,6);
    printf("Check Array size: %d\n", size5);

    return 0;
}

Try it here: https://onlinegdb.com/S1g90lhXu

Sign up to request clarification or add additional context in comments.

Comments

0

This is prefaced by my top comments.

You're replicating code. Better to add an (e.g.) print_array function to do the NULL limited printing.

Note that checkArr3 does not have a NULL terminator


Here's some refactored code. I had replaced the strlen calls with the COUNTOF macro that I mentioned, but that still didn't work too well.

I've used cpp conditionals to denote old vs new code (e.g.):

#if 0
// old code
#else
// new code
#endif

Anyway, here it is:

#include <stdio.h>
#include <string.h>

#define COUNTOF(_arr) \
    (sizeof(_arr) / sizeof(_arr[0]))

void
print_array(char **arr)
{

    for (;  *arr != NULL;  ++arr)
        printf("%s\n",*arr);
}

int
main()
{

    char *checkArr[1000] = {
        "This is very good",
        "text that has been",
        "put into a file for",
        "the purposes of",
        "being an example.",
        NULL
    };
    int size2 = COUNTOF(checkArr);

    printf("Check Array size: %d\n", size2);

#if 0
    for (int i = 0; i < COUNTOF(checkArr); i++) {
        printf("%s\n", checkArr[i]);
    }
#else
    print_array(checkArr);
#endif

    char *checkArr2[1000] = {
        "This is very good",
        "text that has been",
        "put into a file for",
        NULL,
        NULL,
        NULL
    };
    int size3 = COUNTOF(checkArr2);

    printf("Check Array size: %d\n", size3);

#if 0
    for (int i = 0; i < COUNTOF(checkArr2); i++) {
        printf("%s\n", checkArr2[i]);
    }

    for (int i = 0; i < COUNTOF(checkArr2); i++) {
        printf("%s\n", checkArr2[i]);
    }
#else
    print_array(checkArr2);
#endif

    char *checkArr3[1000] = {
        "This is very good",
        "text that has been",
#if 1
        NULL
#endif
    };
    int size4 = COUNTOF(checkArr3);

    printf("Check Array size: %d\n", size4);

#if 0
    for (int i = 0; i < COUNTOF(checkArr3); i++) {
        printf("%s\n", checkArr3[i]);
    }
#else
    print_array(checkArr3);
#endif

    char *checkArr4[1000] = {
        "This is very good",
        "text that has been",
        NULL,
        NULL,
        NULL,
        NULL
    };
    int size5 = COUNTOF(checkArr4);

    printf("Check Array size: %d\n", size5);

#if 0
    for (int i = 0; i < COUNTOF(checkArr4); i++) {
        printf("%s\n", checkArr4[i]);
    }
#else
    print_array(checkArr4);
#endif

    return 0;
}

1 Comment

Thank you so much for a better understanding. I really appreciate it. It is making sense to me now

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.