I am new to C++ and am having issues when running this code, I have no idea where I have gone wrong.
I am just trying to make a simple Song class, then add and display an instance of the song object.
The error is saying that allot of my Methods are already defined in projectName.obj. I am also getting unresolved external symbol on IDSeed.
I am using visual studio 2017.
Main
#include "stdafx.h"
#include "Song.h"
#include "Song.cpp"
int main()
{
Song testSong("Evil Tram", "Catz N dogz");
testSong.setGenre("Tech House");
testSong.display();
return 0;
}
Song.cpp
#include "stdafx.h"
#include "Song.h"
Song::Song()
{
m_title = "";
m_album = "";//change to class
m_artist = "";//change to class
m_genre = "";//change to enum
m_ID = 0;
IDSeed = 0;
}
Song::Song(string title, string artist)
{
m_title = title;
m_album = "No Album";
m_genre = "No Genre";
m_artist = artist;
IDSeed++;
m_ID = IDSeed;
}
string Song::getTitle() const
{
return m_title;
}
string Song::getAlbum() const
{
return m_album;
}
string Song::getArtist() const
{
return m_artist;
}
string Song::getGenre() const
{
return m_genre;
}
int Song::getID() const
{
return m_ID;
}
void Song::setTitle(string title)
{
m_title = title;
}
void Song::setAlbum(string album)
{
m_album = album;
}
void Song::setArtist(string artist)
{
m_artist = artist;
}
void Song::setGenre(string genre)
{
m_genre = genre;
}
void Song::setID(int id)
{
m_ID = id;
}
void Song::display() const
{
cout << m_title << ", " << m_album << ", "
<< m_artist << ", " << m_genre << endl;
}
Song::~Song()
{
}
ostream & operator<<(ostream & out, Song & s)
{
out << s.m_title << ", " << s.m_album << ", "
<< s.m_artist << ", " << s.m_genre << endl;
return out;
}
istream & operator>>(istream & in, Song & s)
{
in >> s.m_title >> s.m_album >> s.m_artist >> s.m_genre;
return in;
}
Song.h
#pragma once
#include <iostream>
#include <string>
#include <ostream>
using std::string;
using std::cout;
using std::endl;
using std::ostream;
using std::istream;
class Song
{
private:
#pragma region Variables
string m_title;
string m_album;//change to class
string m_artist;//change to class
string m_genre;//change to enum
int m_ID;
static int IDSeed;
#pragma endregion
public:
Song();
Song(string title, string artist);
#pragma region Getters
string getTitle() const;
string getAlbum()const;
string getArtist()const;
string getGenre()const;
int getID()const;
#pragma endregion
#pragma region Setters
void setTitle(string title);
void setAlbum(string album);
void setArtist(string artist);
void setGenre(string genre);
void setID(int id);
#pragma endregion
#pragma region Methods
void display() const;
#pragma endregion
friend ostream& operator<<(ostream& out,
Song& s);
friend istream& operator>>(istream& in,
Song& s);
~Song();//destructer
};
Solved by removing the #include song.cpp and placing the static keyword in the cpp file instead of the .h
Related
I have some data in the file that I would like to be able to read into a vector of a class-type/object. This object also has within itself a vector that takes in another class type, and the data that needs to populate that inner vector is also contained within the text file. How can I read the data from the file into the vectors accordingly without using getLine()?
The data is formatted as so in the document.
143 Jones
1234 2 C
-1
123 Smith
4321 4 A
132 3 B
-1
Where the first line is the ID of the student followed by their name, and below it is a series of classes that student has taken followed by the number of credits each course is worth and the grade the student got for the course.
Below is the course class header code
#pragma once
#include <iostream>
class Course {
public:
Course(int, int, std::string);
int getCourseCode() const {return courseCode;}
int getCredits() const {return courseCredits;}
std::string getGrade() const {return grade;}
void print(std::ostream &os) const;
private:
int courseCode;
int courseCredits;
std::string grade;
};
inline std::ostream &operator <<(std::ostream &os, const Course &course) {
course.print(os);
return os;
}
inline Course::Course(int courseCode, int courseCredits, std::string grade) {
this->courseCode = courseCode;
this->courseCredits = courseCredits;
this->grade = grade;
}
Below is the student class header code
#pragma once
#include <vector>
#include "course.h"
class Student {
public:
Student(int, std::string, std::vector<Course> courses);
int getID() const;
double getGPA() const;
std::string getName() const;
void print(std::ostream &os) const;
std::vector<Course> courses;
private:
int id;
std::string name;
};
inline std::ostream &operator << (std::ostream &os, const Student &student) {
student.print(os);
return os;
}
Below is the student.cpp code
#include "student.h"
#include <string>
using namespace std;
Student::Student(int id, std::string name, vector<Course> courses) {
this->id = id;
this->name = name;
this->courses = courses;
}
int Student::getID() const {
return id;
}
string Student::getName() const {
return name;
}
double Student::getGPA() const {
double total;
double creds;
double cgrade;
double gpa;
for(int i = 0; i < courses.size(); i++) {
if(courses[i].getGrade() == "A") cgrade = 4.0;
else if(courses[i].getGrade() == "B") cgrade = 3.0;
else if(courses[i].getGrade() == "C") cgrade = 2.0;
else if(courses[i].getGrade() == "D")cgrade = 1.0;
total += cgrade * courses[i].getCredits();
creds += courses[i].getCredits();
}
gpa = total / creds;
return gpa;
}
void Student::print(std::ostream &os) const {
os << id << " " << name << ": " << this->getGPA() << endl;
for(int i = 0; i < courses.size(); i++) {
os << courses[i];
}
}
This is what I've tried so far in terms of trying to load the vectors
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include "student.h"
using namespace std;
void loadStudents(string fileName, vector<Student> &students);
bool compareCourses(const Course &c1, const Course &c2);
bool compareStudents(const Student &s1, const Student &s2);
void printResults(string fileName, vector<Student> &students);
int main() {
try {
vector<Student> students;
loadStudents("students.data", students);
cout << students.size() << " records processed" << endl;
return 0;
}
catch(string message) {
cout << "Error: " << message << endl;
exit(1);
}
};
void loadStudents(string fileName, vector<Student> &students) {
ifstream studentsFile(fileName.c_str());
if(!studentsFile.good()) {
throw string("Input file: " + fileName + ", not found!");
}
int id;
string name;
vector<Course> cs;
while(studentsFile >> id >> name >> cs) {
students.place_back(student);
}
studentsFile.close();
}
bool compareCourses(const Course &c1, const Course &c2) {
return c1.getGrade() < c2.getGrade();
}
bool compareStudents(const Student &s1, const Student &s2) {
return s1.getGPA() < s2.getGPA();
}
void printResults(string fileName, vector<Student> &students) {
ofstream outputFile(fileName.c_str());
if(!outputFile.good()) {
throw string("Output file: " + fileName + ", not found!");
}
for(auto student : students) {
outputFile << student.print(outputFile) << endl;
}
outputFile.close();
}
I'm getting an error stating that "no operator ">>" matches these operands" in the while loop inside the loadStudents function, which I think pertains to the istream for the vector.
The desired output is something like this printed to an output file.
143 Smith: 3.57143
4321 (4 credits): A
132 (3 credits): B
143 Jones: 2
1234 (2 credits): C
2 records processed
Where the student ID and name are printed along with their calculated GPA and the courses they took below them followed by a message stating the number of students that were processed.
My main issue pertains to the loading of the students vector with the subsequent data of the course information being appropriately loaded into the courses vector for each student. Is this possible without using the getLine() method and istream >>?
A class BookLibrary constructs a vector of objects of class BookInfo. The task is to add some 'books' (objects of class BookInfo) into the vector and print them out. For some reason, a conventional for(unsigned int i = 0; i < vector.size(); i++) cout << vector[i] << endl; loop is not working. This is a homework project from Savitch textbook "Problem Solving with C++".
Here's the code:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class BookInfo
{
public:
BookInfo(string newAuthor, string newTitle);
BookInfo(string newTitle);
string getName();
string getAuthor();
string getTitle();
private:
string author;
string title;
};
class BookLibrary
{
public:
BookLibrary();
BookLibrary(vector<BookInfo> newLibrary);
void add(BookInfo newBook);
void size();
void printInfo();
private:
vector<BookInfo> library;
};
int main()
{
BookLibrary library1;
BookInfo book1("Michael Krichton", "Jurassic Park");
BookInfo book2("War and Peace"), book3("Valter Savitch", "Programming in C++");
library1.add(book1);
library1.add(book2);
library1.add(book3);
library1.size();
library1.printInfo();
return 0;
}
BookInfo::BookInfo(string newAuthor, string newTitle)
{
author = newAuthor;
title = newTitle;
}
BookInfo::BookInfo(string newTitle) :
title(newTitle), author("unknown")
{}
string BookInfo::getName()
{
return (author + " " + title);
}
string BookInfo::getAuthor()
{
return author;
}
string BookInfo::getTitle()
{
return title;
}
BookLibrary::BookLibrary()
{}
BookLibrary::BookLibrary(vector<BookInfo> newLibrary)
{
library = newLibrary;
}
void BookLibrary::add(BookInfo newBook)
{
library.push_back(newBook);
}
void BookLibrary::size()
{
cout << library.size();
}
void BookLibrary::printInfo()
{
for (unsigned int i = 0; i < library.size(); i++)
cout << library[i] << endl;
}
It underlines the cout << in the last line.
Your loop is not able to print out a BookInfo object, because you have not defined an operator<< for BookInfo. As such, a statement like cout << library[i] does not know what to do with the BookInfo that library[i] returns.
You need to add that operator, eg:
class BookInfo
{
public:
...
friend ostream& operator<<(ostream &os, const BookInfo &book)
{
os << "\"" << book.title << "\" by " << book.author;
return os;
}
...
};
If you want to use your getName() method instead, you would need to declare it as const (which you should do anyway for all of your getters), eg:
class BookInfo
{
public:
...
string getName() const;
...
friend ostream& operator<<(ostream &os, const BookInfo &book)
{
os << book.getName();
return os;
}
...
};
string BookInfo::getName() const
{
return ...;
}
I am learning how to work with objects but am stuck the closest answer is could find was Read class objects from file c++.
In this question:
How would you go about the same task if your member variables were declared as private?
Try something similar to this:
Content of person.txt
John California 3683893
Stalin Russia 489895
Sample code:
#include<iostream>
#include <fstream>
#include <vector>
#include <string>
class person
{
private:
std::string _name;
std::string _address;
unsigned int _phone;
public:
person(const std::string& name, const std::string& address, unsigned int phone)
:_name(name),_address(address),_phone(phone)
{}
std::string getName() const { return _name; }
std::string getAddress() const { return _address; }
unsigned int getPhone() { return _phone; }
};
int main()
{
std::vector<person> persons;
std::string name;
std::string address;
unsigned int phone;
std::ifstream fs;
fs.open("person.txt");
if (fs.is_open()) {
while (std::getline(fs, name, ' ') && std::getline(fs, address, ' ') &&
(fs >> phone))
{
persons.push_back(person(name,address,phone));
}
}
for (auto p : persons) {
std::cout << p.getName() << " " << p.getAddress() << " " << p.getPhone() << '\n';
}
return 0;
}
Not sure where I am at the moment, trying to figure it out. I need to initialize the members in print() const as it is giving me random gibberish. No matter what I try to do, it does not seem to work. Not sure what to even do. Can anyone give me a hand?
*edit: Added in the rest of the code. Forgot it when I submitted the first time.
Student.cpp
#include "student.h"
//implement the required 3 functions here
Student::Student(const char initId[], double gpa)
{
// initialize a newly created student object with the passed in value
}
bool Student::isLessThanByID(const Student& aStudent) const
{
// compare the current student object with the passed in one by id.
if (strcmp(id, aStudent.id) > 0)
{
return true;
}
else
{
return false;
}
}
bool Student::isLessThanByGpa(const Student& aStudent) const
{
// compare the current student object with the passed in one by gpa
if (gpa < aStudent.gpa)
{
return true;
}
else
{
return false;
}
}
void Student::print() const
{
cout << id << '\t' << gpa << endl;
}
student.h
#ifndef STUDENT_H
#define STUDENT_H
#include <iostream>
using namespace std;
class Student
{
public:
Student(const char initId[], double gpa);
bool isLessThanByID(const Student& aStudent) const;
bool isLessThanByGpa(const Student& aStudent) const;
void print()const;
private:
const static int MAX_CHAR = 100;
char id[MAX_CHAR];
double gpa;
};
#endif
app.cpp
#include "student.h"
int main()
{
Student s1("G10", 3.9);
Student s2("G20", 3.5);
s1.print();
s2.print();
if(s1.isLessThanByID(s2))
{
cout << "about right!" << endl;
}
else
{
cout << "uhmm ..." << endl;
}
if(!s1.isLessThanByGpa(s2))
{
cout << "about right!" << endl;
}
else
{
cout << "uhmm ..." << endl;
}
system("pause");
return 0;
}
There is nothing in that code that sets the values of Student::id and Student::gpa. Your constructor has parameters initId and gpa; you should copy those into your object. Based on the declaration of Student that you provided, something this should be appropriate:
Student::Student(const char initId[], double gpa) : gpa(gpa)
{
strncpy(id, initId, Student::MAX_CHAR-1);
id[Student::MAX_CHAR-1] = '\0';
}
I'm having a little problem when trying to compile a very simple test c++ code:
I have a Warrior class when I want to define a copy constructor for test purposes. I declare it in Warrior.h and define it in Warrior.cpp.
When compiling the code with g++ on Ubuntu, it works great, however when trying to compile it on Windows7 Codeblocks (mingw), I get the following message :
error: definition of implicitly-declared 'Warrior::Warrior(const Warrior&)'|||=== Build failed: 1 error(s)
The code:
Warrior.h
#ifndef WARRIOR_H_INCLUDED
#define WARRIOR_H_INCLUDED
#include <string>
#include "Arme.h"
#include "Warrior.h"
class Warrior{
public:
Warrior(Warrior const& other);
std::string getName() const;
Warrior setName(std::string name);
int getAge() const;
Warrior setAge(int age);
int getLife() const;
Warrior setLife(int life);
Arme getArme() const;
Warrior setArme(Arme& arme);
void attaquer(Warrior& autreCombattant);
bool isAlive() const;
Warrior setIsAlive(bool isAlive);
Warrior(std::string name, int age);
~Warrior();
private:
std::string m_name;
int m_age;
int m_life;
bool m_isAlive;
Arme m_arme;
};
#endif // WARRIOR_H_INCLUDED
Warrior.cpp
#include "Warrior.h"
#include "Arme.h"
#include <iostream>
#include <string>
using namespace std;
Warrior Warrior::setName(string name){
m_name=name;
return *this;
}
string Warrior::getName() const{
return m_name;
}
int Warrior::getAge() const{
return m_age;
}
Warrior Warrior::setAge(int age){
m_age=age;
return *this;
}
int Warrior::getLife() const{
return m_life;
}
Warrior Warrior::setLife(int life){
m_life=life;
if(life<=0){
cout << m_name << " est mort." << endl;
}else{
cout << m_name << " a la vie suivante : " << m_life << endl;
}
return *this;
}
Arme Warrior::getArme() const{
return m_arme;
}
Warrior Warrior::setArme(Arme& arme){
m_arme=arme;
cout << m_name << " a maintenant l'arme suivante : " << arme.getName() << endl;
return *this;
}
void Warrior::attaquer(Warrior& autreCombattant){
autreCombattant.setLife(autreCombattant.getLife() - m_arme.getDegat());
}
bool Warrior::isAlive() const{
return m_isAlive;
}
Warrior Warrior::setIsAlive(bool isAlive){
m_isAlive=isAlive;
return *this;
}
Warrior::Warrior(string name, int age): m_name(name), m_age(age), m_arme("b",4){
m_life=300;
cout << name << " vient de rejoindre l'arene" << endl;
}
Warrior::~Warrior(){}
Warrior::Warrior(Warrior const& autre): m_name(autre.getName())
{}
Arme.h
#ifndef ARME_H_INCLUDED
#define ARME_H_INCLUDED
#include <string>
class Arme{
private:
int m_degat;
std::string m_name;
public:
int getDegat() const;
Arme setDegat(int degat);
std::string getName() const;
Arme setName(std::string name);
Arme(std::string name, int degat);
Arme();
};
#endif // ARME_H_INCLUDED
Arme.cpp
#include "Arme.h"
#include <iostream>
#include <string>
using namespace std;
int Arme::getDegat() const{
return m_degat;
}
Arme Arme::setDegat(int degat){
m_degat=degat;
return *this;
}
string Arme::getName() const{
return m_name;
}
Arme Arme::setName(string name){
m_name=name;
return *this;
}
Arme::Arme(std::string name, int degat): m_name(name), m_degat(degat){
}
Arme::Arme(){
m_name="default weapon";
m_degat=1;
}
Thanks for your help
I have removed my project on codeblocks, then created a new one and I have added the previously created files, now it compiles without any problem.
It seems to me Codeblocks has a kind of cache engine that was not refreshed...weird!