Gettin Lvalue Ошибка в массиве C++

Мне нужно отсортировать имя и фамилию студента, а затем отобразить полностью отсортированные имена на экране, используя структуру в C++. Я пытался, но компилятор показывает Lvalue Required ошибку - в этих строках

tfname = s[i].fname;
s[i].fname = s[j].fname;
s[j].fname = tfname;
tlname = s[i].lname;
s[i].lname = s[j].lname;
s[j].lname = tlname;

Здесь полный код

#include <iostream.h>
#include <conio.h>
#include <stdio.h>
#include <string.h>
struct student
{
    char fname[20];
    char lname[20];
    int id_no;
};
typedef student S;
void main()
{
    S s[25];
    char tfname[20], tlname[20];
    int t;
    for(int i = 0; i<25; i++)
    {
        cout<<"\n Enter Student's first name:";
        cin>>s[i].fname;
        cout<<"\n Enter Student's last name:";
        cin>>s[i].lname;
        cout<<"\n Enter ID NO";
        cin>>s[i].id_no;
    }
    for(i = 0; i<24; i++)
    {
        for(int j = i+1; j<25; j++)
        {
            if(strcmp(s[i].fname, s[j].fname)>0)
            {
                tfname = s[i].fname;
                s[i].fname = s[j].fname;
                s[j].fname = tfname;
                tlname = s[i].lname;
                s[i].lname = s[j].lname;
                s[j].lname = tlname;
                t = s[i].id_no;
                s[i].id_no = s[j].id_no;
                s[j].id_no = t;
            }
            else
            { 
                if(strcmp(s[i].fname, s[j].fname)==0)
                { 
                        if(strcmp(s[i].lname, s[j].lname)>0)       
                     {
                        tfname = s[i].fname;
                        s[i].fname = s[j].fname;
                                s[j].fname = tfname;
                        tlname = s[i].lname;
                                s[i].lname = s[j].lname;
                                s[j].lname = tlname;
                                t = s[i].id_no;
                                s[i].id_no = s[j].id_no;
                                s[j].id_no = t;
                            }
                }
            }
        }
        cout<<"\n\n FIRST NAME \t LASTNAME \t ID NO ";
        for(int i = 0; i<25; i++)
        {
            cout<<"\n"<< c[i].fname<<"\t" <lt; c[i].lname <<="" <
        }
        getch();
    }
}

Пожалуйста, помогите мне, как я могу решить эту ошибку

4 ответа

Решение

Вы не можете поменять строки таким образом. Строки должны быть скопированы с использованием strcpy(),

strcpy(tfname, s[i].fname);
strcpy(s[i].fname, s[j].fname);
strcpy(s[j].fname, tfname);

Другой способ #include <string> и объявить student::fname, student::lname, tfname а также tlname как std::string, Тогда вы можете использовать оператор присваивания, чтобы скопировать их правильно.

Использование std::vector а также std::string вместо массивов. Массивы имеют всевозможные проблемы в таких случаях использования, как ваша. Одна из их больших проблем, если вы не можете обойти или вернуть их как "нормальные" объекты, например, типа int или же double, Их статус "гражданин второго сорта" на языке C++ также вызывает странное поведение, которое вы наблюдали в своей программе.

int GetInt() // works fine
{
    return 123; 
}

void DoSomethingWithDouble(double d) // works fine
{
    // ...
}

char[] GetArray() // does not even compile
{
    // ...
}

void DoSomethingWithArray(int array[]) // does not work as expected, either
{
    // ...
}

Вот почему в C++ мы используем std::string, std::vector или другие сложные классы, которые позволяют нам обрабатывать строки или коллекции точно (или почти точно), как простые (так называемые "примитивные") типы, такие как int или же double:

std::string GetString()
{
    // ...
}

void DoSomethingWithString(std::string const &s) // you should use const & here because
                                                 // it does not cost you anything and may
                                                 // increase speed of your program
{
    // ...
}

std::vector<int> GetInts()
{
    // ...
}

void DoSomethingWithInts(std::vector<int> const &v) // you should use const & here because
                                                    // it does not cost you anything and 
                                                    // may increase speed of your program
{
    // ...
}

Вы даже можете назначить их совершенно безопасно и без специального синтаксиса:

std::vector<int> v1;
std::vector<int> v2;
v1 = v2;

std::string s1;
std::string s2;
s1 = s2;

И вы можете создавать строковые векторы, и они будут вести себя точно так, как вы ожидаете:

std::vector<std::string> string_vector;
string_vector.push_back("abc");
string_vector[0][0] = 'A';
std::cout << string_vector[0]; // prints "Abc"

Массивы имеют свое место в C++, но не для начинающих и не для программирования высокого уровня.

Массивы не имеют оператора присваивания. Вместо этого вы должны скопировать элементы из одного массива в другой. Так как в вашем коде массивы имеют тип char и предназначены для хранения строк, вы должны использовать стандартную функцию C std::strcpy объявлено в заголовке <cstring>

Так что этот фрагмент кода

tfname = s[i].fname;
s[i].fname = s[j].fname;
s[j].fname = tfname;
tlname = s[i].lname;
s[i].lname = s[j].lname;
s[j].lname = tlname;

будет выглядеть следующим образом

std::strcpy( tfname, s[i].fname );
std::strcpy( s[i].fname,s[j].fname );
std::strcpy( s[j].fname, tfname );
std::strcpy( tlname, s[i].lname );
std::strcpy( s[i].lname, s[j].lname );
std::strcpy( s[j].lname, tlname );

Другой подход заключается в использовании стандартного класса std::array. В этом случае вы можете использовать оператор присваивания. Например

#include <array>
//...
struct student
{

    std::array<char, 20> fname;
    std::array<char, 20> lname;
    int id_no;
};

И, наконец, вы можете использовать класс std::string вместо сырых массивов символов.

Если описание вашей задачи содержит C++, struct, а также sortчто насчет этой версии?

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

struct Student
{
    std::string fname;
    std::string lname;
    int id_no;
};

/// checks order after comparing (fname, then lname) 
/// (usable with std::sort)
bool operator<(const Student& lhs, const Student& rhs)
{
    int c=lhs.fname.compare(rhs.fname);
    if (c < 0) {
        return true;
    } else if (c > 0) {
        return false;
    }
    return lhs.lname < rhs.lname;
}

/// write student to standard output stream
/// (usable with std::for_each)
void out_student(const Student& s)
{
    std::cout << s.fname << " " << s.lname << " " << s.id_no << std::endl;
}


int main() 
{
    std::list<Student> students;

    // entering students left out

    std::sort(students.begin(), students.end());
    std::for_each(students.begin(), students.end(), out_student);
    return 0;
}
Другие вопросы по тегам