I'm learning C++ from the book C++ Primer Plus. At the end of the chapter on loops, they want us to design a structure, allocate adequate memory for an array of such structures using new, then feed input data to it. I got this code:

#include <iostream>

using namespace std;

struct car{
    char make[20];
    int yearMade;
};

int main()
{
    int count = 0;
    cout<<"How many cars do you wish to catalog today? ";
    cin>>count;

    car * autocar = new car[count];

    for(int i=1; i<=count; i++){
        cout<<"Car #"<<count<<": "<<endl;
        cout<<"Please enter the make: ";
        cin.get(autocar[i-1]->make).get();

        cout<<"Please enter the year manufactured: ";
        cin>>autocar[i-1]->yearMade;
        cout<<endl;
    }
    cout<<endl<<"Here is your collection: "<<endl;
    for(int i = 1; i<=count; i++){
        cout<<autocar[i-1]->yearMade<<" "<<autocar[i-1]->make<<endl;
    }
    delete [] autocar;
    return 0;
}

Now, the error comes on line 21, 24 and 29. The compiler is complaining that the "base operand of '->' has non-pointer type 'car'".
Beats me. I made sure that the type is a pointer, as you can see in the statement in line 16. Any suggestions?

autocar is a pointer but autocar[i-1] refers to a struct and so you should use '.' to access its functions, attributes.

autocar is a pointer but autocar[i-1] refers to a struct and so you should use '.' to access its functions, attributes.

I don't see how that works. autocar is a pointer to an array of count cars. So, autocar[i-1] is still a pointer to the structure car.

I did what you suggested anyway, and there was another error on the same line.

"no matching function call to std::basic_istream<char, std::char_traits<cha.."

This is because the function cin.get() will take a char* parameter and the size of the array of chars, and the compiler doesn't find the function that has only a char* parameter.

You should change the "make" variable to type std::string (in #include <string>) and use getline() on the cin instead.

The line "car * autocar = new car[count];" makes an array of cars of size count, and autocar is a pointer to that array. However, the array contains value types of car, not pointers to cars. To get an array of pointers to cars, you'd need to do "car ** autocar = new car*[count];" This creates an array of pointers to cars of size count.

The catch is that C++ implements arrays using pointers. The pointer points to the first element in the array, and the [] operator tells it to go to the first element plus the index. So if you had a pointer to a car you could do

car * myCar = new car();
myCar->yearMade = 1999;

or you could do

car * myCar = new car();
myCar[0].yearMade = 1999;

Both codes would accomplish the same thing, though in my opinion the first is a better choice because the second makes myCar look like it's an actual array when it's not.

I hope that makes things more clear.

Edited 6 Years Ago by embooglement: n/a

Comments
Thanks, that was very well explained, made stuff clear.

The line "car * autocar = new car[count];" makes an array of cars of size count, and autocar is a pointer to that array.

Not quite: autocar is a pointer to the initial element of the array, not a pointer to the array. This distinction is important because it means that *autocar is an element, not an array.

That's what I was going for, arkoenig, though you definitely put it better.

This question has already been answered. Start a new discussion instead.