Sarah
Sarah

Reputation: 43

How do I fix this lvalue warning?

My code is:

void main() {
 person student[10];
 
 student[0].names[0] = 'C';
 student[0].names[1] = 'a';
 student[0].names[2] = 'm';
 student[0].names[3] = 'i';
 student[0].ages = 16;
 student[0].sex[0] = 'F';
 student[0].sex[1] = 'e';
 student[0].sex[2] = 'm';
 student[0].sex[3] = 'a';
 student[0].sex[4] = 'l';
 student[0].sex[5] = 'e';
 student[0].month = 8;
 student[0].day = 2;
 student[0].year = 1993;
}

All of the "student" is underlined saying expression must be a modifiable lvalue. How can i fix this?

person

typedef struct person 
{ 
char names[20][10]; 
char sex[6][10]; 
int ages[10]; 
int month[10]; 
int day[10]; 
int year[10]; 
} person;

Upvotes: 4

Views: 436

Answers (6)

Jacob
Jacob

Reputation: 34621

Why have you defined names as a 2D array with 10 columns? Do you think you need to do this because you are going to create 10 objects of person?

If that's the case, remember this: when you create the person structure, you just have to define member variables for that one object.

So if your person only has one name, and one sex (which needs 6 characters to define) just use that many because when you create 10 objects of person (person student[10];) you are creating 10 unique copies of the person object! So person[0].name is different from person[1].name.

So let's first define member variables in person for one person:

struct person 
{ 
char names[20]; 
char sex[6]; 
int age; 
int month; 
int day; 
int year; 
};

And then assign characters to the name as you've detailed in your code.

Now, this is not a great idea because names is uninitialized. So student[0].names[4] is undefined (when it should a null character to terminate it). Have you considered using std::string? You have C++ after all!

Also, you'll notice I've changed the definition of person ('struct person ... instead oftypedef .. `) since this is all you need to do in C++.

Changes:

Consider the following person structure:

#include <string>
struct person 
{ 
    std::string person;
    std::string sex;
    int age; 
    int month; 
    int day; 
    int year; 
};

Now, you can assign a string by just:

person student[10];
student[0].name = "Cami";
student[0].sex = "Female";
student[0].age = 16;
student[0].month = 8;
student[0].day = 2;
student[0].year = 1993;

And suppose you want to populate it with a for loop with keyboard input --- it's much easier now:

#include <iostream>
for(int i = 0; i < 10; ++i)
{
 std::cin>>student[i].name;
 std::cin>>student[i].sex;
 std::cin>>student[i].age;
 std::cin>>student[i].month; 
 std::cin>>student[i].day; 
 std::cin>>student[i].year; 
}

Upvotes: 2

John Kugelman
John Kugelman

Reputation: 362037

Array usage

You say you have:

typedef struct person {
    char names[20][10];
    char sex[6][10];
    int ages[10];
    int month[10];
    int day[10];
    int year[10];
} person;

There's no need for the [10]'s. You already have that in the person student[10] declaration, which is the proper place for the [10]. Remove the extraneous arrays:

typedef struct person {
    char name[20];
    char sex[6];
    int age;
    int month;
    int day;
    int year;
} person;

String handling

Also your strings aren't null-terminated. In C strings need to have an extra '\0' character at the end to indicate where the end of the string is. Your name assignment, for example, should be:

student[0].name[0] = 'C';
student[0].name[1] = 'a';
student[0].name[2] = 'm';
student[0].name[3] = 'i';
student[0].name[4] = '\0';

Actually though, there's an easier way to assign to a string than to do it a character at a time. The strcpy function will copy an entire string in one go:

strcpy(student[0].name, "Cami");

Or, the easiest option of all is to use the string class available in C++. It makes string-handling a whole lot easier than the C way of manipulating character arrays. With the string class your code would look like this:

// Modified struct declaration.
typedef struct person {
    std::string name;
    std::string sex;
    int         age;
    // ...
} person;

// Modified assignment.
student[0].name = "Cami";

Upvotes: 9

user195488
user195488

Reputation:

A non-modifiable lvalue is addressable, but not assignable.

Having said that, are you intending for the struct to be a container for a bunch of different names?

What you really need is an array of struct to create a container for persons. (i.e. struct person p[10];)

Upvotes: 1

user3458
user3458

Reputation:

student[0].names[0] has a type of (char *) and cannot be assigned to.

You need to assign to student[0].names[0][0] (or change the definition of names)

Upvotes: 2

Tyler McHenry
Tyler McHenry

Reputation: 76750

You don't need those extra [10]s on each of the fields of the person struct. This makes those fields into arrays themselves. You want, for example, an array of ten persons, each of which has an age. What you have right now is an array of ten persons, each of which has ten ages.

Each element of the student array has its own instance of each of the fields defined in person, so the fields do not themselves have to be arrays.

Upvotes: 1

Itsik
Itsik

Reputation: 3930

  1. If person isn't defined in this file, your are probably not including the proper header file.

  2. Don't forget to add \0 to your strings

  3. If names is a 2d array, shouldnt it be :

    names[0][0] = 'J';
    names[0][1] = 'i';
    names[0][2] = 'm';
    names[0][3] = '\0';

Upvotes: 0

Related Questions