Struct in C (assign value into array of struct)

Viewed 153

I have this two different code writing in C. Both of them just try to assign value into structure. And i'm using cs50 library to help me to get string in simple way.

For the first code, when i'm trying to execute it got an error.

First Code:

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

#define MaxStudents 5

typedef struct
{
    string name;
    int age;
    string gender;
}
student;

student students[MaxStudents];

int main(void)
{
    students[0] = {"Kevin Mahendra", 22, "Male"};
    students[1] = {"Wasis Sirutama", 22, "Male"};
    students[2] = {"Alief Dean", 22, "Male"};
    students[3] = {"Adwi Lanang", 21, "Male"};
    students[4] = {"Dhimas Kuncahyo", 22, "Male"};

    for (int i = 0; i < MaxStudents; i++)
    {
        printf("%s, %i %s", students[i].name, students[i].age, students[i].gender);
    }

}

Problem (first code):

sorting.c:19:19: error: expected expression
    students[0] = {"Kevin Mahendra", 22, "Male"};
                  ^
sorting.c:20:19: error: expected expression
    students[1] = {"Wasis Sirutama", 22, "Male"};
                  ^
sorting.c:21:19: error: expected expression
    students[2] = {"Alief Dean", 22, "Male"};
                  ^
sorting.c:22:19: error: expected expression
    students[3] = {"Adwi Lanang", 21, "Male"};
                  ^
sorting.c:23:19: error: expected expression
    students[4] = {"Dhimas Kuncahyo", 22, "Male"};

But for the second code, it works well without any error.

Second Code:

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

#define MaxStudents 5

struct student
{
    string firstName;
    string lastName;
    int age;
};

int main(void)
{
    struct student kevin = {"Kevin", "Mahendra", 22};
    
    printf("%s %s, %i\n", kevin.firstName, kevin.lastName, kevin.age);
}

So what do you guys think the problem on my first code? What is expected expression means?

As you can see i'm just trying to assign value into the array of structures with only write it insdie {} just like i did in second code (But not an array). Please help me. Thank You.

5 Answers

The problem is the difference between initialization and assignment. Initialization is basically an assignment done together with declaration.

When you want to assign a compound literal (for example {"Kevin Mahendra", 22, "Male"}) you need to cast it by putting (student) in front of it, but the cast is not necessary during initialization.

Note: Technically, it's not a cast. But it does look exactly like a cast, and many are calling it casting, either because of lack of knowledge or just because of sloppy language. I thought it was a cast before Eric Postpischil pointed it out.

Change to

students[0] = (student) {"Kevin Mahendra", 22, "Male"};

You can also do this:

student students[MaxStudents] = {
    {"Kevin Mahendra", 22, "Male"},
    {"Wasis Sirutama", 22, "Male"},
    {"Alief Dean", 22, "Male"},
    {"Adwi Lanang", 21, "Male"},
    {"Dhimas Kuncahyo", 22, "Male"},
};

Note that you can initialize arrays this way, like you can with structs. However, you cannot assign array this way afterwards. Take this code:

int arr[3];
arr = // Will not work no matter what you type here.

There's absolutely nothing you could write after arr = that would compile. You could try arr = {1,2,3} or arr = (int[3]) {1,2,3} but it will not work, because it's simply not allowed to assign to an array during any circumstances. However, it's possible with a workaround if you wrap the array in a struct.

There is a difference between initialization (second code) and the assignment (first code)

This syntax is only valid if you initialize the object, not when you assign. As structs are copied when assigned you can use compound literals for that:

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

#define MaxStudents 5

typedef struct
{
    string name;
    int age;
    string gender;
}
student;

student students[MaxStudents];

int main(void)
{
    students[0] = (student){"Kevin Mahendra", 22, "Male"};
    students[1] = (student){"Wasis Sirutama", 22, "Male"};
    students[2] = (student){"Alief Dean", 22, "Male"};
    students[3] = (student){"Adwi Lanang", 21, "Male"};
    students[4] = (student){"Dhimas Kuncahyo", 22, "Male"};

    for (int i = 0; i < MaxStudents; i++)
    {
        printf("%s, %i %s\n", students[i].name, students[i].age, students[i].gender);
    }
}

https://godbolt.org/z/KvE7G1

The second piece of code is an initialization:

struct student kevin = {"Kevin", "Mahendra", 22};

Here you define a variable and provide an initial value. Here the part on the right of the = is parsed as having type struct student.

In the first code there is only an assignment

students[0] = {"Kevin Mahendra", 22, "Male"};

And in an assignment the type of the variable assigned to is not used in the evaluation of the right hand side. So the compiler can not know what {"Kevin Mahendra", 22, "Male"} is supposed to be.

This can be solved by using a compound literal (which essentially looks like a cast):

students[0] = (student){"Kevin Mahendra", 22, "Male"};

Or you can just initialize the students array when you define it:

student students[MaxStudents] = {
    {"Kevin Mahendra", 22, "Male"},
    {"Wasis Sirutama", 22, "Male"},
    {"Alief Dean", 22, "Male"},
    {"Adwi Lanang", 21, "Male"},
    {"Dhimas Kuncahyo", 22, "Male"},
};

You can only initialize a struct like that when it is created. struct student kevin = {"Kevin", "Mahendra", 22}; will work just fine, but try struct student kevin; kevin = {"Kevin", "Mahendra", 22};; it will give an error.

When you create the array, it will put an uninitialized struct at each index, meaning you can't initialize it afterwards. [EDIT] As klutt mentioned, you can set the values with {} with a cast.

For completeness the ugly one:

#include <string.h>

  ...

  student students[MaxStudents];

  memcpy(students, 
    (student[MaxStudents])
    {
      {"Kevin Mahendra", 22, "Male"},
      {"Wasis Sirutama", 22, "Male"},
      {"Alief Dean", 22, "Male"},
      {"Adwi Lanang", 21, "Male"},
      {"Dhimas Kuncahyo", 22, "Male"},
    },
    sizeof (student[MaxStudents])
  );
Related