Question

I need to sort the first name and then last name of of student and then display the fully sorted names on screen using structure in C++. I tried but compiler showing Lvalue Required error - in these line

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;

Here the complete code

#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();
    }
}

Kindly help me how can I solve this error

Was it helpful?

Solution 2

You cannot swap strings this way. Strings should be copied using strcpy().

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

Another way is #include <string> and declare student::fname, student::lname, tfname and tlname as std::string. Then you could use assignment operator to copy them correctly.

OTHER TIPS

Use std::vector and std::string instead of arrays. Arrays have all kinds of problems in use cases such as yours. One of their big problems if that you cannot pass around or return them like "normal" objects, e.g. of type int or double. Their "second-class citizen" status in the C++ language also causes the strange behaviour you've observed in your program.

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
{
    // ...
}

This is why in C++, we use std::string, std::vector or other sophisticated classes which allow us to treat strings or collections exactly (or almost exactly) like simple (so-called "primitive") types such as int or 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
{
    // ...
}

You can even assign them completely safely and with no special syntax:

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

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

And you can create string vectors, and they will behave exactly as you expect:

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

Arrays do have their place in C++, but not for beginners and not in high-level programming.

Arrays has no the assignment operator. Instead of it you have to copy elements from one array to another. As in your code arrays has type char and designed to store strings you should use standard C function std::strcpy declared in header <cstring>

So this code snippet

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;

will look the following way

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

The other approach is to use standard class std::array. In this case you may use the assignment operator. For example

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

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

And at last you could use class std::string instead of raw character arrays.

If your task description contains C++, struct, and sort, what about this version?

#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;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top