Get up to 80 % extra points for free! More info:

Lesson 13 - Structures in the C language

In the previous exercise, Solved tasks for C lesson 12, we've practiced our knowledge from previous lessons.

Lesson highlights

Are you looking for a quick reference on C structures instead of a thorough-full lesson? Here it is:

Declaring a structure:

typedef struct {
    char name[51];
    int age;
    char street[51];
} USER;

Creating and printing structures using loops:

#include <stdio.h>
#include <string.h>

typedef struct {
    char name[51];
    int age;
    char street[51];
} USER;

int main(int argc, char** argv) {
    USER users[10];

    strcpy(users[0].name, "John Smith");
    users[0].age = 33;
    strcpy(users[0].street, "Skew street 5");

    strcpy(users[1].name, "Jack Brown");
    users[1].age = 28;
    strcpy(users[1].street, "Sunnyvale 8");

    int i;
    for (i = 0; i < 2; i++)
    {
        printf("The user at the index %d\n", i);
        printf("Name: %s\n", users[i].name);
        printf("Age: %d\n", users[i].age);
        printf("Street: %s\n\n", users[i].street);
    }
    return 0;
}

Would you like to learn more? A complete lesson on this topic follows.

In the previous lesson, Solved tasks for C lesson 12, we learned how to declare custom functions in the C language. In today's tutorial, we'll learn to use another important feature of the C language which is structures. Since we're only going to create a simple program, we won't use custom functions today. Just remember if it was just a little bit longer, we really would need to split it into separate functions.

Storing complex items

Consider that we want to store data for a single user. He/she has a name, an age, and lives on a certain street. Using our current knowledge, we'd create multiple variables:

int main(int argc, char** argv) {
    char name[] = "John Smith";
    int age = 33;
    char street[] = "Skew street 5";

    return (EXIT_SUCCESS);
}

However, we usually don't store a single user in a program. As we already know, we use arrays to store multiple items of the same type. However, since the user contains values of 3 different types, we'd have to create 3 different arrays. One for names, the second one for ages, and the third one for streets. Let's create several arrays which are 10 elements long (for storing a maximum of ten users). We'll demonstrate their functionality by storing 2 users and printing them to the console using a for loop.

char names[10][51];
int ages[10];
char streets[10][51];

strcpy(names[0], "John Smith");
ages[0] = 33;
strcpy(streets[0], "Skew street 5");

strcpy(names[1], "Jack Brown");
ages[1] = 28;
strcpy(streets[1], "Sunnyvale 8");

int i;
for (i = 0; i < 2; i++)
{
    printf("The user at the index %d\n", i);
    printf("Name: %s\n", names[i]);
    printf("Age: %d\n", ages[i]);
    printf("Street: %s\n\n", streets[i]);
}

The result:

Console application
The user at the index 0
Name: John Smith
Age: 33
Street: Skew street 5

The user at the index 1
Name: Jack Brown
Age: 28
Street: Sunnyvale 8

The program looks pretty impressive considering our skills at this point. Once we learn to store data to files, we could program e.g. a phone book like this. Despite all that, the code above isn't ideal. Let's take note of several things here.

The definition of the names and streets arrays is interesting. Since we need to have a char array (name) in every item of the names array, we have to create a variable which is technically an array of arrays. Therefore, there are two pairs of brackets. In the first brackets, we have specified the number of items of the outer array, i.e. the number of names. In the second pair of brackets, we have the number of characters in each name. In our case it's 50 characters (+1 for \0).

As we already know, we can't assign string constants in the C language in any different way other than during the initialization. This is why we have to use the strcpy() function which copies a string into an existing variable. Printing using a loop should be clear, we're simply working with indexes < 2 since we don't have any more people at the moment.

Structures

To avoid declaring so many confusing arrays, the C language allows us to declare a structure. Simply put, it's a data type which is represented by a single variable, but contains multiple values (it's sometimes called a record type). It may remind you of an array, but it's items don't have to all be of the same type and they're not accessed by numbers. Instead, they're accused by their names. The best decision we could currently make is to create a USER structure in order to store users. Add the following definition somewhere into the global scope above the main() function:

typedef struct {
    char name[51];
    int age;
    char street[51];
} USER;

Although there are multiple ways to declare structures, as it often happens in the C language, we'll stick strictly with this one. We'll define structures as new data types using the typedef keyword which will help us with declaring variables of that type (USER) later on. Then the struct keyword follows. We declare items for the structure in the curly brackets block as ordinary variables. We name structures with UPPERCASE_LETTERS and end the whole declaration with a semicolon.

Now, let's rewrite the main() function to the following form:

#include <stdio.h>
#include <string.h>

typedef struct {
    char name[51];
    int age;
    char street[51];
} USER;

int main(int argc, char** argv) {
    USER users[10];

    strcpy(users[0].name, "John Smith");
    users[0].age = 33;
    strcpy(users[0].street, "Skew street 5");

    strcpy(users[1].name, "Jack Brown");
    users[1].age = 28;
    strcpy(users[1].street, "Sunnyvale 8");

    int i;
    for (i = 0; i < 2; i++)
    {
        printf("The user at the index %d\n", i);
        printf("Name: %s\n", users[i].name);
        printf("Age: %d\n", users[i].age);
        printf("Street: %s\n\n", users[i].street);
    }
    return 0;
}

The whole application is way more readable now. It simply contains a single array of the USER type instead of 3 arrays as before. We use the . (dot) operator to access structure items. If we used structures dynamically (which we can't quite yet), we would use the arrow operator (->). We'll explain all of this further along in the course.

Alternative structure definitions

Just for completeness' sake, let's go over other ways to create structures. Mainly, to enable you all to read programs by other programmers. If we created a structure without the typedef keyword, we'd name it as a lowercase_name:

struct user {
    char name[51];
    int age;
    char street[51];
};

We'd have to provide the struct keyword for declaring variables of this type from then on:

struct user users[10];

Sometimes, a structure is even defined directly with a variable:

struct {
    char name[51];
    int age;
    char street[51];
}  users[10];

Consider this last example as a rather deterrent code. Just because it's a little bit shorter doesn't always mean it's clearer. Furthermore, we can't use this sort of structure at multiple places in our program.

Note: Of course, we don't have to use structures all as arrays. They're an ordinary data type just like int. However, they increase readability, so be sure to use it everywhere where you need to store multiple values which are related to each other.

Note: Aside from structures, we can also declare so-called unions in the C language. Unions look the same as structures but variables of the union type can only have one of their items (values) initialized. Meaning that each user could only have either a name, an age, or a street address. This doesn't make much sense with users, however, it may sometimes happen that we need to store items and each item is a bit different. However, unions didn't become very popular because it gets troublesome to determine which of the values is initialized (therefore, they're often wrapped in structures). All in all, we won't deal with unions here.

We'll get back to structures once more throughout our courses. The source code for today's application is available for download below the article.

At this point, you have now finished the introductory course into the C language. Congratulations, you're now aware of most of its constructs! :) Of course, we'll continue, there are more exercises for you to practice, and then your journey shall continue in the Dynamic memory management in the C language course. There, you'll learn how to allocate memory dynamically, and no longer be limited by the lengths of static arrays. Since these matters are a bit complicated, the whole basics course avoided said constructs so you could try different, simpler C constructs while you get warmed up. I look forward to seeing you all soon. There, we'll create real-world applications!

In the following exercise, Solved tasks for C lesson 13, we're gonna practice our knowledge from previous lessons.


 

Did you have a problem with anything? Download the sample application below and compare it with your project, you will find the error easily.

Download

By downloading the following file, you agree to the license terms

Downloaded 1x (71.72 kB)
Application includes source codes in language C

 

Previous article
Solved tasks for C lesson 12
All articles in this section
The C Language Basic Constructs
Skip article
(not recommended)
Solved tasks for C lesson 13
Article has been written for you by David Capka Hartinger
Avatar
User rating:
No one has rated this quite yet, be the first one!
The author is a programmer, who likes web technologies and being the lead/chief article writer at ICT.social. He shares his knowledge with the community and is always looking to improve. He believes that anyone can do what they set their mind to.
Unicorn university David learned IT at the Unicorn University - a prestigious college providing education on IT and economics.
Activities