For a project, our professor has provided us with one .cpp file and three .h files containing Class definitions. The goal of the project is to construct the implementation .cpp files for these Classes.
I'm aware that using namespace std; is bad practice and should be avoided at all costs, but the teacher insists on three important points in the completion of the project:
You must not modify any of the provided files. "Not a single character". (60% reduction in marks)
It fails to build in Visual Studio 2017. (60% reduction in marks)
It crashes during normal operation. (60% reduction in marks)
My problem is that I'm receiving some errors pertaining to his definition of a forward_list<> in one of the Classes. These errors mean nothing to me... I've been scratching my head for the last few hours, while attempting to remedy these errors:
1>Animation.cpp
1>AnimationManager.cpp
1>c:\users\ali-g\desktop\cst8219\assignment2\assignment2\animation.h(7): error C2143: syntax error: missing ';' before '<'
1>c:\users\ali-g\desktop\cst8219\assignment2\assignment2\animation.h(7): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\ali-g\desktop\cst8219\assignment2\assignment2\animation.h(7): error C2238: unexpected token(s) preceding ';'
1>Ass2.cpp
1>Generating Code...
1>Done building project "Assignment2.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Here is the .h file he provided, containing the Animation class definition:
//Animation.h
#pragma once
class Animation
{
string animationName;
forward_list<Frame> frames;
public:
Animation(string name) :animationName(name) {}
~Animation() {}
void EditFrame();
void DeleteFrame();
friend istream& operator>>(istream&, Animation&);// Add a Frame as in cin >> A;
friend ostream& operator<<(ostream&, Animation&);// output the Frames as in cout << A;
};
Here is my implementation .cpp file from Animation Class:
//Animation.cpp
#include <iostream>
#include <string>
#include <forward_list>
using namespace std;
#include "Frame.h"
#include "Animation.h"
void Animation::EditFrame() {
}
void Animation::DeleteFrame() {
}
istream& operator>> (istream& in, Animation& animation) {
return in;
}
ostream& operator<< (ostream& out, Animation& animation) {
return out;
}
The .h file he provided containing the definition for AnimationManager Class:
// AnimationManager.h
#pragma once
class AnimationManager
{
string managerName;
vector<Animation> animations;
public:
AnimationManager(string name) :managerName(name) {}
~AnimationManager() {}
void EditAnimation();
void DeleteAnimation();
friend istream& operator>>(istream&, AnimationManager&);// add an Animation
friend ostream& operator<<(ostream&, AnimationManager&);// output the Animations
};
And here is my implementation file for AnimationManager Class:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
#include "Frame.h"
#include "Animation.h"
#include "AnimationManager.h"
void AnimationManager::EditAnimation() {
}
void AnimationManager::DeleteAnimation() {
}
istream & operator>>(istream &in, AnimationManager &manager){
string name;
cout << "Please enter Animation Name: ";
cin >> name;
//resize vector array to accommodate a new Animation
manager.animations.resize(manager.animations.size() + 1);
manager.animations.push_back(Animation(name));
}
ostream & operator<<(ostream &out, AnimationManager &manager){
}
I'll also include the .h & .cpp file for the other included header file (Frame.h), as it may help you find my (most likely stupid) mistake.
"Frame.h":
// Frame.h
#pragma once
class Frame{
char* frameName;
double duration;
public:
Frame(char*, double);
Frame(const Frame&);
~Frame();
Frame& operator=(const Frame&);
friend ostream& operator<<(ostream&, Frame&);
};
"Frame.cpp":
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
#include "Frame.h"
Frame::Frame(char* name, double dur) {
//Set frame name
frameName = new char[strlen(name) + 1];
strcpy(this->frameName, name);
//set duration
duration = dur;
}
Frame::Frame(const Frame& frame) {
//copy name from passed frame
frameName = new char[strlen(frame.frameName) + 1];
strcpy(frameName, frame.frameName);
//copy duration
duration = frame.duration;
}
Frame::~Frame() {
//free the space allocated for frameName
if (frameName != nullptr) {
delete[] frameName;
}
}
Frame& Frame::operator= (const Frame& frame) {
//create new Frame using given frame information
Frame copyFrame = Frame(frame.frameName, frame.duration);
//return reference to new frame.
return copyFrame;
}
ostream& operator<< (ostream& out, Frame& frame) {
//add frameName and duration to ostream.
out << "\tframeName - " << frame.frameName << "; ";
out << "duration - " << frame.duration << endl;
//return ostream
return out;
}
I would greatly appreciate any help in solving this problem. Thanks in advance!
Related
I need to create an ADT for an assignment. I have my class definition in a header file as follows:
#ifndef PHONECALL_H
#define PHONECALL_H
#include <iostream>
using namespace std;
class PhoneCall
{
public:
PhoneCall();
PhoneCall(string newNumber);
~PhoneCall();
string getNumber()const;
int getLength()const;
float getRate()const;
float calcCharge(); //calcuates total cost of call
friend bool operator==(const PhoneCall & call1, const PhoneCall & call2);
friend istream& operator >>(istream& in, PhoneCall& call);
friend ostream& operator <<(ostream& out, const PhoneCall& call);
private:
string number;
int length;
float rate;
};
All the bodies of the functions are in the implementation file (no errors there)
Then in the main application file, when I call the calcCharge() function, I get:
error: 'calcCharge()' was not declared in this scope
This is the only error I get. Here is the application file code:
#include <iostream>
#include <fstream>
#include "PhoneCall.h"
using namespace std;
int main()
{
string num, cellNum;
int length;
float rate, total;
cout << "Enter a phone number: " << endl;
cin>> num;
PhoneCall theCall(num);
ifstream read;
while (read >> cellNum >> length >> rate)
{
if (cellNum == num)
{
total += calcCharge();
}
}
return 0;
}
I know the code for the main application is incomplete, but due to this error I am not able to test whether the program is doing what I need it to do.
It's a member of the class.
total += theCall.calcCharge();
So I'm trying to write and read from a file, using std::ostream_iterator and std::iostream_iterator. The process of writng works well without any mistakes. But as for reading I'm lost. The error, I have is:
1>c:\program files (x86)\microsoft visual studio 14.0\vc\include\xutility(2316): error C2678: binary '=': no operator found which takes a left-hand operand of type 'const WRstruct' (or there is no acceptable conversion)
and it says that:
c:\users\xxxxxxx\desktop\ttttt\ttttt\wrstruct.h(21): note: could be 'WRstruct &WRstruct::operator =(const WRstruct &)'
1> c:\program files (x86)\microsoft visual studio 14.0\vc\include\xutility(2316): note: while trying to match the argument list '(const WRstruct, WRstruct)'
What is the correct way of overloading operator=?
class:
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include <iterator>
#include <istream>
class WRstruct
{
private:
std::string name;
std::string number;
friend std::ostream& operator<<(std::ostream&, const WRstruct&);
friend std::istream& operator >> ( std::istream& is, WRstruct&);
public:
WRstruct(){};
void write();
void read();
~WRstruct(){};
};
std::ostream& operator<<(std::ostream& os, const WRstruct& p)
{
os << "User Name: " << p.name << std::endl
<< "Name: " << p.number << std::endl
<< std::endl;
return os;
}
std::istream& operator >> (std::istream& is, WRstruct& p)
{
is >> p.name>>p.number;
return is;
}
Methods:
void WRstruct::write()
{
std::vector<WRstruct> vecP;
std::copy(std::istream_iterator<WRstruct>(std::cin),
std::istream_iterator<WRstruct>(), std::back_inserter(vecP));
std::ofstream temp("temp.txt", std::ios::out);
std::ostream_iterator<WRstruct>temp_itr(temp, "\n");
std::copy(vecP.begin(), vecP.end(), temp_itr);
}
void WRstruct::read()
{
std::vector<WRstruct> vec;
std::ifstream readFile("temp.txt");
std::istream_iterator<WRstruct> istr(readFile);
copy(vec.begin(), vec.end(), istr);
std::istream_iterator<WRstruct> end_istr;
copy(istr, end_istr, back_inserter(vec));
std::ostream_iterator<WRstruct> osIter(std::cout," ");
copy(vec.begin(),vec.end(),osIter);
}
and main():
#include <iostream>
#include "WRstruct.h"
int main()
{
WRstruct r;
r.write();
//r.read();
return 0;
}
As far as I understand, the meaning of your function WRstruct::read is "reading all the data from 'temp.txt' and writing it to console". BTW, it's strange that function read prints something, so consider naming your function accordingly.
To read something from file using istream_iterator, you should create a pair of iterators (one pointing to the beginning of the file, and another empty) and use std::copy. So, the reading part of your function should look like
std::vector<WRstruct> vec;
std::ifstream readFile("temp.txt");
std::istream_iterator<WRstruct> istr(readFile);
std::istream_iterator<WRstruct> end_istr;
copy(istr, end_istr, back_inserter(vec));
So, you can just comment or delete one line from WRstruct::read to get rid of compilation error.
I wanted to try to overload "<<" operator for an output stream and a custom class Article.
my.h
#include <iostream>
using namespace std;
class Article {
string body;
string header;
string author;
public:
Article();
void addHeader(const string&);
void addBody(const string&);
string getHeader();
string getBody();
};
my.cpp
string Article::getHeader() {
return header;
}
void Article::addBody(const string& body) {
this->body = body;
}
void Article::addHeader(const string& header) {
this->header = header;
}
ostream& operator<<(ostream& os, Article& article) {
return os << article.getHeader() << "\n\n" << article.getBody();
}
main.cpp
#include <iostream>
#include <string>
#include "my.h"
void main() {
char bye;
Article article = Article();
article.addBody("This is my article! thank you!");
article.addHeader("Header");
cout << article.getHeader() << "\n";
cout << article.getBody() << "\n";
cout << article;
cin >> bye;
}
This code doesn't compile. VS 2013 says:
binary '<<' : no operator found which takes a right-hand operand of type 'Article' (or there is no acceptable conversion)
If I remove the last line, it compiles successfully and the output of getHeader() and getBody() is as expected. They both return strings so it should be a piece of cake.
This problem seems very simple, however, as simple as it is I can't figure out what is happenning.
Now that you have posted real code the answer is obvious.
You define your operator << in my.cpp, but you don't declare it in my.h, so when compiling main.cpp the compiler has no way of knowing it exists.
Add a declaration of the function to your header.
I am working on this project just trying to keep up my c++ knowledge. Anyways, I am getting many, many errors when i try to implement an operator overload. Not sure why.
#include "students.h"
#include <iostream>
#include "Quack.h"
using namespace std;
void main()
{
quack* classmates = new quack;
classmates->pushFront(students("corey", "9081923456", 4.0));
cout << "\noriginal data set -- " << *students;
and this is where i am getting the errors with the operator. Oddly enough if i comment out the overloaded operator and leave it in students.cpp it compiles find.
#ifndef STUDENTS_H
#define STUDENTS_H
#include <iostream>
class students
{
// causing errors
friend ostream& operator << (ostream& out,const students& student);
public:
students();
students(char * name, char* oitId, float gpa);
students(const students& student); // copy constructor;
~students();
const students& operator=(const students& student);
void getName(char* name) const;
void getoitId(char* oitId) const;
float getGpa(void) const;
void setName(char* name);
void setoitId(char* oitId);
void setGpa(float gpa);
private:
char* name;
char* oitId;
float gpa;
};
#endif
}
and, causes errors alo. But not by itself..
#include "students.h"
#include <iostream>
#include <iomanip>
using namespace std;
#pragma warning(disable:4996)
private:
char* name;
char* oitId;
float gpa;
students::students(): name(NULL), oitId(NULL), gpa(0)
{
}
students::students(char *name, char *oitId, float gpa): name(NULL), oitId(NULL), gpa(0)
{
setName(name);
setoitId(oitId);
}
students::~students()
{
if(name)
delete[] name;
if(oitId)
delete[] oitId;
}
const students& students::operator=(const students& student)
{
//if it is a self copy, don't do anything
if(this == &student)
return *this;
//make current object *this a copy of the passed in student
else
{
setName(student.name);
setoitId(student.oitId);
//setGpa(student.gpa);
return *this;
}
}
void students::setName(char *name)
{
//release the exisisting memory if there is any
if(this->name)
delete [] this->name;
//set new name
this->name = new char[strlen(name)+1];
strcpy(this->name, name);
}
void students::setoitId(char *oitId)
{
if(this->oitId)
delete [] this->oitId;
//set new Id
this->oitId = new char[strlen(oitId)+1];
strcpy(this->oitId, oitId);
}
ostream& operator<< (ostream& out, const students& student)
{
//out << setw(20) << student.name
//<< setw(15) << student.pccId
//<< setw(8) << fixed << setprecision(2) << student.gpa;
return out;
}
here is the errors i get
syntax error : missing ';' before '&'
: error C2433: 'ostream' : 'friend' not permitted on data declarations
error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
error C2061: syntax error : identifier 'ostream'
error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
error C2805: binary 'operator <<' has too few parameters
1>Generating Code...
1>Compiling...
1>students.cpp
my eyes are burning and i cant figure out why its unhappy with the overloaded operator..
You are using ostream without qualifying it with namespace std::
The compiler errors/warnings are vaguely telling you that it has encountered a type that has not been declared yet.
friend std::ostream& operator << (std::ostream& out,const students& student);
Inline with comment by sbi, if your goal is to improve your C++ knowledge:
consider using C++ objects - such as std::string etc. rather than the char* (then you don't need the explicit memory management - always a good candidate for bugs and weird crashes), your getters can then return a const reference to the std::string (presumably in your implementation code, you're doing a copy, think about the added issues of this...)
Presumably quack is some kind of container, again point 1, think about using some of the existing libraries (STL for example).
"this->" is redundant, class members can be referred to directly - just clutters the code, if worried about variable name clashes, think about a naming convention and stick to it.
Now, looking specifically at your code:
1. I'll assume that
cout << "\noriginal data set -- " << *students;
is a typo, students is a type, you can only dereference a pointer, which this isn't (at least in the code snippet you've posted - if not, think carefully about variable names!).
2. presumably you meant it to be
cout << "\noriginal data set -- " << *classmates;
If so, check your stream operator for quack is implemented correctly.
Here is the header for a class I started:
#ifndef CANVAS_
#define CANVAS_
#include <iostream>
#include <iomanip>
#include <string>
#include <stack>
class Canvas
{
public:
Canvas();
void Paint(int R, int C, char Color);
const int Nrow;
const int Ncol;
string Title;
int image[][100];
stack<int> path;
struct PixelCoordinates
{
unsigned int r;
unsigned int c;
} position;
Canvas operator<< (const Canvas& One );
Canvas operator>>( Canvas& One );
};
/*-----------------------------------------------------------------------------
Name: operator<<
Purpose: Put a Canvas into an output stream
-----------------------------------------------------------------------------*/
ostream& operator<<( ostream& Out, const Canvas& One )
{
Out << One.Title << endl;
Out << "Rows: " << One.Nrow << " Columns: " << One.Ncol << endl;
int i,j;
for( i=0; i<One.Nrow; i++)
{
cout<<"\n\n\n";
cout<< " COLUMN\n";
cout<< " 1 2 3";
for(i=0;i<One.Nrow;i++)
{
cout<<"\nROW "<<i+1;
for(j=0;j<One.Ncol;j++) cout<< One.image[i][j];
}
}
return Out;
}
/*-----------------------------------------------------------------------------
Name: operator>>
Purpose: Get a Canvas from an input stream
-----------------------------------------------------------------------------*/
istream& operator>>( istream& In, Canvas& One )
{
// string Line;
// int Place = 0;
// {
// In >> Line;
// if (In.good())
// {
// One.image[Place][0] = Line;
// Place++;
// }
// return In;
#endif
Here is my implementation file for class Canvas:
using namespace std;
#include <iostream>
#include <iomanip>
#include <string>
#include <stack>
#include "proj05.canvas.h"
//----------------Constructor----------------//
Canvas::Canvas()
{
Title = "";
Nrow = 0;
Ncol = 0;
image[][100] = {};
position.r = 0;
position.c = 0;
}
//-------------------Paint------------------//
void Canvas::Paint(int R, int C, char Color)
{
cout << "Paint to be implemented" << endl;
}
And the errors I'm getting are these:
proj05.canvas.cpp: In function 'std::istream& operator>>(std::istream&, Canvas&)':
proj05.canvas.cpp:11: error: expected `;' before '{' token
proj05.canvas.cpp:24: error: expected `}' at end of input
From my limited experience, they look like simple syntax errors but for the life of me, I cannot see what I am missing. I know putting a ; at the end of Canvas::Canvas() is wrong but that seems to be what it expects. Could someone please clarify for me?
(Also, I know much of the code for the << and >> operator definitions look terrible, but unless that is the specific reason for the error please do not address it. This is a draft :) )
You're missing a } for istream& operator>>( istream& In, Canvas& One ) in the header.
The data member int image[][100]; is also invalid, as is image[][100] = {}; in the ctor.
Your implementation (.cpp) files should #include their corresponding header first. This is a simple way to ensure the header is self-contained. In this case, it would lead to syntax errors in standard library headers, which quickly points out to you the problem is in the header (since that is what will be before the stdlib #includes).
You are missing a closing } for your operator>> body. Also, this is not correct:
using namespace std;
#include <iostream>
The order has to be the other way around. GCC's behavior isn't conforming: std must not be visible if no standard header is included yet. So on the next more conformant compiler, it may fail hard.
Also, in the header you should write std::istream instead of just istream (same for ostream, etc). In your current code, your header relies on its users to have typen using namespace std; before including it, which is pretty ugly from a design point of view, since it makes the headers dependent on its users in a non-obvious way (normally, it should be the other way around).
You do not have a closing } at the end of operator >>
Others have answered your question, but here are a couple of extra points:
If your definitions of the insertion and extraction operators aren't templated then you should move them to your implementation file and merely declare them in the header file. This will allow you to replace the line
#include <iostream>
with the line
#include <iosfwd>
The latter will only include declarations of the IO streams, not the entire definitions. This in turn will translate to a faster compilation time of every compilation unit that includes that header.
On the other hand, you could as well choose to leave those functions in the header file but template them.
template <typename Ch,typename Tr>
std::basic_istream<Ch,Tr>& std::operator>>(std::basic_istream<Ch,Tr>& in,
Canvas& o)
{
// ...
}
This will give you the extra flexibility of supporting any stream at the cost of the same increased compilation time you have now.
There is also an error in the way You initialize constant members of Your class.
You have to use an initialization list
Canvas::Canvas()
: Nrow(0), Ncol(0)
{
Title = "";
//Nrow = 0; - this is an attempt to change the value of a const, which was already constructed.
//Ncol = 0; - same as above
//image[][100] = {};
position.r = 0;
position.c = 0;
}