Strange characters when displaying the char array C++ - c++

I can't correctly display information. In the text displayed extra characters. Most likely a problem with the zero character but I was not able to eliminate.
First file: person.h Here I describe a simple class.
#ifndef PERSON_H_INCLUDED
#define PERSON_H_INCLUDED
#include <string>
using std::string;
class Person
{
private:
static const int m_iLIMIT = 25;
string m_sLname; // lastname
char m_cFname[m_iLIMIT]; // firstname
public:
Person () { m_sLname = ""; m_cFname[0] = '\0'; } // #1
Person(const string & sLn, const char * pcFn = "Adam"); // #2
// show lastname и firstname
void Show() const; // format: firstname lastname
void FormalShow() const; // format: lastname, firstname
};
#endif // PERSON_H_INCLUDED
Second file: p_functions.cpp Here I define class methods
#include "person.h"
#include <iostream>
#include <string>
#include <cstring>
using std::string;
using std::cout;
using std::cin;
using std::endl;
// #2
Person::Person(const string & sLn, const char * cFn)
{
m_sLname = sLn;
strcat(m_cFname, cFn);
}
void Person::Show() const
{
cout << "First format: " << m_cFname << ", " << m_sLname << endl;
}
void Person::FormalShow() const
{
cout << "Second format: " << m_sLname << ", " << m_cFname << endl;
}
Third file: main.cpp Here I am testing methods
#include <iostream>
#include "person.h"
using namespace std;
int main()
{
Person one;
Person two("Smith");
Person three("immanuel", "Kant");
one.Show();
one.FormalShow();
two.Show();
two.FormalShow();
three.Show();
three.FormalShow();
return 0;
}
This is the result I get

in the second constructor m_cFname[0] is not initialized with 0
use strcpy instead of strcat
and you will have problem with longer first names

Related

C++ - initializing static vector of pointers causes undefined reference

I'm trying to create a function below in my CreateReport class called load() that copies all the records (data) from my graduate.dat file into my static vector of Record pointers called primaryCollection. I created a Record class with variables that make up each Record, and in my load() function in createReport.cc I attempted to read each line in the file, create a Record object with each line, add it to my vector, and then print everything in primaryCollection.
The problem is every time I attempt to use primaryCollection, I keep getting the error:
CreateReport.o: In function `CreateReport::CreateReport()':
CreateReport.cc:(.text+0x43): undefined reference to `CreateReport::primaryCollection'
CreateReport.o: In function `CreateReport::load()':
CreateReport.cc:(.text+0x2ac): undefined reference to `CreateReport::primaryCollection'
CreateReport.cc:(.text+0x31d): undefined reference to `CreateReport::primaryCollection'
CreateReport.cc:(.text+0x32f): undefined reference to `CreateReport::primaryCollection'
I get 4 undefined references for the 4 times I mention primaryCollection in createReport.cc. I'm not sure if I'm initializing primaryCollection correctly and if that is whats causing these undefined references. I don't know if this is relevant to my problem, but CreateReport is also an abstract class and has a few subclasses called ReportOne, ReportTwo, etc.
primaryCollection is supposed to be a static vector of Record pointers and I'm also not allowed to use std::map for this task.
I would appreciate any help with this issue. I looked at this post Undefined reference to static variable c++ but I still don't really understand what to do. I'm not allowed to make global variables and I'm dealing with a collection rather than a single variable.
My graduate.dat file is formatted like below in the format < year province degree >
2000 AB Bachelor's
2005 AB Bachelor's
2005 MB College
Each line basically represents a Record. So the first record here is 2000 AB Bachelor's
EDIT: So I made changes to my code based on the comments by adding the line vector<Record*> CreateReport::primaryCollection; above my constructor, but it gives me the error:
CreateReport.cc:13:34: error: conflicting declaration ‘std::vector<Record*> CreateReport::primaryCollection’
vector<Record*> CreateReport::primaryCollection;
^~~~~~~~~~~~~~~~~
In file included from CreateReport.cc:5:0:
CreateReport.h:23:33: note: previous declaration as ‘std::vector<Record*>* CreateReport::primaryCollection’
static std::vector<Record*>* primaryCollection; //STL vector of record pointers
^~~~~~~~~~~~~~~~~
CreateReport.cc:13:34: error: declaration of ‘std::vector<Record*>* CreateReport::primaryCollection’ outside of class is not definition [-fpermissive]
vector<Record*> CreateReport::primaryCollection;
Any ideas how to fix this?
Record.h
#ifndef RECORD_H
#define RECORD_H
#include <iostream>
#include <string>
class Record{
public:
Record(int = 0, string = "", string = "");
~Record();
private:
int year;
string province;
string degree;
};
#endif
Record.cc
#include <iostream>
#include <string>
using namespace std;
#include "Record.h"
Record::Record(int i1, string s1, string s2) : year(i1), province(s1), degree(s2){}
Record::~Record(){}
CreateReport.h
#ifndef CREATEREPORT_H
#define CREATEREPORT_H
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <iterator>
#include <algorithm>
#include <cstdlib>
#include "Record.h"
class CreateReport{
public:
CreateReport();
static void load();
protected:
static vector<Record*> primaryCollection; //STL vector of record pointers
};
#endif
CreateReport.cc
#include <iostream>
using namespace std;
#include <string>
#include "CreateReport.h"
vector<Record*> CreateReport::primaryCollection;
CreateReport::CreateReport(){
}
void CreateReport::load(){
int year;
string province, degree;
ostream_iterator<Record*> outItr(cout);
ifstream infile("graduate.dat", ios::in);
if (!infile) {
cout << "Error: could not open file" << endl;
exit(1);
}
while (infile >> year >> province >> degree) { //as long as were not at end of file
Record* record = new Record(year, province, degree); //create Record object with this data
primaryCollection->push_back(record); //undefined reference
}
cout<<endl<<"List of Records:"<<endl;
copy(primaryCollection->begin(), primaryCollection->end(), outItr); //2 undefined references
}
Second version using `Record*` for `std::vector primaryCollection`.
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
using namespace std;
class Record{
public:
Record(int = 0, string = "", string = "");
~Record()=default;
friend std::ostream& operator<<(std::ostream&, const Record&);
private:
int year;
string province;
string degree;
};
// **** output overload for Record ***********
std::ostream& operator<<(std::ostream& os, const Record& rd)
{
os << "year = " << rd.year << " prov = " << rd.province << " degree = " << rd.degree << std::endl;
return os;
}
// ****** end of output overload **************
Record::Record(int i1, string s1, string s2) : year(i1), province(s1), degree(s2){}
//end of Record.cc
//
class CreateReport{
public:
CreateReport() = default;
void load();
protected:
static vector<Record*> primaryCollection; //STL vector of record pointers
};
//***************** you need this line ********************
std::vector<Record*> CreateReport::primaryCollection;
//*********************************************************
void CreateReport::load(){
int year;
string province, degree;
ifstream infile("graduate.dat", ios::in);
if (!infile) {
cout << "Error: could not open file" << endl;
exit(1);
}
while (infile >> year >> province >> degree) {
Record *a = new Record(year, province, degree);
primaryCollection.push_back( a );
}
cout<<endl<<"List of Records:"<<endl;
for (int i = 0; i<primaryCollection.size(); ++i ) std::cout << *primaryCollection[i];
}
int main()
{
CreateReport mime;
mime.load();
}
Three major problems:
Using std::vector<*Record> cause many un-necessary difficulties;
For static member vector, a extra definition outside the class is necessary.std::vector<Record> CreateReport::primaryCollection;. This erases the undefined error message.
Using copy to std::cout doesn't work, it provide no method of printing Record. Suggest to write a output overload.
Based on these, I provide a version as follows (mixed all headers together.)
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
using namespace std;
class Record{
public:
Record(int = 0, string = "", string = "");
~Record()=default;
friend std::ostream& operator<<(std::ostream&, const Record&);
private:
int year;
string province;
string degree;
};
// **** output overload for Record ***********
std::ostream& operator<<(std::ostream& os, const Record& rd)
{
os << "year = " << rd.year << " prov = " << rd.province << " degree = " << rd.degree << std::endl;
return os;
}
// ****** end of output overload **************
Record::Record(int i1, string s1, string s2) : year(i1), province(s1), degree(s2){}
//end of Record.cc
//
class CreateReport{
public:
CreateReport() = default;
void load();
protected:
static vector<Record> primaryCollection;
};
//***************** you need this line ********************
vector<Record> CreateReport::primaryCollection;
//*********************************************************
void CreateReport::load(){
int year;
string province, degree;
ifstream infile("graduate.dat", ios::in);
if (!infile) {
cout << "Error: could not open file" << endl;
exit(1);
}
while (infile >> year >> province >> degree) {
primaryCollection.push_back( Record(year, province, degree) );
}
cout<<endl<<"List of Records:"<<endl;
for (int i = 0; i<primaryCollection.size(); ++i ) std::cout << primaryCollection[i];
}
int main()
{
CreateReport mime;
mime.load();
}

Error: expected constructor, destructor, or type conversion before ‘(’ token?

When I compile this I get the error title before my name functions in Name.cpp. I've never seen this error before. What's confusing is that there's already a constructor before the three functions in Name.cpp, since that's what the error seems to be talking about.
main.cpp
#include <iostream>
#include <string>
#include "Name.h"
using namespace std;
int main()
{
}
Name.h
#ifndef NAME_H
#define NAME_H
#include <iostream>
#include <string>
using namespace std;
class Name
{
public:
Name();
string getFirst(string newFirst);
string getMiddle(string newMiddle);
string getLast(string newLast);
void setFirst();
void setLast();
void setMiddle();
private:
string First;
string Middle;
string Last;
};
#endif // NAME_H
Name.cpp
#include "Name.h"
#include <iostream>
#include <string>
using namespace std;
Name::Name()
{
}
Name::setFirst(newFirst){
Name = newFirst;
cout << "You entered: " << Name << endl;
}
Name::setMiddle(newMiddle){
Middle = newMiddle;
cout << "You entered: " << Middle << endl;
}
Name::setLast(newLast){
Last = newLast;
cout<< "You entered: " << Last << endl;
}
You cannot omit type names of arguments. Write ones. Also function prototypes in declaration and definition have to be matched.
Your Name.h should be
#ifndef NAME_H
#define NAME_H
#include <iostream>
#include <string>
using namespace std;
class Name
{
public:
Name();
string getFirst();
string getMiddle();
string getLast();
void setFirst(string newFirst);
void setLast(string newLast);
void setMiddle(string newMiddle);
private:
string First;
string Middle;
string Last;
};
#endif // NAME_H
and Name.cpp should be
#include "Name.h"
#include <iostream>
#include <string>
using namespace std;
Name::Name()
{
}
void Name::setFirst(string newFirst){
Name = newFirst;
cout << "You entered: " << Name << endl;
}
void Name::setMiddle(string newMiddle){
Middle = newMiddle;
cout << "You entered: " << Middle << endl;
}
void Name::setLast(string newLast){
Last = newLast;
cout<< "You entered: " << Last << endl;
}

Printing out the wrong value

I'm trying to write a program that takes the grades and prints out the following:
ID:123 NAME:John GRADE:78
but instead I'm getting:
ID:-842150451 NAME: GRADE: 78
Can you guys help me and give me some extra tips to make my code cleaner since I'm fairly new to C++.
Student.h
#ifndef STUDENT_H
#define STUDENT_H
#include <iostream>
#include <string>
using namespace std;
class Student {
public:
Student(int num, string text);
int getID();
void setExamGrade(int a, int b);
int getOverallGrade();
void display();
string getName();
string name;
int id;
int exams[3];
int sum;
int average;
};
#endif
Student.cpp
#ifndef STUDENT_CPP
#define STUDENT_CPP
#include "Student.h"
#include <iostream>
#include <string>
using namespace std;
Student::Student(int num, string text)
{
num = id;
text = name;
exams[0, 1, 2] = 0;
}
int Student::getID() {
return id;
}
string Student::getName() {
return name;
}
void Student::setExamGrade(int a, int b) {
exams[a] = b;
}
int Student::getOverallGrade() {
sum = exams[0] + exams[1] + exams[2];
average = sum / 3;
return average;
}
void Student::display() {
cout << "ID: " << getID();
cout << " NAME: " << getName();
cout << " GRADE: " << getOverallGrade() << endl;
}
#endif
gradebook.cpp
#ifndef GRADEBOOK_CPP
#define GRADEBOOK_CPP
#include "Student.h"
#include <iostream>
using namespace std;
int main() {
Student *s = new Student(123, "John");
s->setExamGrade(0, 80);
s->setExamGrade(1, 60);
s->setExamGrade(2, 95);
s->display();
delete s;
return 0;
}
#endif
You never assign to id in the constructor, hence it's uninitialized and you will have undefined behavior when you print it.
Change
num = id;
to
id = num;
Same with the name.
Also, the statement
exams[0, 1, 2] = 0;
doesn't do what you expect it to do, it only initializes exams[2] to sero, and leaves the rest uninitialized. The expression 0, 1, 2 uses the comma operator.
Either assign to all members of the array separately, or use a constructor member initializer list (which I recommend for all the initialization).

non-const lvalue reference to type cannot bind error

Im trying to create a very simple VCard but im getting a non-const lvalue reference to type cannot bind error in my main.cpp and can't figure this out. the problem line is.....
vc->createVCard("JasonSteindorf.vcf", &p1);
//Person.h
#ifndef JASONSTEINDORF_PERSON_H
#define JASONSTEINDORF_PERSON_H
#include <string>
using std::string;
namespace JasonSteindorf{
class Person{
public:
Person();
Person(string firstName,string lastName,string phoneNumber,string email)
: firstName(firstName), lastName(lastName), phoneNumber(phoneNumber), email(email){}
inline string getFirstName(){ return firstName; }
inline string getLastName(){ return lastName; }
inline string getPhoneNumber(){ return phoneNumber; }
inline string getEmail(){ return email; }
private:
string firstName, lastName, phoneNumber, email;
};
}
#endif
//VCard.h
#ifndef JASONSTEINDORF_VCARD_H
#define JASONSTEINDORF_VCARD_H
#include "Person.h"
#include <string>
using std::string;
namespace JasonSteindorf{
class VCard{
public:
void createVCard(string fileName, Person &p);
string getVCard(Person &p);
};
}
#endif
//VCard.cpp
#include "VCard.h"
#include <fstream>
using std::ofstream;
#include <string>
using std::string;
#include <sstream>
#include <iostream>
using std::ostringstream;
using namespace JasonSteindorf;
//Writes the VCard to a file
string getVCard(Person &p){
ostringstream os;
os << "BEGIN:VCARD\n"
<< "VERSION:3.0\n"
<< "N:" << p.getLastName() << ";" << p.getFirstName() << "\n"
<< "FN:" << p.getFirstName() <<" " << p.getLastName() << "\n"
<< "TEL:TYPE=CELL:" << p.getPhoneNumber() << "\n"
<< "EMAIL:" << p.getEmail() << "\n"
<< "URL:" << "http://sorcerer.ucsd.edu/html/people/jason.html" << "\n"
<< "REV:20110719T195243Z" << "\n"
<< "END:VCARD\n";
return os.str();
}
//Returns a string containing the VCard format
void createVCard(string fileName, Person &p){
string vCard = getVCard(p);
ofstream outputFile("/Users/jsteindorf/Desktop/" + fileName);
outputFile << vCard;
}
//main.cpp
#include "Person.h"
#include "VCard.h"
#include <iostream>
using namespace JasonSteindorf;
int main(int argc, const char * argv[])
{
VCard *vc = new VCard();
Person *p1 = new Person ("Jason", "S", "858-555-5555", "js#ucsd.edu");
vc->createVCard("JS.vcf", &p1);
return 0;
}
You haven't defined the functions createVCard and getCard as member functions of VCard class.
Those are global functions. Use the scope resolution operator :: to define them as member functions of the class like
void Vcard::createVCard(string fileName,Person &p)
{
....
....
}
string Vcard::getVCard(Person &p)
{
....
....
}
And also your createVCard function accepts a reference to Person hence you will have to pass the object to the person not the address of pointer to the object (&p) nor address of the object (p) instead pass the object by de-referencing it like *p, hence the call would look like vc->createVCard("JS.vcf", *p1)

Linker error undefined reference to class::class (Person::Person in my case)

I am getting a linker error undefined reference to Person::Person when trying to implement my program. The three parts are below. I have been working on fixing it for a few hours now. I know it's probably something simple that I am just not seeing. But I have looked around on the internet and still have not found my answer. So any help would be appreciated.
#ifndef PERSON0_H_
#define PERSON0_H_
#include <string>
class Person // class declaration
{
private:
static const int LIMIT = 25;
std::string lname;
char fname[LIMIT];
public:
Person() {lname = ""; fname[0] = '\0';}
Person(const std::string & ln, const char * fn = "Hay you");
void Show() const;
void FormalShow() const;
};
#endif
#include <iostream>
#include <string>
#include "person0.h"
void Person::Show() const
{
using namespace std;
std::cout << fname << " " << lname << '\n';
}
void Person::FormalShow() const
{
using std::cout;
std::cout << lname << ", " << fname << '\n';
}
#include <iostream>
#include <string>
#include "person0.h"
int main()
{
using namespace std;
Person one;
Person two("Smythecraft");
Person three("Dimwiddy", "Sam");
one.Show();
cout << endl;
one.FormalShow();
cout << endl;
two.Show();
cout << endl;
two.FormalShow();
cout << endl;
three.Show();
cout << endl;
three.FormalShow();
cin.get();
cin.get();
return 0;
}
I am not really a C++ person, so the terminology might be wrong, but I would say that the implementation of the
Person::Person(const std::string & ln, const char * fn)
constructor is missing.