Thread: How to identify the end of array

  1. #1
    Registered User
    Join Date
    Apr 2019
    Posts
    35

    How to identify the end of array

    I have written the following code to identify the end of array
    Code:
    #include <stdio.h>
    unsigned int array[20]={21,22,23,12,1,0,6,7,'\0'};
    int main() 
    {
        // Write C code here
        unsigned int max=0;
        unsigned int index=0;
        while(array[index] != '\0')
        {
            if(array[index] > max)
            {
                max = array[index];
            }
            index++;
        }
        printf("max = %d\n number of elements = %d",max,index);
        return 0;
    }
    The output of the index is 5, which is not expected. How do i update the logic to identify the end of array?

  2. #2
    Registered User
    Join Date
    Dec 2017
    Posts
    1,633
    In C, character literals are ints, so '\0' is identical to 0. Even if char literals weren't ints (as in C++), assigning '\0' to an unsigned data type will still yield 0.
    You could use the value -1, which when interpreted as an unsigned int becomes UINT_MAX.
    You could also directly use UINT_MAX (include limits.h).
    If your data values can use the entire unsigned range, then you will need to keep track of the array size and stop when index reaches that size.
    A little inaccuracy saves tons of explanation. - H.H. Munro

  3. #3
    Registered User Sir Galahad's Avatar
    Join Date
    Nov 2016
    Location
    The Round Table
    Posts
    277
    Quote Originally Posted by Clearner123 View Post
    I have written the following code to identify the end of array
    Code:
    #include <stdio.h>
    unsigned int array[20]={21,22,23,12,1,0,6,7,'\0'};
    int main() 
    {
        // Write C code here
        unsigned int max=0;
        unsigned int index=0;
        while(array[index] != '\0')
        {
            if(array[index] > max)
            {
                max = array[index];
            }
            index++;
        }
        printf("max = %d\n number of elements = %d",max,index);
        return 0;
    }
    The output of the index is 5, which is not expected. How do i update the logic to identify the end of array?
    You could probably use a macro.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    #define CARDINAL(array) \
      (((void*)array != (void*)&array) ? 0 : sizeof(array) / sizeof(array[0]))
    
    void this_will_not_work(unsigned int* arg) {
      printf("CARDINAL macro does not work for variables passed to functions (cardinality: %zu)\n",
             CARDINAL(arg));
    }
    
    #include <stdio.h>
    unsigned int array[20] = {21, 22, 23, 12, 1, 0, 6, 7, '\0'};
    int main() {
      // Write C code here
      unsigned int max = 0;
      unsigned int index = 0;
      while (array[index] != '\0') {
        if (array[index] > max) {
          max = array[index];
        }
        index++;
      }
      printf("max = %d\nnumber of elements = %zu\n", max, CARDINAL(array));
      this_will_not_work(array);
      return 0;
    }
    Not sure if there are any corner cases where that could fail however...

  4. #4
    Registered User rstanley's Avatar
    Join Date
    Jun 2014
    Location
    New York, NY
    Posts
    1,111
    Quote Originally Posted by Clearner123 View Post
    I have written the following code to identify the end of array
    Code:
    #include <stdio.h>
    unsigned int array[20]={21,22,23,12,1,0,6,7,'\0'};
    int main() 
    {
        // Write C code here
        unsigned int max=0;
        unsigned int index=0;
        while(array[index] != '\0')
        {
            if(array[index] > max)
            {
                max = array[index];
            }
            index++;
        }
        printf("max = %d\n number of elements = %d",max,index);
        return 0;
    }
    The output of the index is 5, which is not expected. How do i update the logic to identify the end of array?
    Just get used to the idea that two variables must be defined when using arrays. The array itself, and a variable (or constant) containing the size of the array!

    This is especially true when passing arrays to a function, and for dynamically allocated arrays, using malloc() or calloc()!

    You need to pass the array, AND the size of the array to the function as sizeof(array) would be useless inside of the function!

    You also need to insure that you do not exceed the size of the array when adding data to the array, again, especially when using strcpy(), strcat(), etc...!!!

  5. #5
    Registered User
    Join Date
    Dec 2023
    Posts
    6
    Officially you're mixing up data types, so '\0' is going to get cast to an unsigned int if the compiler allows this code to begin with. Officially a good compiler would have pointed this out.

    I would recommend you just add a variable "int last=7;" to identify the index of the last value you set in the array. To make matters more structured in your code, you might want to create a new "struct" that contains the array and other variables you might want to reference.

    I don't know whether this is interesting to you, but you could have all kinds of fun things going on. You could in the struct also have an array of 20 booleans that identify for each and every individual element whether it was set or not. Then you can write functions that shrink the array or insert new elements in it. That kind of stuff.

  6. #6
    Registered User
    Join Date
    Mar 2023
    Posts
    33
    The output is 5 because the array stops incrementing index when it reaches your element 0, as john.c explained with different words.

    Here is the working version of your program, "array[index]" is the value of the elements, and "index" can be used for the loop:

    Code:
    #include <stdio.h>
    
    
    unsigned int array[]={21,22,23,12,1,0,6,7};
    
    
    int main() 
    {
        // Write C code here
        unsigned int max=0;
        unsigned int index=0;
        while(index != 8)
        {
            if(array[index] > max)
            {
                max = array[index];
            }
            index++;
        }
        printf("max = %d\n number of elements = %d",max,index);
        return 0;
    }
    However, I'm sure you realize the issue with counting out the elements, so we could also make a version of your program that counts the number of integer elements so that it could be compared to the array even if you change the number of elements:

    Code:
    #include <stdio.h>
    
    
    unsigned int array[]={21,22,23,12,1,0,6,7};
    
    
    int main() 
    {
        // Write C code here
        unsigned int max=0;
        unsigned int index=0;
        unsigned int size = sizeof(array) / 4;
        
        while(index != size)
        {
            if(array[index] > max)
            {
                max = array[index];
            }
            index++;
        }
        printf("max = %d\n number of elements = %d",max,index);
        return 0;
    }
    What I did was pass the array to the sizeof() function, which counts the number of bytes in the array. Since integers are 4 bytes each, we divide the number by 4 to get the number of elements.

    You should also understand that null terminators are not necessary or used commonly for arrays of integers. Null terminators are just used to mark the end of a string, because otherwise your compiler will have no way of knowing when the loop ends otherwise. You don't actually need to add it yourself unless you are using a loop to make an array, if you have an array of chars, then the null terminator will get added automatically:

    Code:
    your_name[] = "Clearner123";
    When the string is declared like that, your compiler will add the null terminator.

    Also, having "while(array[index] != '\0')" is redundant, because while loops run until the condition is true or
    false anyways:

    Code:
    while(array[index])
    {
    ...
    }
    That while loop will run as long as "array[index]" does not equal zero...in programming terminology, it will
    run while the condition is true. To run the loop as long as the condition is equal to zero (false), then just
    add the exclamation point:

    Code:
    while(!array[index])
    {
    ...
    }

  7. #7
    Registered User
    Join Date
    May 2012
    Location
    Arizona, USA
    Posts
    948
    Quote Originally Posted by C_me_run View Post
    Code:
    #include <stdio.h>
    
    
    unsigned int array[]={21,22,23,12,1,0,6,7};
    
    
    int main() 
    {
        // Write C code here
        unsigned int max=0;
        unsigned int index=0;
        unsigned int size = sizeof(array) / 4;
        
        while(index != size)
        {
            if(array[index] > max)
            {
                max = array[index];
            }
            index++;
        }
        printf("max = %d\n number of elements = %d",max,index);
        return 0;
    }
    What I did was pass the array to the sizeof() function, which counts the number of bytes in the array. Since integers are 4 bytes each, we divide the number by 4 to get the number of elements.
    What you should do instead of hardcoding the size of int as 4 (int is larger or smaller than 4 on some platforms) is to use sizeof (int), or better yet, sizeof array[0]:

    Code:
        unsigned int size = sizeof array / sizeof array[0];
    Using sizeof array[0] is useful in case you change the type of the array array.

  8. #8
    Registered User
    Join Date
    Apr 2021
    Posts
    140
    Quote Originally Posted by christop View Post
    What you should do instead of hardcoding the size of int as 4 (int is larger or smaller than 4 on some platforms) is to use sizeof (int), or better yet, sizeof array[0]:

    Code:
        unsigned int size = sizeof array / sizeof array[0];
    Using sizeof array[0] is useful in case you change the type of the array array.

    This macro is one of the most common utility macros in C programmers' toolboxes everywhere. Pretty much everybody needs it, and the standards committee has never bothered to help us out, because ... that's what they do.

    Create a header file named after yourself. So, @op might create clearner123.h. Then give it the standard include guard treatment, and then add this definition:

    Code:
    #define dimension_of(arr) (sizeof (arr) / sizeof *(arr))
    You can also put in all the other "cool" things you think might be useful, and have them all in one place.

    Code:
    #define elif else if
    #define is_power_of_2(intval) (((intval) & (intval) - 1) == 0)
    #define is_even(intval) (((intval) & 1) == 0)
    #define is_null(ptr) ((ptr) == NULL)
    #define STRCMP(a, op, b) (strcmp(a, b) op 0)
    #define str_eq(a, b) STRCMP((a), ==, (b))
    #define str_lt(a, b) STRCMP((a), <, (b))

  9. #9
    Registered User
    Join Date
    Mar 2023
    Posts
    33
    Quote Originally Posted by christop View Post
    What you should do instead of hardcoding the size of int as 4 (int is larger or smaller than 4 on some platforms) is to use sizeof (int), or better yet, sizeof array[0]:

    Code:
        unsigned int size = sizeof array / sizeof array[0];
    Using sizeof array[0] is useful in case you change the type of the array array.
    Yeah that's true, but it's also better to understand when you are starting out as a low-level programmer the size of elements of different data types, it's true your method is more flexible though and prevents you from having to make future changes to your code...

  10. #10
    Registered User rstanley's Avatar
    Join Date
    Jun 2014
    Location
    New York, NY
    Posts
    1,111
    Quote Originally Posted by C_me_run View Post
    Yeah that's true, but it's also better to understand when you are starting out as a low-level programmer the size of elements of different data types, it's true your method is more flexible though and prevents you from having to make future changes to your code...
    If the beginner, or "low-level" programmer, would first study a good up-to-date book on the C Programming Language, and do all the exercises at the end of each chapter, the programmer would then learn about all the data types available, such as char, int, long, float, double, etc.... The programmer would also learn about the header file, limits.h, and the minimum, and maximum range of values each type can contain.

    An advanced programmer could then study about the header file, stdint.h, to expand the types available.

    And of course, a study of the compiler documentation in use would provide the features and limits of the data types in the specific compiler.
    Last edited by rstanley; 01-02-2024 at 09:49 AM. Reason: typo correction

  11. #11
    Registered User
    Join Date
    May 2012
    Location
    Arizona, USA
    Posts
    948
    Quote Originally Posted by C_me_run View Post
    Yeah that's true, but it's also better to understand when you are starting out as a low-level programmer the size of elements of different data types, it's true your method is more flexible though and prevents you from having to make future changes to your code...
    I disagree for the most part.

    A beginner programmer shouldn't really worry about how big each data type is (they should understand their ranges and when and where to use each type, though). And by the time a programmer learns about arrays, they should know how to use sizeof.

    A programmer also should learn from nearly the beginning not to use "magic numbers".

  12. #12
    Registered User
    Join Date
    Mar 2023
    Posts
    33
    Quote Originally Posted by christop View Post
    I disagree for the most part.

    A beginner programmer shouldn't really worry about how big each data type is (they should understand their ranges and when and where to use each type, though). And by the time a programmer learns about arrays, they should know how to use sizeof.

    A programmer also should learn from nearly the beginning not to use "magic numbers".
    People learn in their own way, it doesn't hurt to learn about how sizeof works. You can't use sizeof properly w/o understanding it uses byte size by default.

    I personally think it's bad practice to omit parenthesis when passing arguments to functions, but you do you.

  13. #13
    Registered User
    Join Date
    May 2012
    Location
    Arizona, USA
    Posts
    948
    Quote Originally Posted by C_me_run View Post
    You can't use sizeof properly w/o understanding it uses byte size by default.
    One nitpick: sizeof reports the size of an object or type in terms of the size of a char, not bytes. A char is one byte on most platforms, but some platforms may define char as 16 or 32 bits (in which case sizeof (int) could be 1 or 2).

    I personally think it's bad practice to omit parenthesis when passing arguments to functions, but you do you.
    Which function? sizeof is a unary operator, not a function. It takes either an object or a type. A type must be in parentheses, such as sizeof (int), but an object does not, such as sizeof array. (Some people also mistakenly think return needs parentheses, but it doesn't.) And if sizeof were a function, it wouldn't be only "bad practice" to omit the parentheses around the parameter list; it would be a compile error.

  14. #14
    Registered User
    Join Date
    Mar 2023
    Posts
    33
    Quote Originally Posted by christop View Post
    One nitpick: sizeof reports the size of an object or type in terms of the size of a char, not bytes. A char is one byte on most platforms, but some platforms may define char as 16 or 32 bits (in which case sizeof (int) could be 1 or 2).



    Which function? sizeof is a unary operator, not a function. It takes either an object or a type. A type must be in parentheses, such as sizeof (int), but an object does not, such as sizeof array. (Some people also mistakenly think return needs parentheses, but it doesn't.) And if sizeof were a function, it wouldn't be only "bad practice" to omit the parentheses around the parameter list; it would be a compile error.
    Okay, whatever, there's no harm in understanding how sizeof works. There's also no harm in learning C through whatever methods work for you. Putting arguments to sizeof in parens makes the code clearer to me.

  15. #15
    Registered User rstanley's Avatar
    Join Date
    Jun 2014
    Location
    New York, NY
    Posts
    1,111
    Quote Originally Posted by christop View Post
    One nitpick: sizeof reports the size of an object or type in terms of the size of a char, not bytes. A char is one byte on most platforms, but some platforms may define char as 16 or 32 bits (in which case sizeof (int) could be 1 or 2).
    ...
    In the C17 C Programming Language Standard:

    sizeof: Section 6.5.3.4 Paragraph 2
    The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. The size is determined from the type of the operand. The result is an integer.
    char: Section 6.5.3.4 Paragraph 4
    When sizeof is applied to an operand that has type char, unsigned char, or signed char, (or a qualified version thereof) the result is 1. When applied to an operand that has array type, the result is the total number of bytes in the array.
    The number of bits in the char may vary from the standard 8 bits, depending on the Compiler/O/S implementation, but the sizeof(char) is ALWAYS 1, and can be assumed. "sizeof(char)" in redundant redundancy!

    The actual size of all other data types should not be assumed.
    Last edited by rstanley; 01-02-2024 at 01:59 PM. Reason: Bad link

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. identify bug in code
    By acpower in forum C Programming
    Replies: 1
    Last Post: 06-17-2012, 07:02 AM
  2. Need help. Can't identify error.
    By bummielove in forum C Programming
    Replies: 23
    Last Post: 07-05-2011, 06:06 AM
  3. can you identify this car?
    By axon in forum A Brief History of Cprogramming.com
    Replies: 15
    Last Post: 07-19-2004, 02:59 PM

Tags for this Thread