std::vector Struct Student example - c++

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
struct StudentDataTypes
{
std::string name{};
int grade{};
};
int main()
{
//Ask for Class_Size
int Class_Size{};
std::cout << "How big is the class?" << '\n';
std::cin >> Class_Size;
//Syntax format
//std::vector<T> array(size);
//Intialize a vector for the students called Vector_Student
//T links to the struct StudentDataTypes
//size is the Class_Size.
std::vector<StudentDataTypes> Vector_Student(Class_Size);
//Print Class Size
std::cout << "There are " << Class_Size << " students." << '\n';
//Get the Userinputs for the Class
for (int i = 0; i < Class_Size; ++i)
{
std::cout << "Please input the name of Student #" << i + 1 << '\n';
std::cin >> Vector_Student[i].name;
std::cout << "Please input the grade of Student #" << i + 1 << '\n';
std::cin >> Vector_Student[i].grade;
}
//Sort
std::sort(Vector_Student.begin(), Vector_Student.end());
//Print the required output
for (int j = 0; j < Class_Size; ++j)
{
std::cout
<< Vector_Student[j].name
<< " got a grade of "
<< Vector_Student[j].grade << '\n';
}
return 0;
}
I have an issue with a Vector Struct tutorial.
I'm using Visual Studio 2019 and there's a peculiar scenario where the compiler doesn't give me any warning at all. If I debug it, the first warning appears on line 1544, way out of bounds. The above code will actually sort of compile, run and crash.
I know the issue lies in the sorting but I can't figure it out.

std::sort requires you to implement operator< for your datatype. Here in this case adding following definition in your class will get your code to compile
bool operator<(const StudentDataTypes& that) {
return this->grade < that.grade;
}
Update:
Alternatively as sugested by Casey, we can use custom sort comparator. Here is the sample code for the same.
std::sort(Vector_Student.begin(), Vector_Student.end(), [](const StudentDataTypes& a, const StudentDataTypes&b) { return a.grade < b.grade; });

Here is the answer. I'm posting it in the answers for how to sort a vector-struct.
Step 1:
bool compareTwoStudents(StudentDataTypes a, StudentDataTypes b) {
if (a.grade != b.grade)
return a.grade > b.grade;
return a.grade==b.grade;
}
Step 2:
std::sort(Vector_Student.begin(), Vector_Student.end(),compareTwoStudents);

Related

Sorting array of objects in c++

I'm a newbie and this is my first question. So I am working for a task organizer and I want to organize list of tasks by their "urgency" value. Here is my code:
#include <iostream>
#include <math.h>
#include <vector>
#include <stdlib.h>
#include <list>
using namespace std;
struct Task {
public:
string name;
float deadline, estimated;
int urgency;
int getUrgency() {
urgency = ceil(deadline - estimated);
return urgency;
}
};
void newTask(Task task[], int n1) {
for (int i = 0; i < n1; i++)
{
system("cls");
cout << "Input task name: ";
cin >> task[i].name;
cout << "Input task deadline (in hours): ";
cin >> task[i].deadline;
cout << "Input task estimated work time (in hours): ";
cin >> task[i].estimated;
}
}
void printAll(Task task[], int n1) {
system("cls");
cout << "Name\tDeadline\tEstimated\tUrgency\n";
for (int i = 0; i < n1; i++)
{
cout << task[i].name << "\t" << task[i].deadline << "\t\t" << task[i].estimated << "\t\t" << task[i].getUrgency() << endl;
}
}
int main() {
int n;
cout << "How many work do you have? ";
cin >> n;
//Create number of object based on input n
std::vector<Task> p(n);
newTask(p.data(), n);
std::list<Task> taskList;
printAll(p.data(), n);
cin.ignore();
return 0;
}
I want to add a function that sorts the list of tasks by their "urgency" value. What kind of function should I use?
In your case you can use the std::sort function, defined in <algorithm> header, on the p vector defining a custom compare function:
std::sort (p.begin(), p.end(), sortTaskByUrgency);
where sortTaskByUrgency() is defined as:
bool sortTaskByUrgency(const Task& lhs, const Task& rhs)
{
return lhs.getUrgency() < rhs.getUrgency();
}
Using the above function in your sample code getUrgency() must be const:
int getUrgency() const { return ceil(deadline - estimated); }
removing useless int urgency public member.
I would try using std::sort. It will sort in place any iterable object (array, vector, etc...). A common std::sort function call has the following arguments: The first argument is an iterator/pointer to the beginning of the collection, the second argument is an iterator/pointer to the end of that same collection, and the third argument is a function callback that determines how the data is sorted. You can see an example implementation here

How to print certain elements from vector?

I am trying to print out whatever is necessary from my program. What it does is it takes a long list from a text file and sort it based on first choice and GPA and put it into a vector. I manage to sort by First choice and GPA however how can I remove whatever output that isn't necessary?
This is an example of my Txt File (The sequence of each line is 1st choice, 2nd choice, 3rd choice, GPA, Name):
CC,DR,TP,3.8,AlexKong
SN,SM,TP,4,MarcusTan
DR,TP,SC,3.6,AstaGoodwin
SC,TP,DR,2.8,MalcumYeo
SN,SM,TP,3.7,DavidLim
SN,SM,TP,3.2,SebastianHo
SC,TP,DR,4,PranjitSingh
DR,TP,SC,3.7,JacobMa
and so on...
This is my output now (it is a long vector):
TP,DR,SC,4,SitiZakariah
TP,DR,SC,3.9,MuttuSami
TP,DR,SC,3.5,SabrinaEster
TP,DR,SC,3,KarimIlham
TP,DR,SC,3,AndryHritik
SN,SM,TP,4,MarcusTan
SN,SM,TP,3.8,MarcusOng
SN,SM,TP,3.7,DavidLim
SN,SM,TP,3.4,MollyLau
SN,SM,TP,3.2,SebastianHo
SN,SM,TP,3.2,NurAfiqah
SN,SM,TP,2.4,TanXiWei
SC,TP,DR,4,SallyYeo
SC,TP,DR,4,PranjitSingh
SC,TP,DR,3.6,RanjitSing
SC,TP,DR,2.8,MalcumYeo
SC,TP,DR,2.8,AbdulHalim
SC,TP,DR,2.7,AlifAziz
DR,TP,SC,3.9,SitiAliyah
DR,TP,SC,3.9,LindaChan
DR,TP,SC,3.8,SohLeeHoon
DR,TP,SC,3.7,PrithikaSari
DR,TP,SC,3.7,NurAzizah
DR,TP,SC,3.7,JacobMa
DR,TP,SC,3.6,AstaGoodwin
CC,DR,TP,3.9,MuruArun
CC,DR,TP,3.8,AlexKong
CC,DR,TP,3.7,DamianKoh
CC,DR,TP,3.3,MattWiliiams
CC,DR,TP,3.3,IrfanMuhaimin
And this is the output that I need (Basically students with CC as their 1st choice without displaying the 3 options):
3.9,MuruArun
3.8,AlexKong
3.7,DamianKoh
3.3,MattWiliiams
3.3,IrfanMuhaimin
This is my program.
#include <iostream>
#include <vector>
#include <fstream>
#include <string>
#include <algorithm>
using namespace std;
struct greater
{
template<class T>
bool operator()(T const &a, T const &b) const { return a > b; }
};
void main()
{
vector<string> v;
int p = 0;
ifstream File;
File.open("DSA.txt");
if (!File.is_open()) return;
string First;
cout << "Round 1:\n";
while (File >> First)
{
v.push_back(First);
p++;
}
for (int i = 0; i < v.size(); i++)
{
sort(v.begin(), v.end(), greater());
cout << v[i] << endl;
}
}
your last for loop:
for (int i = 0; i < v.size(); i++)
{
sort(v.begin(), v.end(), greater());
cout << v[i].substr(9) << endl;
}
EDIT:
If you want to only display ones with CC as 1st choice you can add if statement to your loop:
for (int i = 0; i < v.size(); i++)
{
if (v[i].substr(0,2) != "CC") continue;
cout << v[i].substr(9) << endl;
}
Also, I noticed another problem in your code. You should not sort the vector at every iteration. You should do it only once before the loop:
sort(v.begin(), v.end(), greater());
for (int i = 0; i < v.size(); i++)
{
if (v[i].substr(0,2) != "CC") continue;
cout << v[i].substr(9) << endl;
}
as I propose in the comment,
since the data is well defined as a structure, you can interpret semantically each row and filter according to that: here is what am talking about
int main()
{
std::vector<std::string> v;
std::string r = "CC,DR,TP,3.9,MuruArun";
std::string delimiter = ",";
std::string token = r.substr(0, r.find(delimiter));
if(token == ??)// compare to what ever you want
{
v.emplace_back(r);
}
cout << "token: " << token << endl;
cout << v.size() << endl;
return 0;
}

Vector of Objects - C++. No operator "<<" matches these operands, Error

I am a beginner in programming.I have a problem. I am trying to code the Enigma machine. I have two classes. One for Enigma, one for rotors. Rotors are small parts of the enigma machine, that doesn't matter for the problem. My problem is the error. I cannot cout, the function cout << rotors[0].GetRotor(); which should return my vector of integers. I have no idea why is that. I don't need that to my program, but I'm not sure if my adding rotor to enigma void AddRotor(Rotor rotor) { rotors.push_back(rotor); }function, called in "TakeRotors" function, works right. In my opinion, it should work well, but I can't check it. Debugger, unfortunately, doesn't show any values of vector<Rotor> rotors; permutation so I am not sure :( Any help would be great. Thank You.
Here's my full, needed code :)
#include <iostream>
#include <vector>
using namespace std;
class Rotor {
public:
vector <int> permutation;
int position;
Rotor(vector<int> permutation) {
position = 0;
permutation;
}
vector<int> GetRotor() const {
return permutation;
}
};
class Enigma {
public:
vector<Rotor> rotors;
void AddRotor(Rotor rotor) {
rotors.push_back(rotor);
}
void PrintRotor(const vector<Rotor>& rotors) {
cout << rotors[0].GetRotor(); // Error right here
cout << rotors[0].position;
}
void setupRotor(int index) {
Rotor rotor = rotors[index];
}
void MoveRotor(int index) {
rotors[index].position++;
cout << "Before" << endl;
// cout << rotors[index].permutation.data << ' ';
Enigma::PrintRotor(rotors);
rotate(rotors[index].permutation.begin(), rotors[index].permutation.begin() + rotors[index].permutation.size(), rotors[index].permutation.end());
cout << "After" << endl;
Enigma::PrintRotor(rotors);
}
};
vector<int> take_numbers(int number) {
vector<int> numbers;
for (int i = 0; i < number; i++) {
int number;
cin >> number;
numbers.push_back(number);
}
return numbers;
}
void take_rotors(int number_letters, Enigma* enigma) {
int numberOfRotors;
// int numberOfNotch, positionOfNotch;
cout << "Give number of Rotors" << endl;
cin >> numberOfRotors;
for (int i=0; i < numberOfRotors; i++) {
vector<int> permutation = take_numbers(number_letters);
Rotor Rotor(permutation);
enigma->AddRotor(Rotor); // I am not sure if it adds Rotors fine.
}
}
int main()
{
Enigma enigma;
int number_letters, move_rotor;
cout << "Give number of letters in alphabet" << endl;
cin >> number_letters;
take_rotors(number_letters, &enigma);
// take_reflectors(number_letters, &enigma);
cout << "Which rotor do you want to move (index)" << endl;
cin >> move_rotor;
enigma.MoveRotor(move_rotor);
return 0;
}
There is no operator<<(std::ostream&,const std::vector<int>&) if you want it you need to supply your own. However, overloading operators for types you don't own is not recommended, so I would rather write a function:
void print_vector(std::ostream& out, const std::vector<int>& vect) {
for (int i : vect) {
out << i << '\n';
}
}
That you can call like this
print_vector(std::cout, rotors[0].GetRotor());
Alternatively you can supply an overload for << that prints all the Rotor:
std::ostream& operator<<(std::ostream&,const Rotor& rotor) {
out << rotor.position;
for (auto& i : rotor.GetRotor()) {
out << i;
}
// modify and add more to your likings
return out;
}
Once you have that you can also provide an overload to print a vector of rotors that you can use in Enigma::PrintRotor (which currently only prints the first element of the vector):
std::ostream& operator<<(std::ostream& out,const std::vector<Rotor>& rotors) {
for (const auto& r : rotors) {
out << r << '\n';
}
return out;
}
PS your naming is a little confusing. A Rotor has a GetRotor which returns permutations !?! I strongly suggest to use better names. If I have Rotor r; then r is the Rotor and it is not obvious what a GetRotor will do. Maybe rename it to GetPermutations?

Access to the struct elements. Is it possible to access like a vector?

I have the following example (simplified) using a struct:
#include <iostream>
#include <algorithm>
#include <time.h>
using namespace std;
struct s_str
{
int a=1,b=2,c=3;
};
int main(void)
{
s_str str;
int sel;
srand(time(NULL)); //initialize random seed
sel = rand() % (3); //generate a random number between 0 and 2
cout << "sel: " << sel << endl;
cout << "str: " << str.??? << endl;//I was wondering to output a, b or c
return 0; //depending whether sel=0,1,2respectively.
}
When the struct "str" is defined, we can access to each element by using the opertor "." followed by the name of the element. For instance "str.c" will give us the number 3.
However in this example we don't know the element of "str" to output when programing because it's randomly selected by sel.
I don't know how to output "str.???" from sel number, that is, str.a if sel=0, str.b if sel=1, and str.c if sel=3.
I tried something like "str.[sel]", but it didn't work. Can you help me?
PD: I don't want to bother too much, but how to solve the same problem but now supposing that a,b and c have different variable type. For example:
int a=1,b=2;
string c="hola";
I tried to do it with two operators, but it didn't compile because they were overloaded.
As mentioned you can't do this without providing a certain mapping and indexing operator. The following should work well:
struct s_str
{
int a=1,b=2,c=3;
int& operator[](int index) {
switch(index) {
case 0:
return a;
case 1:
return b;
case 2:
return c;
default:
throw std::out_of_range("s_str: Index out of range.");
break;
}
}
};
int main() {
s_str s;
cout << s[0] << ", " << s[1] << ", " << s[2] << endl;
// cout << s[42] << endl; // Uncomment to see it fail.
return 0;
}
In general, no.
If the only distinguishing feature of the elements of the struct is their index, define a vector or array in the struct.
If you sometimes want to refer to the elements by name and sometimes by position, define an operator []( int ) for the struct.
Te easiest way, if you have only a couple of ints in your structure is:
struct s_str
{
int a = 1, b = 2, c = 3;
int& operator[] (size_t t) {
assert(t<3); // assumption for the following to return a meaningful value
return (t == 0 ? a : (t == 1 ? b : c));
}
};
You'd access with
cout << "str: " << str[sel] << endl;
and you could even use int to assign, because it's by reference:
str[sel] = 9;
cout << "a,b,c=" << str.a << "," << str.b << "," << str.c << endl;

Print struct element of vector

I am learning about vector. I try to implement a code that print the struct element of a vector as displayed below. Many resources in the internet only teach me a simple vector. I get stcuk in expression when to print it. However, any suggestion for improving the quality and elegance of the code is open, although the change is fundamental (in struct or looping).
Thank you very much.
#include "stdafx.h"
#include <iostream>
#include <vector>
using namespace std;
typedef struct _student {
string name;
int age;
vector <string> subject;
}student;
int _tmain(int argc, _TCHAR* argv[])
{
vector <student> x; //assmue at this point we do not know the number of students
student y;
//and I want to insert new information
y.name ="John";
y.age =9;
y.subject.push_back("biology");
y.subject.push_back("math");
y.subject.push_back("art");
x.push_back(y);
//get new information again
//and I want to insert new information
y.name ="Bon";
y.age =12;
y.subject.push_back("history");
y.subject.push_back("physics");
x.push_back(y);
// then I want display all data
cout << "myvector contains:";
for (int i=0; i<x.size(); i++)
{
cout << "Student # " << i+1 <<endl;
cout << " name : " << x.at(i).name <<endl; //Reference in the internet only display a simple vector --
cout << " age : " << x.at(i).age <<endl; //I get stuck to express this and next part
cout <<" Subject : ";
for (int j =0; j < x.at(i).subject.size(); j++)
{
cout << x.at(i).subject.at(j);
}
cout << endl;
cin.get();
return 0;
}
Here, added some comments and stuff. Not sure if this is what you were looking for, but here it is.
#include "stdafx.h"
#include <iostream>
#include <vector>
#include <string> // string would be welcome here!
struct _student // the typedef thing is not necessary in C++
{
std::string name; // i find this "using namespace ..." thing a bad habit, it can make code harder to read
int age;
std::vector<std::string> subject;
};
int _tmain(int argc, _TCHAR* argv[])
{
std::vector<student> x;
student y;
size_t size; // calling vector.size() every iterations is a bad idea, performance-wise
size_t size_subj; // same
y.name = "John";
y.age = 9;
y.subject.push_back("biology");
y.subject.push_back("math");
y.subject.push_back("art");
x.push_back(y);
y.name = "Bon";
y.age = 12;
y.subject.clear(); // clear subjects of the other student
y.subject.push_back("history");
y.subject.push_back("physics");
x.push_back(y);
std::cout << "my vector contains:";
for (int i = 0, size = x.size(); i < size; ++i)
{
size_subj = x[i].subject.size();
// I prefer using operator[] when I'm sure nothing can go wrong
std::cout << "Student # " << i + 1 <<endl;
std::cout << "\tname: " << x[i].name <<endl;
std::cout << "\tage: " << x[i].age <<endl;
std::cout << "\tSubjects: ";
for (int j = 0; j < size_subj; ++j)
std::cout << x[i].subject[j];
std::cout << endl;
}
return 0;
}
Finally, using a std::vector< std::string* > or std::vector< std::string& > could be a better idea performance-wise, depending on what you are planning to do with it later.
There is no real question here, so I'm assuming you are asking for "code review"
The "neat" way is of course to create an operator<< that takes your inner structure.
Aside from that, you may want to look at using iterators to walk your way through your vector - that way, you should be able to change your vector for any other container type without having to change the loop(s) that print things.
Use longer variable names than x and y for your vector and temporary student.
Use setw to print fields at the same width every time.
I'm sure there are plenty of other suggestions too.
As the comments point to, it turns out that you're not including the string header file.