Okay, so this is effectively the first C++ I have ever written. Consequently, my attempts to research this Segmentation Fault error have failed to yield a useful response that I can understand. Most suggestions say that I'm exceeding the heap memory, but I don't see how I could be in this code. Maybe I'm trying to reference something that I can't reference?
Can someone please take a look at this code and possibly tell me what is causing this error? The code compiles fine, it just throws this error when it runs. I have tried commenting out all the code involving vectors, and that didn't solve the problem. I'm guessing it's something stupid that I'm missing or just a concept about C++ that I don't understand. Either way, some insight would be much appreciated! Thanks in advance.
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
using namespace std;
const int DEFAULT_SIZE = 15;
//---------------------------------User----------------------------------------------------------------------------------
//User Interface Definition
class User
{
public:
User(string nameValue);
string getName();
string getWall();
string getHome();
private:
string name;
};
//User Implementation Definition
User::User(string nameValue) : name(nameValue)
{
}
string User::getName()
{
return name;
}
//---------------------------------Group----------------------------------------------------------------------------------
//Group Interface Definition
class Group
{
public:
Group(string nameValue);
string getName();
void addMember(User newMember);
private:
string name;
vector<User> members;
};
//Group Implementation
Group::Group(string nameValue) : name(nameValue)
{
}
string Group::getName()
{
return name;
}
void Group::addMember(User newMember)
{
members.push_back(newMember);
}
//---------------------------------MessageBuffer----------------------------------------------------------------------------------
//MessgeBuffer Interface Declaration
class MessageBuffer
{
public:
MessageBuffer();
void insert(string user, string recipient, string message);
string readByGroup(string groupName);
string readByUser(string userName);
string readPublic();
private:
string buffer;
};
//MessageBuffer Implementation
MessageBuffer::MessageBuffer() : buffer("")
{
}
void MessageBuffer::insert(string user, string recipient, string message)
{
buffer = "|<" + user + "::" + recipient + ">|" + message + buffer;
}
string MessageBuffer::readByGroup(string groupName)
{
return "Something";
}
string MessageBuffer::readByUser(string userName)
{
return "Something";
}
string MessageBuffer::readPublic()
{
return "Something";
}
//---------------------------------System-------------------------------------------------------------------------------
//System Interface Definition
class System
{
public:
System();
void start();
private:
bool running;
User currentUser;
MessageBuffer messageBuffer;
vector<User> users;
vector<Group> groups;
};
//System Implementation Definition
System::System() : running(false), currentUser(0)
{
}
void System::start()
{
running = true;
string userSelection;
cout << "===========================================================" << endl;
cout << "|\t Welcome to the Auburn Messaging System! \t |" << endl;
cout << "===========================================================" << endl;
while (running) {
cout << "1) Create a new user\n";
cout << "2) Broadcast a message\n";
cout << "3) Multicast a message\n";
cout << "4) Unicast a message\n";
cout << "5) Display Wall page\n";
cout << "6) Display Home page\n";
cout << "7) Create a new group\n";
cout << "8) Join a group\n";
cout << "9) Switch to a different user\n";
cout << "10) Quit Auburn Messaging System\n";
cin >> userSelection;
if (userSelection == "1")
{
running = false;
}
}
}
//----------------------------------------------------------------------------------------------------------------------
int main() {
cout << "Part 1";
System system1;
cout << "Part 2";
system1.start();
cout << "Part 3";
return 0;
}
In the System constructor, currentUser(0) is attempting to initialise a the first parameter of the User constructor (a string) with a literal zero which will be interpreted as a null char pointer.
The std::string constructor (look for basic_string<char> in the debugger) which constructs a string from a char* will be called with a null pointer, which it will dereference and invoke undefined behaviour.
Related
I am trying to develop a text adventure in C++ where users can input string commands (ex. "take apple").
Here is a very naive sample of code I came up with:
# include <iostream>
using namespace std;
class fruit{
public:
string actual_name;
fruit(string name){
actual_name = name;
}
take() {
cout << "You take a " << actual_name << "." << endl;
}
};
fruit returnObjectFromName(string name, fruit Fruits[]){
for(int i = 0; i <= 1; i++){ // to be modified in future depending on Fruits[] in main()
if (Fruits[i].actual_name == name)
return Fruits[i];
}
}
int main(){
string verb;
cout << "Enter verb: ";
cin >> verb;
string object;
cout << "Enter object: ";
cin >> object;
fruit apple("apple");
fruit Fruits[] = { apple }; // to be extended in future
// returnObjectFromName(object, Fruits). ??? ()
}
How can I possibly get the fruit method with something similar to the function returnObjectFromName, if this is even possible?
I began the development with Python (independently), and there I can at least use eval(), but as I understand in C++ this is not an option.
I tried also with map, but I didn't manage to make it work with methods.
Thank you all for your answers.
Its not good way to rely on reflection in C++ and i think there is no way to list methods in classes. Maybe you can use function pointers but pointer to instance methods are hell.
I recommend to use polymorphism and good design. If some items might be taken, then use interface like this:
#include <iostream>
using namespace std;
class ITakeable {
public:
virtual bool isTakeable() = 0;
virtual void take() = 0;
virtual void cannotTake() = 0;
};
class fruit : public ITakeable {
public:
string actual_name;
fruit(string name){
actual_name = name;
}
bool isTakeable() {
return true;
}
void take() {
cout << "You take a " << actual_name << "." << endl;
}
void cannotTake() {
cout << "not needed to be implemented";
}
};
class airplane : public ITakeable {
public:
string actual_name;
airplane(string name){
actual_name = name;
}
bool isTakeable() {
return false;
}
void take() {
cout << "not needed to be implemented";
}
void cannotTake() {
cout << "You CANNOT take a " << actual_name << "." << endl;
}
};
int main() {
fruit apple("apple");
if (apple.isTakeable()) {
apple.take();
}
airplane plane("boeing");
if (plane.isTakeable()) {
plane.take();
} else {
plane.cannotTake();
}
// use of interface in general
ITakeable * something = &apple;
if (something->isTakeable()) {
something->take();
}
something = &plane;
if (something->isTakeable()) {
something->take();
} else {
something->cannotTake();
}
return 0;
}
Since fruit is a user defined type, you have to declare your own methods for your type or you inherit from one previously defined.
There are a lot of method for "built-in" string type
that Performs virtually the same job as eval (...) in python.
Also I noticed your function need not be defined independently outside of class fruit.
I want to be able to have the user enter their name, store it and be able to recall it in different functions. This is my first code, first program. I am sure there is an easier way to do this, so if you could offer both an answer to the question and a easier way of accomplishing this task it would be much appreciated. Thank you in advance.
This is what I have so far:
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <string>
#include <sstream>
using namespace std;
void game();
void other();
class NameClass{
public:
string name;
};
int main()
{
int a;
int age;
string name;
cout << "Hello user, what is you name? \n\n";
/*Not sure if class and operator needs to be here. I was hoping that when the user
input the stream(their name) it would be stored in the class as well as being able
to use it in the main function.*/
NameClass person;
//This line is here to get name from user.
getline(cin, name);
cout << "Well " << name << ", are you having a good day? \n\n";
cout << "1=Yes 2=No \n\n";
cin >> a;
cout <<"\n";
if(a==1){
cout << "Well that is good to hear.\n\n";
}else{
cout << "I am sorry to hear that. I hope things get better for you. \n\n";
}
cout << "Do you want to play a game? \n\n";
cin >> a;
if(a==1){
game();
}else{
other();
return 0;
}
return 0;
}
void game(){
/*It is in this function that I want the be able to recall the name that the user input in the main function.*/
cout << "Cool "<< name <<",let get started." << endl;
}
void other(){
cout << "Well then "<< name <<", lets do something else.";
}
I assume you aren't aware of the OOP concepts.
Do this (make methods part of the class):
class NameClass{
public:
string name;
void game();
void other();
};
int main()
{
...
NameClass person;
getline(cin, person.name);
...
}
Or this (pass name as parameter):
int main()
{
string name;
...
game(name);
}
void game(string name)
{
cout << "Cool "<< name <<",let get started." << endl;
}
If you want to pass information from one function to another then you use a function parameter (or more than one).
void game(string name);
int main()
{
string name;
...
game(name);
}
void game(string name)
{
cout << "Cool "<< name <<",let get started." << endl;
}
It's a fundamental concept that pretty much all programming languages have.
Just pass the name as a parameter in both your functions, it should be something like this:
//functions
void game(string name);
void other(string name);
In your main function when you call either function just pass the name to it.
if(a == 1)
{
game(name);
}
else
{
other(name);
}
class Message {
public:
void changeSubject(string);
string getSubject();
private:
string subject;
};
void Message::changeSubject (string subjecto) //change subject{
subject = subjecto;
}
string Message::getSubject () //return subject {
return subject;
}
int main ()
{
Message person;
string aboutwhat;
cout << "Enter subject" << endl;
getline(cin, aboutwhat);
person.changeSubject(aboutwhat);
cout << person.getSubject();
return 0;
}
Above isn't the full code. The problem right now is that it prints "Enter Subject" and ends the program. Why am I not prompted to cin?
Your code as posted has several issues and doesn't compile. The following works for me
// Include al necessary headers:
#include <iostream>
#include <string>
// Either qualify the namespace of `std::string`, `std::cin`, etc
// or place a using statement like follows
using namespace std;
class Message {
public:
void changeSubject(string);
string getSubject();
private:
string subject;
};
void Message::changeSubject (string subjecto) //change subject
{ // <<< You have hidden the opening brace after the comment above
subject = subjecto;
}
string Message::getSubject () //return subject
{ // <<< You have hidden the opening brace after the comment above
return subject;
}
int main ()
{
Message person;
string aboutwhat;
cout << "Enter subject" << endl;
getline(cin, aboutwhat);
person.changeSubject(aboutwhat);
cout << person.getSubject();
return 0;
}
See the working sample here please.
Since you have stated in your question, "This isn't the full code", I'd suspect you have some error in the other parts that weren't shown.
"Why am I not prompted to cin?"
One likely possibility is you have had other inputs on cin before, that were invalid and cin got into fail() state.
To prevent this, you can put a cin.clear(); statement before the getline() call.
If you take inputs like e.g. numbers, you should check for validity like this
int x;
do {
cout << "Enter a number please: "
if(cin >> x) {
break;
}
cout << "Not a valid number, try again." << endl;
cin.clear();
} while(true);
Since your code above looks correct.
I would suggest you first get the prompting working first.
Then add back more code later.
I just tested the following in my own environment
#include <iostream>
#include <string>
main ()
{
std::string aboutwhat;
std::cout << "Enter subject" << std::endl;
std::getline (std::cin,aboutwhat);
std::cout << "Subject: " << aboutwhat << std::endl;
return 0;
}
Here is my code:
class LibItem
{
public:
virtual void PrintDetails() = 0;
virtual void setDetails() = 0;
void setTitle(string TitleName)
{
Title = TitleName;
}
string getTitle()
{
return Title;
}
void setReleaseDate(string date)
{
ReleaseDate = date;
}
string getReleaseDate()
{
return ReleaseDate;
}
void setAuthor(string AuthorName)
{
Author = AuthorName;
}
string getAuthor()
{
return Author;
}
void setCopyright(string CopyrightDetails)
{
Copyright = CopyrightDetails;
}
string getCopyright()
{
return Copyright;
}
void setGenre(string GenreDetails)
{
Genre = GenreDetails;
}
string getGenre()
{
return Genre;
}
void setStatus(string StatusDetails)
{
Status = StatusDetails;
}
string getStatus()
{
return Status;
}
private:
string Title;
string ReleaseDate;
string Author;
string Copyright;
string Genre;
string Status;
};
class Book : public LibItem
{
public:
Book(string TitleName)
{
setTitle(TitleName);
}
void setISBN(int ISBNDetails)
{
ISBN = ISBNDetails;
}
int getISBN()
{
return ISBN;
}
void setDetails(string setBookTitle, string setBookAuthor, string setBookReleaseDate, string setBookCopyright, string setBookGenre, string setBookStatus, int setBookISBN)
{
setTitle(setBookTitle);
setAuthor(setBookAuthor);
setReleaseDate(setBookReleaseDate);
setCopyright(setBookCopyright);
setGenre(setBookGenre);
setStatus(setBookStatus);
setISBN(setBookISBN);
}
void PrintDetails()
{
cout << "Title: " << getTitle() << endl;
cout << "Author: " << getAuthor() << endl;
cout << "Release Date: " << getReleaseDate() << endl;
cout << "Copyrite: " << getCopyright() << endl;
cout << "Genre: " << getGenre() << endl;
cout << "Status: " << getStatus() << endl;
cout << "ISBN: " << getISBN() << endl;
}
private:
Book();
int ISBN;
};
class DVD : public LibItem
{
public:
DVD(string TitleName)
{
setTitle(TitleName);
}
void setRunningTime(int RunningTimeDetails)
{
RunningTime = RunningTimeDetails;
}
int getRunningTime()
{
return RunningTime;
}
void setDirector(string DirectorDetails)
{
Director = DirectorDetails;
}
string getDirector()
{
return Director;
}
void setStudio(string StudioDetails)
{
Studio = StudioDetails;
}
string getStudio()
{
return Studio;
}
void setProducer(string ProducerDetails)
{
Producer = ProducerDetails;
}
string getProducer()
{
return Producer;
}
void setDetails(string setDVDTitle, string setDVDAuthor, string setDVDReleaseDate, string setDVDCopyright, string setDVDGenre, string setDVDStatus, int setDVDRunningTime, string setDVDDirector, string setDVDStudio, string setDVDProducer)
{
setTitle(setDVDTitle);
setAuthor(setDVDAuthor);
setReleaseDate(setDVDReleaseDate);
setCopyright(setDVDCopyright);
setGenre(setDVDGenre);
setStatus(setDVDStatus);
setDirector(setDVDDirector);
setStudio(setDVDStudio);
setProducer(setDVDProducer);
}
void PrintDetails()
{
cout << "Title: " << getTitle() << endl;
cout << "Author: " << getAuthor() << endl;
cout << "Release Date: " << getReleaseDate() << endl;
cout << "Copyrite: " << getCopyright() << endl;
cout << "Genre: " << getGenre() << endl;
cout << "Status: " << getStatus() << endl;
cout << "Running Time: " << getRunningTime() << endl;
cout << "Director: " << getDirector() << endl;
cout << "Studio: " << getStudio() << endl;
cout << "Producer: " << getProducer() << endl;
}
private:
DVD();
int RunningTime;
string Director;
string Studio;
string Producer;
};
I am having trouble with the virtual void setDetails();
I am wanting both the Book and DVD class to have a method called setDetails to set the details. The problem is, both the Book class and the DVD class have different arguments for this method.
How can I achieve this?
How is the best way to solve this problem?
Since
setDetails(string setDVDTitle, string setDVDAuthor, string setDVDReleaseDate, string setDVDCopyright, string setDVDGenre, string setDVDStatus, int setDVDRunningTime, string setDVDDirector, string setDVDStudio, string setDVDProducer)
only makes sense for a DVD object, and
setDetails(string setBookTitle, string setBookAuthor, string setBookReleaseDate, string setBookCopyright, string setBookGenre, string setBookStatus, int setBookISBN)
only makes sense for a Book, the methods shouldn't be virtual, nor in the base class.
Say I give you a LibItem* and I tell you to set its details. What do you do? Does it make sense to set its details, since they differ from one concrete implementing class to another?
The base class should only have the method that sets:
string Title;
string ReleaseDate;
string Author;
string Copyright;
string Genre;
string Status;
which shouldn't be virtual, since its behavior doesn't change from implementation to implementation, and you should set specific details on the implementing classes themselves.
The abstract base class can only contain functions that are common to all derived classes, so if you need different functions in different derived classes, they can't go in the base class.
You could downcast to get the derived type, and access its type-specific functions:
LibItem & item = some_item();
if (Book * book = dynamic_cast<Book*>(&item)) {
book->setDetails(book_details);
} else if (DVD * dvd = dynamic_cast<DVD*>(&item)) {
dvd->setDetails(dvd_details);
}
If you have many different types, and many type-specific operations, then it might be worth considering the Visitor pattern; but that's overkill in most situations.
you cant, you need common interface. http://www.tutorialspoint.com/cplusplus/cpp_interfaces.htm . This article will help you a lot in understanding of abstract classes. Member function which has different arguments for different childs shouldnt be virtual.
Looking into your code:
try to change your arguments type from "string" to "const string&" you will avoid copies.
virtual void LibItem::setDetails() = 0;
and
void Book::setDetails(string setBookTitle, string setBookAuthor, string setBookReleaseDate, string setBookCopyright, string setBookGenre, string setBookStatus, int setBookISBN)
and
void DVD::setDetails(string setDVDTitle, string setDVDAuthor, string setDVDReleaseDate, string setDVDCopyright, string setDVDGenre, string setDVDStatus, int setDVDRunningTime, string setDVDDirector, string setDVDStudio, string setDVDProducer)
are different methods, so, there is no overloading in your code.
BTW. Don't forget about virtual destructor in your LibItem...
There are two ways you could handle this. The first involves varargs,
declaring the interface in the base to be setDetails( std::string
const& title... ). I will not go further into this way, however, as it
is a sure path to unexplained crashes later down the road. The other
solution is to use something like: setDetails( std::map< std::string,
std::string > const& ), and in the concrete implementation extract the
details you want by name. Even then, I'm not sure it's a good solution,
since given a LibItem*, you don't know what to put in the map. (It
could be a valid solution if you get the type of object and the list
of details from the user. Even then, I'd probably encapsulate this into
a factory function, which would know the type it is creating, verify
that the details correspond, and then pass all of the details to the
constructor.)
And while I'm at it: you can't use an int for ISBN. The most reasonable representation is a string.
I'm very new to the program world and I am stuck at the moment. I'm suppose to design a bookrecord that contains the title, author, publisher, category (Dewey decimal), and date of publication. For booklist I need to know how to add a new bookrecord object, find a bookrecord given the title, remove a bookrecord object, and show all the bookrecord objects. For booklistUI, I need the menu, command processor, add records, remove records, display all records. I am sort of lost as to where I should begin how would I start it out? I do have some of it so far... is it correct?
This is what I have so far
/*
Title: CSU Bodie.cpp
Description: implements three classes to make a simple searchable list of the library holdings.
*/
#include <iostream>;
#include <string>;
#include <vector>;
using namespace std;
//Define a name class...
class ShortName {
string FirstName;
string LastName;
public:
ShortName(); //Define a default constructor...
ShortName(string, string); //...and an initializing one...
//Define some mutators...
void SetFirst(string First) { FirstName = First; }
void SetLast(string Last) { LastName = Last; }
//...and some accessors...
string GetFirst() { return FirstName; }
string GetLast() { return LastName; }
};
ShortName::ShortName()
{
FirstName = "";
LastName = "";
}
ShortName::ShortName(string First, string Last)
{
FirstName = First;
LastName = Last;
}
//Define a list class...
class ShortNameList {
vector<ShortName> List; //Create a specific sized list...
public:
ShortNameList() {;} //Nothing for it to do at this point...
void AddRecord(string, string);
void ShowList();
};
void ShortNameList::AddRecord( string First, string Last)
{
ShortName NameBuffer;
NameBuffer.SetFirst(First);
NameBuffer.SetLast(Last);
List.push_back(NameBuffer);
}
void ShortNameList::ShowList()
{
int K;
for(K = 0 ; K < List.size() ; K++)
cout << List[K].GetFirst() << " " List[K].GetLast() << endl;
}
class ShortNameUI {
ShortNameList Collection;
public:
ShortNameUI() {;}
void Menu();
void AddNewRecord();
void RunIT();
};
//This gives us options...
void ShortNameUI::Menu()
{
cout << "Choices..." << endl;
cout << "====================================================================" << endl;
cout << "\\tAdd.........allows the user to enter names." << endl;
cout << "\\tDisplay......shows the names." << endl;
cout << "\\tQuit.........terminates the program" << endl;
cout << "====================================================================" << endl;
}
void ShortNameUI::RunIT()
{
string Command;
while(true) {
Menu();
cout << "Command: ";
getline(cin, Command);
if(Command == "Quit")
break;
else if(Command == "Add")
AddNewRecord();
else if(Command == "Display")
Collection.ShowList();
}
}
void ShortNameUI::AddNewRecord()
{
string First, Last;
cout << "Enter Names Below, Stop To Quit" << endl;
while(true) {
cout << "First Name: ";
getline(cin, First);
if(First == "Stop")
break;
cout << "Last Name: ";
getline(cin, Last);
if(Last == "Stop")
break;
Collection.AddRecord(First, Last);
}
}
int main()
{
ShortNameUI NameList;
NameList.RunIT();
}
}
Yes, what you have is a good start - once you fix compilation.
Preprocessor directives are not statements so should not be terminated with ;
There is a stray } at the end of the file.
You seem get that adding the full book details will be much the same. The key thing is that you need to find a book from the title. The simplest thing to do is to change from a vector<> to store the books to a map<>.
typedef std::string Title;
class BookDetails
{
// etc.
};
typedef std::map<Title, BookDetails> BookCollection;
Look up the documentation on std::map<> to see how it used.
Please try to pass parameters as a reference instead of passing by values. For eg.
instead of
void SetFirst(string First);
try to use
void SetFirst(string& First);
better still, if you are sure that the value is not going to change inside the function use like this SetFirst(const string& First);
This will save you from grief later.
Is this a console application or windows application that you are developing? If Console application the UI will be straight forward, but if Windows application you have to use either MFC or pure Win32.