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;
}