Can I initiate a string array and pass it as a function that initializes it. I know this sounds redundant, but basically I want to initiate a string array and then pass it to a variable so that I can use it later? Something like this:
This is the .h:
class ScreenBasics{
void setupAnswers(int &_numberOfAnswers, string *_answersText);
string *answersText;
{
This will be the implementation .cpp
void ScreenBasics::setupAnswers(int &_numberOfAnswers, string *_answersText){
answersText = _answersText; // this is where I get confused cause I don't know if I should initiate my string pointer using new like answersText = new string(_numberOfAnswers);
{
so in the main.cpp I can do something like this:
int main( ) {
ScreenBasics basics;
int numberOfAnswers = 4;
string newAnswers [] = { "Good", "Superb", "Great", "Perfect"};
basics.setupAnswers(numberOfAnswers, newAnswers);
// let's say I want to call some of those answers later
for ( int i = 0; i < numberOfAnswers; i++){
cout << basics.answersText[i] << endl;
}
}
Thanks!
Have you thougt about using structs? Both classes and structs can have a mixture of public and private members, can use inheritance, and can have member functions. I would recommend using structs as plain-old-data structures without any class-like features, and using classes as aggregate data structures with private data and member functions.
Your code would look like the following:
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
struct movies_t {
string title;
int year;
} mine, yours;
int main ()
{
string mystr;
mine.title = "2001 A Space Odyssey";
mine.year = 1968;
cout << "Enter title: ";
getline (cin,yours.title);
cout << "Enter year: ";
getline (cin,mystr);
stringstream(mystr) >> yours.year;
cout << "My favorite movie is:\n ";
printmovie (mine);
cout << "And yours is:\n ";
printmovie (yours);
return 0;
}
void printmovie (movies_t movie)
{
cout << movie.title;
cout << " (" << movie.year << ")\n";
}
Please let me know if you have any questions!
It sounds like your class should use a constructor to initialize the pointer.
class ScreenBasics
{
ScreenBasics(std::string* _answersText, std::size_t size)
: answersText(new std::string[size])
{
// copy values from _answersText to answersText
}
};
Note that since you are allocating a resource dynamically, you will need to implement The Rule of Three: that is, you need to create a copy-constructor, copy-assignment operator and destructor. This is because their default implementations do not semantocally conform to our requirements. For instance, the default copy-constructor and copy-assignment operator perform shallow copies (that is, they copy the pointer but not what it points to). Also, the destructor doesn't free the memory allocated my new[]. You will need to provide your own definition of the destructor that calls delete[].
Fortunately, all this can be avoided by using the standard library container std::vector, which is a dynamic array class that handles the memory allocation for you. The default implementations of the aforementioned constructors will correctly copy/copy-assign a vector if the need be:
class ScreenBasics
{
ScreenBasics(std:vector<std::string> _answersText)
: answersText(_answersText)
{
}
};
Notice that the size also didn't have to be passed as a parameter. A vector maintains its size internally.
Related
How can I create be object array of type Book in this program.
Tried to create the object but couldnt do it.Its driving me nuts. hence I need a litle help.
#include<iostream>
#include <algorithm>
using namespace std;
class BOOK{
private:
char bookname[20];
float bookprice;
public:
void getBookDetails()
{
cout<<"Enter the Book Name:";
cin>>bookname;
cout<<"Enter the Book Price:";
cin>>bookprice;
}
void displayDetails()
{
cout<<"Book Name:"<<bookname<<endl;
cout<<"Book Price:"<<bookprice<<endl;
}
};
bool comparator(string a, string b)
{
return a<b;
}
int main()
{
int Book=5;
string sortBook[]={"sandwich","apple","banana","zombie","pear"};
std::sort(sortBook,sortBook+Book,comparator);
for(int i=0;i<Book;i++)
{
cout<<sortBook[i]<<" ";
}
}
}
An object array of books would look like this:
int size = 5;
BOOK bookArray[size];
Major Problems
You are not using constructors
You are unnecessarily using char arrays
The string array 'sortBooks' should be a BOOK array (I assume?)
You declared a string array without including the string header file (probably the reason your code won't compile)
In my honest opinion, it seems that you are trying to solve a complex task without first mastering the basics of the language. I would highly recommend watching/reading a complete C++ tutorial, such as The Cherno's C++ Guide or NeuralNine's C++ Guide. Reading TutorialPoint's guides on C++ and The C++ Standard Library would also be helpful. Finally, if I had to recommend something more, I would recommend Sam's Teach Yourself C++, which helps you understand that language on a deeper level and covers many intricacies of the C++ language that beginners often overlook (note: I would not recommend using this book by itself, as it can be dry and difficult at times).
The reason your code isn't doing what you want is because you are not declaring an array of type BOOK, but of type string. Once you change the array to type book, you will run into two main problems:
Declaring an array of objects requires a default constructor.
Comparing classes requires operator overloading
Here is a good reference for learning about constructors. Essentially, a constructor is a special function that shares the exact same name as the class. When the class is declared, the constructor is automatically called. You should use a constructor to initialize the values instead of using the getBookDetails() function. If you used a constructor, you would just be able to write BOOK newBookObject("name", price)
Concerns
You are trying to sort an array of objects, which is difficult because objects are custom types, so the computer doesn't know how to compare two objects with a < (less than sign). Because of this, you would have to manually define how to compare the two objects (via operator overloading).
What You Need To Do:
Include the '<string>' Header File
Add #include <string> to the top of the file.
Change 'char bookname[20]' to 'string bookname'
I would not recommend using char arrays with classes, as it is difficult for a beginner. I agree with this question in that there's no reason to not using a string here, especially when you've already included the string library for the 'sortBooks' array you have at the bottom.
Add a Default Constructor
A default constructor is necessary to declare an array of objects.
BOOK()
{
bookname = ""
bookprice = 0.0
}
Add a Parameterized Constructor
A parameterized constuctor will allow you to declare a BOOK object like this:
BOOK newBook("book name here", price)
An Example:
BOOK newBook("Pride and Prejudice", 50.00)
BOOK(string book_name, double book_price)
{
bookname = book_name;
bookprice = book_price;
}
You can have two methods of the same name, as long as they have different parameters; this is called method overloading
Change the 'sortBooks' array to type BOOK
BOOK bookArray[5] { book1(title, price), book2(title, price) book3(title, price) book4(title, price) book5(title, price) };
Replace 'title' and 'price' with the appropriate titles and prices
Overload the '<' Operator
Comparing by Book Name
bool operator < (BOOK& otherBook)
{
return bookname < otherBook.bookname;
}
Comparing by Price
bool operator < (const BOOK& otherBook)
{
return bookprice < otherBook.bookprice;
}
Just some nitpicks/extra advice:
You don't have to name the data members 'bookname' and 'bookprice'. Since it's already in the context of a class, you could just write 'name' and 'price'.
As a beginner, you should always use doubles instead of floats, since floats have the possibility of introducing rounding errors.
Name classes using PascalCase
Finally, my code
I compiled this code on an Ubuntu Linux Subsystem using G++ (version: 9.3.0)
#include <iostream>
#include <string> //Include the 'string' header
#include <algorithm>
using namespace std;
class BOOK
{
//Private data members
private:
string bookname;
float bookprice;
//Public methods
public:
BOOK()
{
bookname;
bookprice = 0.0;
}
BOOK(string name, double price)
{
bookname = name;
bookprice = price;
}
void getBookDetails()
{
cout << "Enter the Book Name: ";
cin >> bookname;
//Add a 'cout << endl;' here
cout << "Enter the Book Price: ";
cin >> bookprice;
//Add a 'cout << endl;' here
}
void displayDetails()
{
cout << "Book Name: " << bookname << endl;
cout << "Book Price: " << bookprice << endl;
}
bool operator < (BOOK& otherBook)
{
return bookname < otherBook.bookname; //You can access private data members within the same class
}
};
int main()
{
int size = 5;
BOOK bookArray[5]; //an array of 5 'BOOK' objects
if (bookArray[0] < bookArray[1]) //Both have the same value, "" (the default value)
cout << "Item 1 is greater" << endl;
return 0;
}
The bellow code works fine unless I don't define destructor for the class.
But it produces wrong result when I define destructor . In the destructor part I freed up the memory that was created in constructor .I think its my job to do so . But in this case doing this make my program to run with undesired output. I am very frustrated with the program. Please help me out. I can not figure out any problem with the code. All things seem to okay for me.
Here I have made an array of objects of type list. Then I assigned values to the objects individually with the help of constructor. But it seems that the values are not getting initialize appropriately .But I think had not made any mistake there to initialization process. Then when I print the object data with member function display it could not produce the desire result. Although it prints the int and float data member properly. it can not print the char* data member properly.
#include <iostream>
#include <cstring>
#include <iomanip>
using namespace std;
class list
{
private:
char* name;
int code;
double cost;
public:
//constructor
list()
{
}
list(const char* name,int code,double cost)
{
int len=strlen(name);
this->name=new char[len+1];
strcpy(this->name,name);
this->code=code;
this->cost=cost;
}
//mem fun
void display(void)
{
cout.precision(2);
cout.setf(ios::fixed);
cout << setw(20) << this->name << setw(10) << this->code << setw (12) << cost << endl;
}
//destructor
~list()
{
delete[] this->name;
}
};
int main()
{
list item[3];
item[0]=list("Turbo C++",1001,250.95);
item[1]=list("C Primer",905,95.70);
item[2]=list("C++ Book",105,30);
cout << setw(20) << "NAME" << setw(10) << "CODE" << setw(12) << "COST" << endl;
for(int i=0;i<3;i++)
item[i].display();
return 0;
}
You are copying all your list items because you have an array of objects (not not pointers) - since it is just a "shallow copy" you have two instances with the same name pointer hence the "double free" message.
There are a couple of approaches to fix it:
You could define an operator= that makes a duplicate string. That
works but you still have unnecessary copies.
You could have an array of pointers in main (instead of instances).
You could have a set() method to set the values inside an existing instance (e.g. item[0].set("Turbo C++", 1001, 250.95); )
I want to output the values of the private class members Bankcode and AgentName. How can I do this from within my main() function, or in general, outside of the BOURNE class.
My initial code attempts are below:
#include <iostream>
#include <string>
using namespace std;
class BOURNE
{
string Bankcode ={"THE SECRET CODE IS 00071712014"} ; /*private by default*/
string AgentName={"Jason Bourne"}; /*private by default*/
public:
void tryToGetSecretCodeandName(string theName ,string theCode); //trying to get the private
void trytoGetAgentName( string name); // try to get name
};
//***********************defining member function**************************************
void BOURNE::tryToGetSecretCodeandName(string theName, string theCode) //member defining function
{
Bankcode=theCode; //equalling name to the code here
AgentName=theName; //the samething here
cout<<theCode<<"\n"<<theName; //printing out the values
}
//************************main function*****************************
int main()
{
BOURNE justAnyObject; //making an object to the class
justAnyObject.tryToGetSecretCodeandName();
return 0;
}
Third Answer
Your code has two 'getter' style functions, but neither one takes no arguments. That is, both of your functions require arguments to be passed.
Your main function is calling get...CodeandName(), which has no arguments. As such, you get a compiler error, probably complaining about valid signatures, or arguments passed.
Edited Answer
If you only want to get the values, the typical (as far as I am aware) implementation is something like
std::string BOURNE::getCode()
{
return Bankcode;
}
std::string BOURNE::getName()
{
return AgentName;
}
int main()
{
BOURNE myAgent;
cout<< "The agent's name is : " << myAgent.getName() << endl;
cout<< "The agent's code is : " << myAgent.getCode() << endl;
}
Original Answer, left in because I feel like it's more useful
I suspect what you're asking is if you could do something like
void BOURNE::tryToGetSecretCodeandName(string theName, string theCode)
{
if (Bankcode == theCode) {
cout<< "You correctly guessed the code : " << Bankcode << endl;
}
if (AgentName == theName) {
cout << "You correctly guessed the agent's name : " << AgentName << endl;
}
}
This will allow you to repeatedly guess at the name, and get output when you're correct.
If you wanted to disable this kind of guessing, then you could consider creating a new class (possibly derived from/based on std::string - but see this question for reasons to be careful!) and implement an operator== function which always returned false.
i am having trouble with my code. I am abit stumped.
I have a data member which is a pointer to a string type.
I use the constructor as a defualt initialer to this pointer, then when I call an object in the main function the intialised pointer to points to the memory address where the string is stored and prints the contents. That is what is supposed to happen, but I can't get the program to work. May somebody please tell me where I am going wrong?
#include<iostream>
#include<string>
using namespace std;
class NoName{
public:
NoName(string &sName("Alice In Wonderland") ){};
private:
string *pstring;
};
int main(){
//the constructor will be automatically called here once a object is created
// and the string "Alice in Wonderland" will appear on the screen
return 0;
}
Just simply use a std::string member and initialize it in Member initializer list:
private:
string mstring;
public:
NoName():mstring("Alice In Wonderland"){}
You could also let the constructor take in a parameter instead of hardcoding the string and let the user pass the string at run-time:
NoName(std::string str):mstring(str){}
You do not need a pointer. By using a pointer to std::string You nullify the advantages of implicit manual memory management offered by std::string.
If you really need to store a pointer for some reason, then there are some points to remember:
Pointers are initialized like new Class
Prefer to initialize class members in the member initializer list
Any time you write the word new think about where you're going to write delete. (In this case it goes in the destructor.
Rule of Three: If you need a destructor (you do, because of delete), then you also need a copy constructor and copy assignment operator.
This is one way your code could look: http://ideone.com/21yGgC
#include<iostream>
#include<string>
using std::cout; using std::endl;
using std::string;
class NoName
{
public:
NoName(string sName = "Alice In Wonderland") :
pstring(new string(sName))
{
cout << "ctor - " << *pstring << endl;
}
NoName(const NoName& rhs) :
pstring(new string(*rhs.pstring))
{
cout << "Copy ctor - " << *pstring << endl;
}
NoName& operator=(const NoName& rhs)
{
*pstring = *rhs.pstring;
cout << "Copy assignment operator - " << *pstring << endl;
return *this;
}
~NoName()
{
cout << "dtor, my name was " << *pstring << endl;
delete pstring;
}
private:
string *pstring;
};
.
int main()
{
NoName m, n("Another name");
NoName o(m);
o = n;
return 0;
}
Notice how much easier it is if you don't use the unnecessary pointer:
class Better
{
public:
Better(string sName = "Alice In Wonderland") :
m_string(sName)
{
}
private:
string m_string;
};
Because you don't need the custom destructor, you also don't need the copy constructor or copy assigment operator either. Much easier!
You're not using the constructor properly. First of all, you create this reference parameter and try to initialize it to a string object (that's asking for problems). Second, your constructor never actually does anything.
You need to call new on your pointer, dereference it and give the data pointed to a value, output the dereferenced value with std::cout and then clean the memory up with delete in the destructor (or in this case, you can do it after you use cout if you're not planning on using that string again. But do it in the destructor if you need it still).
Assuming you're doing this for a class, your textbook should tell you how to do these things.
EDIT: this is also not the default-constructor. I changed your tag to match appropriately.
Just beginning to learn about structs, I thought I understood how they work, using the dot operator to access a member of an object, but i clearly don't as the readEmployeeRecord function below doesn't work at all. How should i be doing this? (the code is short and self explantory)
Many thanks for taking the time to further explain structs to me! Naturally I tried google first but i couldn't find an example that inputted data quite the way i wanted and wasn't sure how i should be going about it.
#include <iostream>
#include <iomanip>
using namespace std;
//Employee type
struct Employee{
float wage;
char status;
char dept[4]; //for 3letter department, last position is \0 correct?
};
//function definitions
void readEmpoyeeRecord(Employee staff);
void printEmployeeRecord(Employee staff);
int main(){
Employee employeeA;
readEmpoyeeRecord(employeeA);
printEmployeeRecord(employeeA);
return 0;
}
void readEmpoyeeRecord(Employee employee){
cout << "Enter empolyees wage: ";
cin >> employee.wage;
cout << "Enter empolyees status (H or S): ";
cin >> employee.status;
cout << "Enter empolyees dept (ABC): ";
cin >> employee.dept;
}
void printEmployeeRecord(Employee staff){
cout << "Wage: Status: Department:" <<endl;
cout << fixed << setprecision( 2 ) << staff.wage;
}
First, try searching google for "passing parameters by reference and by value".
You'll learn that:
void readEmpoyeeRecord(Employee staff);
passes your variable to the function by value, meaning that a copy of your object is created and used inside the function, so your original object doesn't get modified, but a copy.
To get the desired result, use:
void readEmpoyeeRecord(Employee& staff);
Passing by reference means you pass that exact same object, and not a copy.
Your code will basically work like this:
//create new employee
Employee employeeA;
//call method readEmployeeRecord on a copy of employeeA
readEmpoyeeRecord(employeeA);
//call method printEmployeeRecord on a copy of employeeA
printEmployeeRecord(employeeA);
readEmpoyeeRecord(Employee employee) is copy by value, not reference, so you are loosing your changes.
Use readEmpoyeeRecord(Employee& employee) instead.
Your problem is that in C++, objects are passed by value until you specify otherwise. Thus, in the body of readEmpoyeeRecord you're dealing with a copy of employeeA, not with employeeA itself.
Pass a reference to your readEmpoyeeRecord function. The signature of readEmpoyeeRecord should read:
void readEmpoyeeRecord(Employee &employee)