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???

Jerry Jeremiah
  • 9,045
  • 2
  • 23
  • 32
  • 1
    Your code does not compile. – Fredrik Mar 14 '21 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. – kaylum Mar 14 '21 at 20:42
  • There i added more tests for an explanation of what am i looking at here? And what do you mean it does not compile –  Mar 14 '21 at 20:43
  • What do you mean where did i get this code. I wrote it. If i had gotten from somewhere i would have just left this alone and moved on with my life. But i am trying tto understand arrays and finding length of an array and printing out the arrays in c –  Mar 14 '21 at 20:44
  • `strlen(checkArr)` is just checking the length of the first string, as if you did `strlen(*checkArr)` or `strlen(checkArr[0])`, i think – Alexander Mar 14 '21 at 20:45
  • `strlen(checkArr);` doesn't work because `checkArr` is an array of things and `strlen` is expecting a string. If you want the length of the array itself you probably need to write your own function. Your compiler should have watned you about that. Mine says: `main.c:16:20: warning: passing argument 1 of ‘strlen’ from incompatible pointer type [-Wincompatible-pointer-types] int size2 = strlen(checkArr);` – Jerry Jeremiah Mar 14 '21 at 20:45
  • Your code does not compile means if anyone takes your code exactly as shown it will not compile - because it is incomplete. To get the array size you should do `sizeof(checkArray)/sizeof(checkArray[0])` – kaylum Mar 14 '21 at 20:46
  • @kaylum I don't think he wants the array size - I think he wants the number of things in the array (which is why he called strlen). – Jerry Jeremiah Mar 14 '21 at 20:48
  • It's part of my Project where I am trying to implement an Array to store and use to write. So I was just testing the waters basically and came across this interesting cloud of darkness –  Mar 14 '21 at 20:49
  • 7
    _Side note:_ C has only been around for 50 years :-) – Craig Estey Mar 14 '21 at 20:51
  • So, do you want number of string in the array? In that case use sizeof() as mentioned above. If you want no of characters, you need to iterate on the array. – Bichu Ben Mar 14 '21 at 20:55
  • okay i deff dont want to use strlen() find the length of an array. and strlen(*array) or strlen(array[0]) will not give you the right length for sure it will not throw an error. I was wrong –  Mar 14 '21 at 20:57
  • I want to print string by string and if there is NULL values i want to exit as if(arr[i]==NULL)break; but its throwing a segfault for when i try to write the array to a file and for stdout it prints the (null) values out –  Mar 14 '21 at 20:59
  • 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)` – Craig Estey Mar 14 '21 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 – Ed Heal Mar 14 '21 at 21:03
  • @Ed Heal yea but that whole part i was just trying to understand what the problem was people also down voted it so i just got rid of it. Plus its also part of the project and other students from my class my see my solution. You see people work as partners. I do it all alone SOLO Programmer haha –  Mar 14 '21 at 21:06
  • I tried to compile your extact code and it does not compile. – ClaudioDeLise Mar 14 '21 at 21:07
  • 1
    But, `COUNTOF` doesn't account for `NULL` values in the given array. Most of your arrays have a `NULL` terminator, but _not_ all. If you want just the valid [non-null] values, you need a function like: `size_t notnullcount(char **arr) { size_t count = 0; for (; arr[count] != NULL; ++count); return count; }` Or, just do (e.g.): `for (int i = 0; checkArr[i] != NULL; ++i)` – Craig Estey Mar 14 '21 at 21:08
  • Well, i just wanted to know why all the sizes were the same but I guess the program wasn't compiling even though the more test cases I was putting in. I was getting the output for all of them just the size was the same. –  Mar 14 '21 at 21:09
  • @ Craig Estey Thank you my friend. I used the checkArr[i] != NULL and it worked perfectly. And everyone else thank you for ya time. –  Mar 14 '21 at 21:16

2 Answers2

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

Jerry Jeremiah
  • 9,045
  • 2
  • 23
  • 32
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;
}
Craig Estey
  • 30,627
  • 4
  • 24
  • 48
  • Thank you so much for a better understanding. I really appreciate it. It is making sense to me now –  Mar 14 '21 at 21:37
  • 1
    You're welcome. Don't forget to upvote/accept. See: https://stackoverflow.com/help/someone-answers – Craig Estey Mar 14 '21 at 21:40