Search

8.12 — Struct definition and member selection

There are many instances in programming where we need more than one variable in order to represent something of interest. For example, lets say you were writing a program where you wanted to represent yourself. In order to do that, you might want to store your name, your birthday, your height, your weight, or any other number of characteristics about yourself. You could do so like this:

However, you now have 6 independent variables that are not grouped in any way. If you wanted to pass this information to a function, you’d have to pass each variable individually, which means the function needs to take 6 parameters.

Furthermore, if you wanted to store information about someone else besides yourself, you’d have to declare 6 more variables for each additional person! As you can see, this can quickly get out of control.

In lesson 8.2 -- Introduction to unscoped enumerations, we discussed how enumerations allowed us to create our own program-defined data types. Enumerations are not the only kind of program-defined data type that C++ offers. C++ also allows us to create our own program-defined aggregate data types. An aggregate data type is a data type that groups more than one variable together.

One of the simplest aggregate data types is the struct. A struct (short for structure) allows us to group variables of mixed data types together into a single unit. Structs are also considered to be a class type, which means we will typically pass them by reference instead of by value.

Author's note

In this lesson, we’ll talk about structs that only hold data. These are sometimes called plain old data structs (sometimes abbreviated as POD structs). We’ll talk more about non-POD structs in a future lesson, when we discuss how to create your own classes.

Declaring structs

Because structs are a program-defined type, we first have to tell the compiler what our struct looks like before we can begin using it. To do this, we define our struct using the struct keyword. Here is an example of a struct declaration:

This tells the compiler that we are declaring a struct type named Employee. The Employee struct contains 3 variables inside of it: a short named id, an int named age, and a double named wage. These variables that are part of the struct are called members (or member variables, or rarely fields). Keep in mind that Employee is just a declaration -- even though we are telling the compiler that the struct will have member variables, no memory is allocated at this time.

Because they are a program-defined type, struct names typically start with a capital letter.

Warning

One of the easiest mistakes to make in C++ is to forget the semicolon at the end of a struct declaration. This will cause a compiler error on the next line of code. These errors can be really hard to find, because the compiler may tell you the error is on a line that doesn’t actually have an error!

Defining struct objects

In order to use the Employee struct, we simply define a variable of type Employee:

This defines a variable of type Employee named joe. As with normal variables, defining a struct variable allocates memory for that variable.

It is possible to define multiple variables of the same struct type:

Accessing members

Consider the following example:

When we reference joe, joe refers to the entire struct (which contains the member variables). To members of a struct, we use the member selection operator (which is a period) in between the struct object name and the member name. For example, to access Joe’s age, we’d use joe.age:

This prints:

32

Struct member variables work just like normal variables, so it is possible to do normal operations on them:

In the above example, it is very easy to tell which member variables belong to Joe and which belong to Frank. This provides a much higher level of organization than individual variables would. Furthermore, because Joe’s and Frank’s members have the same names, this provides consistency across multiple variables of the same struct type.

We’ll continue our exploration of structs in the next lesson, including a look at how to initialize them.


8.13 -- Struct initialization
Index
8.11 -- Pass by address and return by address

134 comments to 8.12 — Struct definition and member selection

  • Gayan

  • begginner

    #include<iostream>
    #include<string>
    using namespace std;
    struct advertise
    {

        int no_of_ads;
        int no_of_users;
        int average_per_click;
        };

    getreport(advertise pa)
    {
        cout<<"enter no af ads no of user and avg per click"<<endl;
        cin>>pa.no_of_ads;
        cin>>pa.no_of_users;
        cin>>pa.average_per_click;
        cout<<"no of ads are"<<pa.no_of_ads<<endl;
    cout<<"no of users are"<<pa.no_of_users<<endl;
        cout<<"avaerage per click"<<pa.average_per_click<<endl;
        cout<<"money per day is"<<pa.no_of_ads*pa.no_of_users*pa.average_per_click;
    }

    main(){
        advertise a;
        getreport( a);
        

    }

  • Thnx Alex. You are great.
    Still confused, what is 32767 here and should I use cin.ignore. In both the cases where getline (cin, ) and simple cin are used, or only when getline is used. Why this only messes up with getline and not with cin?

    • Alex

      32767 is just a large integer that tells cin.ignore how many characters to look through for a 'n'. In this case, you could use a low number since the 'n' is likely going to be the first character (unless the user entered invalid input when asked for an integer).

      Unfortunately, getline and cin just work different with regards to how they handle input (particularly whitespace). They're a pain, and their error handling capabilities are limited. I personally find it easier to read in everything as a string and then convert the string to an integer when that's appropriate. That helps avoid unexpected characters in the streams.

  • I m trying to write a program that prints a company's information (e.g. company name, name of CEO etc.). I am using struct to group all the related variables. My struct looks like:

    I defined a void printInfo (Company x) to print information of a company. My main () takes data from user and passes that to printInfo(). Rest of the work is done by printInfo (). My problem is with main () that is following:

    The above code compiles and links fine (not including the void printInfo (), nothing wrong with that). On execution, the program starts from taking input for x.NameOfCompany. That's okay. But all the other getline () puzzled me. Program never asks for input for one (or both when i change the order of getlines, e.g. putting BranchesIn before NameOfCeo) variables which is set to take input through getline method. What's the problem. Does getline has any limitations?

    If the code has any syntax or typographical error, please ignore. I swear that was linked and compiled fine.
    Thanx Alex :-)

    • Alex

      The problem is the way cin works. When it asks for total revenue, and you enter "45" and hit enter, this gets input as "45n". The 45 gets extracted to x.Revenue, but the "n" stays in the input stream. This messes up the next call to getline() (because it sees the 'n' and says, "I'm done!").

      To fix this, after each call to cin to read in a number, you can use the following to get rid of the extra 'n' stuck in the input stream:

  • Jacob

    In this segment of code, if Joe and Frank have the same wage, for example, if Joe and Frank both make 24.15, (joe.wage > frank.wage) will evaluate to false, and it will say "Joe makes less than frank"

  • "Structs can contain other structs"

    If you want to tell what struct can contain, you should clear everything.  When I finished reading this lesson and moved to comprehensive quiz, I found that you have nested an enumerated  type as a struct member in your solution. Before that, I was believing struct can only contain structs. It is still unclear to me what other kinds of objects a struct can contain.

    One question: I want to create great programs using C++. What should I do after completing your tutorials? How much time would it take to reach there?
    Thanks... :)

  • thanks all
    this note is very necessary

  • techsavvy....aye

    But I took the example of- Input the first numerator:12

                               Input the first denominator:4

                               Input the second numerator:12

                               Input the second denominator:3

    Which does not include any fractional division but still according to the problem which I had it is giving 4 instead of 12.

    Sorry!!!....to keep bothering you off topic.

    • Alex

      Oh.

      Should be:

  • techsavvy....aye

    Just by changing the signs in the void multiply part of the quiz question 2. Why does it give a different answer.

    • Alex

      static_cast(f1.numerator / f1.denominator) does an integer division (dropping any fractional part) and then casts the result to a float (which isn't useful because we've already lost any fractional result).

      The quiz example does the integer multiplication first, casts that to a float, and then does a floating point division (so as not to lose the fractional component).

  • techsavvy....aye

    A typo (maybe)

    everywhere you have mentioned joe's age to be 32 but here "Initializer lists" it is 42.

    Though it isn't an issue. Just to let you know.

    :P

Leave a Reply

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">