0

I am not understanding why this code is wrong, it says lvalue required as increment operand. But isn't planets an array of pointers to strings? so isn't planets++ supposed to take me to the next string. example- planets is a pointer to the string "mercury". When I do planets++ shouldn't it take me to "venus"

#include <stdio.h>

int main()
{

    char* planets[] = {"Mercury", "Venus", "Earth","Mars","Jupiter",
                        " Saturn", "Uranus", "Neptune", "Pluto"};


    int count = 0;
    for(planets; planets <= planets + 8;planets++){
        if(**planets == 'M'){
            count++;
        }// if 

    }// for

    printf("\n%d",count);

}
Support Ukraine
  • 42,271
  • 4
  • 38
  • 63
  • 2
    *"...isn't planets an array of pointers to strings?"* - Yup, stress the *first* part of that description; it's an *array*. This is a not-quite-textbook example of how arrays *aren't* pointers.. That increment operation makes no sense. – WhozCraig Oct 27 '19 at 05:57
  • @Saadman, is the space in front of `Saturn` intentional? – Mahonri Moriancumer Oct 27 '19 at 06:19
  • I think I got confused because when we pass pointers as function parameters we are allowed to use the array name as the pointer and change it. Because since arguments passed to functions are protected against change, it works in that case. I think that might be the diff – Saadman Islam Khan Oct 27 '19 at 07:01
  • `planets` is an array of pointers to strings. thus, `if(**planets == 'M')` is wrong. You might need another pointer which points to the pointer array `planets`. Note `**planets` is a pointer named `planets` to another pointer, which isn´t the case here. – RobertS supports Monica Cellio Oct 27 '19 at 12:08

4 Answers4

3

Your description of planets is accurate; it's defined as an array of pointers. Stress the array part of that, because that means using its id is disqualified for lvalue operations like post-increment.

If you want to walk that array of pointers using pointer notation, it can be done using a proper pointer-to-pointer keyed to the type of the array. If the array is an array of const char*, then a pointer to const char * (i.e. a const char **) is appropriate.

Like this:

#include <stdio.h>

int main()
{
    const char *planets[] = {
        "Mercury", "Venus", "Earth", "Mars", "Jupiter",
        "Saturn", "Uranus", "Neptune", "Pluto"
    };


    int count = 0;
    for(const char **p = planets; p != planets + 9; ++p)
    {
        if(**p == 'M'){
            count++;
        }// if
    }// for

    printf("%d\n",count);
}

Output

2
WhozCraig
  • 65,258
  • 11
  • 75
  • 141
  • Thank you for your answer. As far as I knew arrays are the same as pointers right? So Why can't I just use the array name as pointer and move through? Also, I am quite new to pointers, so its confusing me. Suppose, we declare a 2 dimentional array int B[2][3] . So doing the following will give me a compilation error right? int* p = B; But i read in my textbook, that we can int(p) [3] = B; and it would be correct? So for my planets code, could I have written the following: Instead of char** planet = planets; can i write char* planet [8] = planets; ? and can you explain the diff? – Saadman Islam Khan Oct 27 '19 at 06:57
  • @SaadmanIslamKhan They're *not* the same as pointers. When their id is used in the appropriate expression context, their id converts to a temporary pointer-to-type (most call it "decaying", but I prefer not to if for no other reason than because the language standard doesn't). An example of such conversion is in the init construct of the for loop of this answer, btw. – WhozCraig Oct 27 '19 at 07:02
  • Suppose, we declare a 2 dimentional array int B[2][3] . So doing the following will give me a compilation error right? int* p = B; But i read in my textbook, that we can int(p) [3] = B; and it would be correct? So for my planets code, could I have written the following: Instead of char** planet = planets; can i write char* planet [8] = planets; ? and can you explain the diff? ^can you answer this please? – Saadman Islam Khan Oct 27 '19 at 07:07
  • @SaadmanIslamKhan given a 2D array (use the term "array of arrays, because that's exactly what a real 2D array is), `int arr[2][3];` then an appropriate pointer type to initialize with *just* the array id would be `int (*p)[3] = arr;` – WhozCraig Oct 27 '19 at 07:14
  • So for the planets, if we had used array index to loop through, it would look like this,planents[0][i], so this is also a 2d array. So wouldn't an approriate pointer type to initialize with just the array id be char (*p)[8] = planets;? char *planets[] = { "Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune", "Pluto" }; could this not be written as char planets[9][8] ={ "Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune", "Pluto" }; – Saadman Islam Khan Oct 27 '19 at 07:28
  • Sorry for bugging you, but I am totally not getting this. If there's any online video or article reference you can give, it will be really appreciated too. – Saadman Islam Khan Oct 27 '19 at 07:29
  • References o-plenty are in the [Book Page for C](https://stackoverflow.com/questions/562303/the-definitive-c-book-guide-and-list). Sorry I don't have anything else; I learned this stuff 30+ years ago and it's like breathing now; I just do it. – WhozCraig Oct 27 '19 at 07:32
1

The variable planets is an array so you can't increment it.

Instead use an integer as index in the loop:

#include <stdio.h>

int main()
{

    char* planets[] = {"Mercury", "Venus", "Earth","Mars","Jupiter",
                        " Saturn", "Uranus", "Neptune", "Pluto"};


    int count = 0;
    for(int i = 0; i < 9; i++){
        if(planets[i][0] == 'M'){
            count++;
        }// if 

    }// for

    printf("\n%d",count);

}
Support Ukraine
  • 42,271
  • 4
  • 38
  • 63
1

As stated in the other answers, char *planets[] defines a an array of strings. The compiler will consider planets as a label afixed to the array, and will (generally) not allow that label to be moved. So, the best options are (as shown in the other answers here) to index through the array, or use an auxiliary pointer to walk the array.

I like to add an ending NULL to arrays, which provides a stopping point when walking them with an auxiliary pointer. For example:

  #include <stdio.h>

  int main()
    {
    char *planets[] = {"Mercury", "Venus", "Earth","Mars","Jupiter",
                        " Saturn", "Uranus", "Neptune", "Pluto", NULL};
    char **planet;

    int count = 0;
    for(planet = planets; *planet; planet++)
      {
      if(**planet == 'M')
            count++;
      }

    printf("%d\n",count);
    }
Mahonri Moriancumer
  • 5,993
  • 2
  • 18
  • 28
  • Thank you for your answer. As far as I knew arrays are the same as pointers right? So Why can't I just use the array name as pointer and move through? Also, I am quite new to pointers, so its confusing me. Suppose, we declare a 2 dimentional array int B[2][3] . So doing the following will give me a compilation error right? int* p = B; But i read in my textbook, that we can int(*p) [3] = B; and it would be correct? So for my planets code, could I have written the following: Instead of char** planet = planets; can i write char* planet [8] = planets; ? and can you explain the diff? – Saadman Islam Khan Oct 27 '19 at 06:49
  • @SaadmanIslamKhan, [This link](https://stackoverflow.com/questions/23963269/can-someone-explain-how-pointer-to-pointer-works/23964156#23964156) might help clear your mind about pointers. – Mahonri Moriancumer Oct 28 '19 at 06:03
0

regarding:

for(planets; planets <= planets + 8;planets++){  

this results in the following message from the compiler:

:11:48: error: lvalue required as increment operand

However, the variable planets is located at the address, fixed in memory, so cannot be changed. Suggest

for( char *string = planets; string <= planets+8; string++ )

then use the variable string within the body of the for() loop

user3629249
  • 16,402
  • 1
  • 16
  • 17
  • Thank you for your answer. As far as I knew arrays are the same as pointers right? So Why can't I just use the array name as pointer and move through? Also, I am quite new to pointers, so its confusing me. Suppose, we declare a 2 dimentional array int B[2][3] . So doing the following will give me a compilation error right? int* p = B; But i read in my textbook, that we can int(p) [3] = B; and it would be correct? So for my planets code, could I have written the following: Instead of char* planet = planets; can i write char* planet [8] = planets; ? and can you explain the diff? – Saadman Islam Khan Oct 27 '19 at 07:02
  • Actually and array is NOT a pointer. However, referencing an array name results in the address of the first byte of the array – user3629249 Oct 27 '19 at 08:00
  • The array cannot be moved. So need to use a different variable to step through the array (or access the array via `planets[0]` ... `planets[8]` – user3629249 Oct 27 '19 at 08:02