I have some code below that will take some names and ages and do some stuff with them. Eventually it will print them out. I need to change my print() function with a global operator<<. I saw on a different forum that <<operator takes two parameters, but when I try it I get a "too many parameters for << operation error. Is there something I am doing wrong? I am newer to C++ and I really do not get the point of operator overloading.
#include <iostream>;
#include <string>;
#include <vector>;
#include <string.h>;
#include <fstream>;
#include <algorithm>;
using namespace::std;
class Name_Pairs{
vector<string> names;
vector<double> ages;
public:
void read_Names(/*string file*/){
ifstream stream;
string name;
//Open new file
stream.open("names.txt");
//Read file
while(getline(stream, name)){
//Push
names.push_back(name);
}
//Close
stream.close();
}
void read_Ages(){
double age;
//Prompt user for each age
for(int x = 0; x < names.size(); x++)
{
cout << "How old is " + names[x] + "? ";
cin >> age;
cout<<endl;
//Push
ages.push_back(age);
}
}
bool sortNames(){
int size = names.size();
string tName;
//Somethine went wrong
if(size < 1) return false;
//Temp
vector<string> temp = names;
vector<double> tempA = ages;
//Sort Names
sort(names.begin(), names.end());
//High on performance, but ok for small amounts of data
for (int x = 0; x < size; x++){
tName = names[x];
for (int y = 0; y < size; y++){
//If the names are the same, then swap
if (temp[y] == names[x]){
ages[x] = tempA[y];
}
}
}
}
void print(){
for(int x = 0; x < names.size(); x++){
cout << names[x] << " " << ages[x] << endl;
}
}
ostream& operator<<(ostream& out, int x){
return out << names[x] << " " << ages[x] <<endl;
}
};
You are overloading << operator as a member function, therefore, the first parameter is implicitly the calling object.
You should either overload it as friend function or as a free function. For example:
overloading as friend function.
friend ostream& operator<<(ostream& out, int x){
out << names[x] << " " << ages[x] <<endl;
return out;
}
However, the canonical way is to overload it as free function. You can find very good information from this post: C++ operator overloading
declare operator overloading function as friend.
friend ostream& operator<<(ostream& out, int x)
{
out << names[x] << " " << ages[x] <<endl;
return out;
}
Related
In the following code I made a clone of an for_each function defined in <algorithm> (I believe). The only problem is for the third argument which is a void function I made, I get the no matching function for call....unresolved overloaded function type. Could someone shed some light on this matter?
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
void fill(int& n) { //The custom made function, a simple rewrite,
if (n < 100) //which is why I passed an int reference
n = 100;
}
template <class Iterator, class Function> //Clone for_each
void clone_for_each(Iterator first, Iterator last, Function f) {
while( first != last) {
f(*first);
first++;
}
}
int main (int argc, char const* argv[])
{
//Just inputing data and printing it out
//This part is fine up until...
int n;
cout << "Unesite broj vrsta artikala: ";
cin >> n;
vector<string> names;
vector<int> quantity;
cout << "Unesite naziv artikla potom njegovu kolicinu: " << endl;
for (int i = 0; i < n; i++) {
string name;
int amount;
cout << "Unesite naziv: ";
cin >> name;
cout << endl;
cout << "Unesite kolicinu: ";
cin >> amount;
cout << endl;
names.push_back(name);
quantity.push_back(amount);
}
cout << "Raspolozivi artikli: " << endl;
vector<string>::iterator itNames = names.begin();
vector<int>::iterator itQuantity = quantity.begin();
for(itNames, itQuantity; itNames != names.end(), itQuantity != quantity.end(); itNames++, itQuantity++ )
cout << *itNames << " " << *itQuantity << endl;
cout << "Artikli nakon dopune: " << endl;
//right here, which is where I called for clone_for_each
clone_for_each(quantity.begin(), quantity.end(), fill);
return 0;
}
Since you're using namespace std, fill from
clone_for_each(quantity.begin(), quantity.end(), fill);
is supposed to be std::fill() from <algorithm>and don't fit to clone_for_each().
See Why using namespace std is considered harmful?
I wrote following code for finding maximum score:
#include "stdafx.h"
#include <iostream>
#include<vector>
#include <string>
#include <algorithm>
constexpr int MAX_STUDENTS = 3;
using namespace std;
class student{
public:
void vrod();
void dis();
int stno;
int score
int i;
string name;
};
void student::vrod(){
cout << "name=";
cin >> name;
cout << "stno=";
cin >> stno;
cout << "score=";
cin >> score;
}
void student::dis(){
cout << "name=" << name << "\n" << "stno=" << stno << "\n" << "score=" << score<< "\n";
cin.get();
}
int main(){
int l;
vector<student> my_vector;
for(int i = 0; i < n; i++)
{
student new_student;
cout << "Number: ";
cin >> new_student.stno;
cout << "Score: ";
cin >> new_student.score;
cout << "Name: ";
cin >> new_student.name;
my_vector.push_back(new_student);
}
l=0;
for(int i = 0; i < MAX_STUDENTS; ++i)
{
if (my_vector[i].score>l) {
l=my_vector[i].score;
}
}
cout << "max=" << l;
cin.get();
cin.get();
}
I used common ways to find maximum amount, but how can I use vector? how about algorithm? I found that there is a function which is max in algorithm, but it needs two argument and I could not use that for this code. Thanks for your tips beforehand.
You can use std::max_element and a lambda expression for the comparator:
auto l = std::max_element(my_vector.cbegin(), my_vector.cend(),
[](const student& s1, const student& s2) {
return s1.score < s2.score;
});
l is a const iterator, to output maximum score you need to check if it did return anything and output the score
if(l != my_vector.cend()){
cout << "max=" << l->score;
}
Also a few tips:
Don't do
#define n 3
This is C++, and giving meaningful variable names is a good practice you can use
constexpr int MAX_STUDENTS = 3;
You aren't using student::vrod() and student:dis() methods anywhere
UPDATE (OP request):
Lambda expressions is a more convenient way to write functions for various uses. Lambda in this case
[](const student& s1, const student& s2) {
return s1.score < s2.score;
}
is a more convenient way to write a comparator function, it can also be implemented with a functor
struct compare_students {
bool operator() (const student& s1, const student& s2) const {
return s1.score < s2.score;
}
};
auto l = std::max_element(my_vector.cbegin(), my_vector.cend(), compare_students());
For more information please consider searching for C++ lambda tutorials and examples.
int max_score = std::max_element(
my_vector.begin(),
my_vector.end(),
[] (student const& lhs, student const& rhs){
return lhs.score < rhs.score;
}
)->score;
is one way. Note the use of the lambda function acting as the comparator.
Pre C++11, you'd use a function object to model the comparator.
Recently in my c++ class we have learned about pointers and classes.
I'm trying to make a program that has a class Student, which we will point to give each student a name and test score.
After entering both name and test score, they are sorted and then listed in order of highest to lowest.
I believe all my syntax to be correct, however I am still learning. The problem I am having is that the first time I use my class I get an uninitialized local variable error, any help on how to fix this?
#include "stdafx.h"
#include <iostream>
#include <string>
#include <array>
using namespace std;
class Student {
private:
double score;
string name;
public:
void setScore(double a) {
score = a;
}
double getScore() {
return score;
}
void setName(string b) {
name = b;
}
string getName() {
return name;
}
};
void sorting(Student*, int);
int main()
{
Student *students;
string name;
int score;
int *count;
count = new int;
cout << "How many students? ";
cin >> *count;
while (*count <= 0) {
cout << "ERROR: The number of students must be greater than 0.\n";
cin >> *count;
}
for (int i = 0; i < *count; i++) {
cout << "Please enter the students name: ";
cin >> name;
students[i].setName(name);
cout << "Please enter " << students[i].getName() << "'s score: ";
cin >> score;
while (score < 0) {
cout << "ERROR: Score must be a positive number.\n";
cin >> score;
}
students[i].setScore(score);
}
sorting(students, *count);
for (int i = 0; i < *count; i++) {
cout << students[i].getName() << ": " << students[i].getScore() << endl;
}
system("PAUSE");
return 0;
}
void sorting(Student *s, int size) {
for (int i = 0; i < size; i++) {
for (int j = i; j < size; j++) {
if (s[j].getScore() > s[(j + 1)].getScore()) {
int tmp = s[(j + 1)].getScore();
s[(j + 1)].setScore(s[j].getScore());
s[j].setScore(tmp);
string tmp1 = s[(j + 1)].getName();
s[(j + 1)].setName(s[j].getName());
s[j].setName(tmp1);
}
}
}
}
First off, your Student class can be simplified to this:
struct Student {
double score;
std::string name;
};
Because the accessors do absolutely nothing. I've also added the std:: prefix because using namespace std is considered a bad practice.
Now, instead of using the pointer to store the students, include vector and use that:
std::cout << "How many students? ";
int count;
std::cin >> count;
std::vector<Student> students(count);
The loading routine can also be simplified given the absence of accesors:
for (auto& student : students) {
std::cout << "Please enter the students name: ";
std::cin >> student.name;
std::cout << "Please enter " << student.name << "'s score: ";
std::cin >> student.score;
while (score < 0) {
std::cout << "ERROR: Score must be a positive number.\n";
std::cin >> student.score;
}
}
And actually once you have that, you could just put it in istream& operator>>(istream&, Student&) and reduce it to:
std::copy_n(std::istream_iterator<Student>(std::cin), students.size(), students.begin());
No need now for temporary variables anymore (and even if you want to use them, they should be defined just before the use, so inside of the loop).
The last thing is your sorting routine. First off, there's std::sort that you can use instead if you simply provide a comparator:
std::sort(
begin(students),
end(students),
[](Student const& a, Student const& b) { return b.score < a.score; }
);
If you insist on writing the sorting routine yourself, at least use std::swap.
I need to merge two text files and have them sort by "lastName" on a third outputted file. My code is below, it is outputting gibberish, all on one line. I understand my overload may be stupid, any help is appreciated.
//header
#include <fstream>
#include <string>
#include <iostream>
using namespace std;
struct mergedList {
string firstName;
string lastName;
float gpa;
int hours;
};
ostream& operator << (ostream& os, mergedList A) {
os << A.firstName << "\t" << A.lastName << "\t" << A.gpa << "\t" << A.hours;
return os;
}
istream& operator >> (istream& is, mergedList& A) {
is >> A.firstName >> A.lastName >> A.gpa >> A.hours;
return is;
}
void swap(mergedList D1[], int i, int j);
void sort(mergedList D1[], int size);
int main() {
ifstream indata;
ifstream indata2;
ofstream outdata;
indata.open("merge1.txt");
indata2.open("merge2.txt");
outdata.open("merged.txt");
//begin sentinel controlled loop for both lists
mergedList D1[100];
int index = 0;
indata >> D1[index];
while (!indata.eof()) {
index++;
indata >> D1[index];
}
sort(D1, index);
mergedList D2[100];
int index2 = 0;
indata2 >> D2[index2];
while (!indata2.eof()) {
index2++;
indata2 >> D2[index2];
}
sort(D2, index); {
int i = 0, j = 0;
while ((i < index) && (j < index2)) if (D1[i].lastName < D2[j].lastName) {
outdata << D1[i];
i++;
indata >> D1[i];
} else {
outdata << D2[j];
j++;
indata2 >> D2[j];
}
}
indata.close();
indata2.close();
outdata.close();
return 0;
}
void swap(mergedList D1[], int i, int j) {
mergedList temp;
temp = D1[i];
D1[i] = D1[j];
D1[j] = temp;
return;
}
void sort(mergedList D1[], int size) {
for (int p = 1; p < size; p++) {
for (int c = 0; c < size - p; c++) {
if (D1[c].lastName > D1[c + 1].lastName) swap(D1, c, c + 1);
}
}
return;
}
Here is some code. I have tried to explain as much as I can. If you are using C++ you should try to take advantage of the containers and algorithms that are already available for you.
struct mergedList
{
string firstName;
string lastName;
float gpa;
int hours;
};
ostream& operator <<(ostream& os, mergedList A)
{
os << A.firstName << "\t" << A.lastName << "\t" << A.gpa << "\t" << A.hours;
return os;
}
istream& operator >>(istream& is, mergedList& A)
{
is >> A.firstName >> A.lastName >> A.gpa >> A.hours;
return is;
}
// We use this to compare two MergedList structs. i.e. by first name
// http://www.cplusplus.com/reference/algorithm/sort/ for an example
struct my_sorter {
bool operator() (mergedList one, mergedList two) { return one.firstName < two.firstName ; }
};
int main()
{
ifstream indata;
ifstream indata2;
ofstream outdata;
indata.open("merged.txt");
indata2.open("merged2.txt");
outdata.open("merged.txt");
// This can be a vector. No need for array here.
vector<mergedList> D1;
int index=0, index2 = 0;
mergedList tmp;
// You can read from streams like this if the data is formatted.
while (indata >> tmp)
{
D1.push_back(tmp);
index++; // Maybe you need this??
}
// Read the second file in to the same vector.
// You don't need another one.
while (indata2 >> tmp)
{
D1.push_back(tmp);
index2++;
}
cout << "Before sorting" << endl;
copy(D1.begin(), D1.end(), ostream_iterator<mergedList>(cout, "\n"));
// Sort the vector using the std::sort algorithm.
// http://www.cplusplus.com/reference/algorithm/sort/ for an example
sort(D1.begin(), D1.end(), my_sorter());
cout << "After sorting" << endl;
copy(D1.begin(), D1.end(), ostream_iterator<mergedList>(cout, "\n"));
// Write the sorted list to the output file
copy(D1.begin(), D1.end(), ostream_iterator<mergedList>(outdata, "\n"));
indata.close();
indata2.close();
outdata.close();
return 0;
}
If optimization is an issue for you, I suggest you use STL containers as the proper sort methods are implemented. Do not use static arrays if your code should work on every given input file. I might also add that you can first merge the two files and then sort the third one.
I posted earlier for the first time and was able to almost complete this assignment. The program isn't giving an error, but I'm getting undesired results. The output appears to be outputting the array address instead of the data I input. Or at least I think it is based on my very very limited knowledge. Can anyone help guide me in how to fix this? I've been working on this all day and at this hour, I think I'm ready to throw in the towel. Any advice is greatly appreciated, thanks!
// Amanda
// SoccerPlayer.cpp : main project file.
// October 6, 2012
/* a. Design a SoccerPlayer class that includes three integer fields: a player's jersey number,
number of goals, and number of assists. Overload extraction and insertion operators for the class.
b. Include an operation>() function for the class. One SoccerPlayer is considered greater
than another if the sum of goals plus assists is greater.
c. Create an array of 11 SoccerPlayers, then use the > operator to find the player who has the
greatest goals plus assists.*/
#include "stdafx.h"
#include<conio.h>
#include<iostream>
#include<string>
using namespace std;
class SoccerPlayer
{
friend std::ostream& operator<<(std::ostream&, const SoccerPlayer&);
friend istream& operator>>(istream&, SoccerPlayer&);
private:
int jerseyNum;
int numGoals;
int numAssists;
public:
SoccerPlayer(int, int, int);
int score;
int operator>(SoccerPlayer&);
void DisplayStar();
};
SoccerPlayer::SoccerPlayer(int jersey = 0, int goal = 0, int assist = 0)
{
jerseyNum = jersey;
numGoals = goal;
numAssists = assist;
}
void SoccerPlayer::DisplayStar()
{
cout<<"Player Number: "<< jerseyNum <<endl;
cout<<"Goals Scored: "<< numGoals <<endl;
cout<<"Assists Made: "<< numAssists <<endl;
}
std::ostream& operator<<(std::ostream& player, const SoccerPlayer& aPlayer)
{
player << "Jersey #" << aPlayer.jerseyNum <<
" Number of Goals " << aPlayer.numGoals <<
" Number of Assists " << aPlayer.numAssists;
return player;
}
std::istream& operator>>(std::istream& inPlayer, SoccerPlayer& aPlayer)
{
cout << "Please enter the jersey number: ";
inPlayer >> aPlayer.jerseyNum;
cout << "Please enter the number of goals: ";
inPlayer >> aPlayer.numGoals;
cout << "Please enter the number of assists: ";
inPlayer >> aPlayer.numAssists;
aPlayer.score=(aPlayer.numGoals) + (aPlayer.numAssists);
return inPlayer;
}
int SoccerPlayer::operator>(SoccerPlayer& aPlayer)
{
int total = 0;
if (score > aPlayer.score)
total = 1;
return total;
}
int main()
{
const int sz = 11;
int x;
SoccerPlayer aPlayer[sz];
for(x = 0; x < sz; ++x)
cin >> aPlayer[x];
{
double max = aPlayer[x].score;
for(int i = 1; i<sz; ++i)
{
if(aPlayer[i] > aPlayer[x])
{
max=aPlayer[i].score;
}
}
cout << max << endl;
cout << aPlayer[x];
}
_getch();
return 0;
}
It looks as if you intended a loop here, but it's malformed:
for(x = 0; x < sz; ++x)
cin >> aPlayer[x];
{
double max = aPlayer[x].score;
for(int i = 1; i<sz; ++i)
{
if(aPlayer[i] > aPlayer[x])
{
max=aPlayer[i].score;
}
}
cout << max << endl;
cout << aPlayer[x];
}
You meant (I think) that double max ... should be inside the loop, but the cin >> ... line comes after the for statement, outside the braces. So the iteration applies only to the cin >> ... statement; once it's done, control proceeds to double max = aPlayer[x].score;, but x (left over from for(...)) is equal to sz, so aPlayer[x] is outside the array, in no-man's-land.
Put the cin >> ... inside the brackets.
The problem is that you only print the element aPlayer[x]. But notice that your first for loop terminates when x = 11. Well, that's one past the end of the array, so really, you're outputting junk.
I just tried it out with aPlayer[0] instead and got expected results.
This is what I ended up with. Thanks everyone for the help!
// Amanda
// SoccerPlayer.cpp : main project file.
// October 6, 2012
/* a. Design a SoccerPlayer class that includes three integer fields: a player's jersey number,
number of goals, and number of assists. Overload extraction and insertion operators for the class.
b. Include an operation>() function for the class. One SoccerPlayer is considered greater
than another if the sum of goals plus assists is greater.
c. Create an array of 11 SoccerPlayers, then use the > operator to find the player who has the
greatest goals plus assists.*/
#include "stdafx.h"
#include<conio.h>
#include<iostream>
#include<string>
using namespace std;
//soccer player class - see above description
class SoccerPlayer
{
friend std::ostream& operator<<(std::ostream&, const SoccerPlayer&);
friend istream& operator>>(istream&, SoccerPlayer&);
private:
int jerseyNum;
int numGoals;
int numAssists;
public:
SoccerPlayer(int, int, int);
int score;
int operator>(SoccerPlayer&);
void DisplayStar();
};
//soccerplayer constructor
SoccerPlayer::SoccerPlayer(int jersey = 0, int goal = 0, int assist = 0)
{
jerseyNum = jersey;
numGoals = goal;
numAssists = assist;
}
//to display star player
void SoccerPlayer::DisplayStar()
{
cout<<"Jersey #: "<< jerseyNum <<endl;
cout<<"Goals Scored: "<< numGoals <<endl;
cout<<"Assists Made: "<< numAssists <<endl;
}
//overload operator out
std::ostream& operator<<(std::ostream& player, const SoccerPlayer& aPlayer)
{
player << "Jersey #" << aPlayer.jerseyNum <<
" Number of Goals " << aPlayer.numGoals <<
" Number of Assists " << aPlayer.numAssists;
return player;
}
//overload operator in
std::istream& operator>>(std::istream& inPlayer, SoccerPlayer& aPlayer)
{
cout << "Please enter the jersey number: ";
inPlayer >> aPlayer.jerseyNum;
cout << "Please enter the number of goals: ";
inPlayer >> aPlayer.numGoals;
cout << "Please enter the number of assists: ";
inPlayer >> aPlayer.numAssists;
aPlayer.score=(aPlayer.numGoals) + (aPlayer.numAssists);
return inPlayer;
}
//overload operator greater than
int SoccerPlayer::operator>(SoccerPlayer& aPlayer)
{
int total = 0;
if (score > aPlayer.score)
total = 1;
return total;
}
//main declaration
int main()
{
//11 players
const int sz = 11;
int x;
SoccerPlayer aPlayer[sz];
double max = 0;
//to display star
SoccerPlayer Star;
//allow user to input players, show what they input
for(x = 0; x < sz; ++x)
{
cin >> aPlayer[x];
cout << aPlayer[x] << endl << endl;
for(int i=1; i<sz; i++)
{
Star=aPlayer[0];
if(aPlayer[i] > aPlayer[i+1])
Star=aPlayer[i];
}
}
//show star player
cout << "The Star Player: "<< endl;
Star.DisplayStar();
_getch();
return 0;
}