class vehicle{
private:
vector<string>carList;
public:
void info();
void displayCarInfo(vector<string>&carList);
}
void vehicle::info(){
char a;
string choice;
do{
cout<<"Please enter your car Reg number: ";
cin >> carPlate;
carList.push_back(carPlate);
cout << "Do you want to continue add car info(y/n)?";
cin >> choice;
}while(choice == "y");
}
void vehicle::displayCarInfo(vector<string>&carList){
for(int i = 0; i < 100; i++){
cout << carList[i];
}
}
//----------------------------------------------------------------
int main(){
vehicle a;
a.displayCarInfo(carList);
return 0;
}
Questions:
Error show when display all the car list. How to solve it?
And how I can retrieve information for particular element inside carList?
You don't need to pass the vector as an argument to void displayCarInfo();:
class Vehicle{ //<--- define classes starting with uppercase
private:
vector<string>carList;
public:
void info();
void displayCarInfo();
}; //<----- you need a semicolon here
The termination condition should be the vector size.
void vehicle::displayCarInfo(){
for(int i = 0; i < carList.size(); i++){
cout << carList[i];
}
}
The in the main():
int main(){
vehicle a;
a.displayCarInfo();
return 0;
}
If I consider that the and header files were included then too, the program has so many stray compilation errors. Did you not check those ??
Like: choice and carPlate was never declared. Class doesn't end with a ';' etc.
Issues: 1. You create a vehicle 'a' and never put anything in the member variables. I guess the info() function was supposed to do that, then why wasn't it called. I guess you'd need to do that in some loop.
You made the carList vector private and tried to pass the same as an argument from main to the displayCarInfo() func. I hope you realize that such a thing won't be required as being a member function to that same class it can access the carList directly. you simply need to call the public function using an object.
Since Vectors are unbounded (meaning their range can grow and shrink) it's not a good idea to print the content of an vector using a constant loop. That way you always risk a chance of either overrunning the loop or under-running it.
prefer
for vector<string>::iterator it = carList.begin(); it!= carList.end(); it++) std::cout << *it << std::endl;
Although there are smarter ways to do the same using ostream_iterators and std::copy, but that can rest for now.
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 months ago.
Improve this question
I created a class with students and groups. The group consists of the group name and the number of students. The student class consists of:
student name, price, and logical operation scholarship.
My main goal is to find the average of the grades received by students in their group. However, if a student's scholarship is - > false, then we don't count them. This is the main problem. I created both classes, combined them using a vector, wrote a program so that it would display the average scores of the groups, but when I turn on the program, the console only displays the name of the first group.
I want to clarify that this task is for a two-dimensional array. I just changed it to vectors to learn about the vectors (I don't know vectors well, but I will learn more about vectors in the future).
Here's my code:
#include <iostream>
#include <vector>
using namespace std;
class Student {
public:
string name;
double grade;
bool Grant;
Student() {
string is_Grant;
cin >> name >> grade >> is_Grant;
if (is_Grant == "true") {
Grant = true;
} else
Grant = false;
}
string GetName() {
return name;
}
double Get_Grade() {
return grade /** (Grant)*/;
}
};
class Group {
public:
string G_Name;
int count;
vector<Student> stud;
Group() {
cin >> G_Name >> count;
vector<Student> stud(count);
}
double GetAverage()
{
cout << "\n";
double avg = 0;
for (int i = 0; i < count; i++)
{
avg += stud[i].Get_Grade();
}
return avg / stud.size();
}
};
int main() {
int size;
cin >> size;
vector<Group> grp(size);
for (int i = 0; i < size; i++)
{
cout << grp[i].G_Name << ": Average is " << grp[i].GetAverage() << endl;
}
}
I want to know where I made a mistake. Maybe I forgot to add something?
First, I was using Void GetAvg() instead of a string. At that time, when I only typed in the number of inputs, the program stopped there.
I also tried creating a bool value as a separate function, but it wouldn't output either.
Most importantly, I want to know why the program doesn't find the average value.
So your code is super weird and I'm not sure it can ever work, but there is one obvious error
Group() {
cin >> G_Name >> count;
vector<Student> stud(count);
}
that should be
Group() {
cin >> G_Name >> count;
vector<Student> s(count);
stud = s;
}
Your version creates a local variable called stud which is a vector with the given size, but that has nothing to do with the stud that is a member variable in the Group class. My version uses a different name and then assigns that variable to stud.
This is still weird code, the code I originally wrote in the answer was the more natural
Group() {
cin >> G_Name >> count;
vector<Student> s(count);
stud.resize(count);
}
but this code doesn't work because your strange constructors. This version of the code only creates one Student which is then copied to fill in the vector. So you would end up with count identical students. More on this in the last paragraph.
The reason for your error is that when you call GetAverage you have some value for count but because of the bug the size of stud is still zero, so you are accessing that vector out of bounds and that (probably) is what is crashing your code.
And that brings up another issue with your code. One of the reasons vectors are superior to arrays is that vectors know their own size, and so variables like count are redundant, just query the vector for it's size. Rewriting your code to take advantage of that gives you something like this
class Group {
public:
string G_Name;
vector<Student> stud;
// no count in group
and this
Group() {
int count; // count is now a local variable
cin >> G_Name >> count;
vector<Student> s(count);
stud = s;
}
and this
double GetAverage()
{
cout << "\n";
double avg = 0;
for (int i = 0; i < stud.size(); i++) // get the count from the vector
{
avg += stud[i].Get_Grade();
}
return avg / stud.size();
}
But the elephant in the room is the way you do data input in your constructors. Don't do that. It means that every time you declare a variable the program is going to pause and ask the user for input. It also means that every student you do want to create has to be created with the default constructor, which is why my resize code doesn't work. Think about how restricting that is going to be going forward.
#include <iostream>
using namespace std;
class car{
string owner;
string car_num;
string issue_date;
car(string o, string cn, string id)
{
owner = o;
car_num = cn;
issue_date = id;
}
void getInfo()
{
cout << "Car's Owner's Name : " << owner << endl;
cout << "Cars' Number : " << car_num << endl;
cout << "Car's Issue Date : " << issue_date << endl;
}
};
int main()
{
int n;
cout << "Enter total number of cars stored in your garage : \n";
cin >> n;
car c1[n]; //incomplete code due to the issue
return 0;
}
Here I want to take the total car numbers from user. And also want to take the car properties from user by using a loop. But how Can I do that while using a constructor?
My advice is not to over use the constructor. It supposed to construct, and really should only construct. In your case, you don't even really need a constructor.
Instead add a new function to do initialization.
Traditional is to use an operator >> which is often an external function.
As for the loop...
car c1[n]; //incomplete code due to the issue
is not legal C++ (although it's allowed in C, and many compilers that are also C compilers)
It's better to use a vector. So...
vector<car> c1(n);
for (auto& c : c1)
cin >> c;
An advanced technique is to use a istream iterator, which will allow you to use algorithms like std::copy, calling the input operator for each member of the vector. However, it's really not required, just a "nicety"
car c1[n]; //incomplete code due to the issue
In fact, you have 2 issues here:
Variable-Length Arrays (VLA) are not allowed in standard C++. They
are optionally allowed in standard C, and are supported by some
C++ compilers as an extension.
You can't have an array of objects w/o default constructor (unless you fully initialize it).
Assuming you don't want to change the class (other than insert public: after the data members), the modern solution should use std::vector:
std::vector<car> c;
//incomplete part
for(int i = 0; i < n; i++){
std::string owner, car_num, issue_date;
//TODO: get the strings from the user here ...
c.emplace_back(owner, car_num, issue_date);
}
Use pointer array instead.e.g.
car* c1[n];
//incomplete part
for(int i = 0; i < n; i++){
//take input and process
c1[i] = new car(//put processed inputs here);
}
PS: I feel like I made a mistake somewhere but can't test it now. If it doesn't work, put a comment here.
You can use loop with std::cin, likefor(int i=0;i<n;++i){std::cin<<num;}. The 'n' I mentioned in the code can also be assigned by std::cin
int n;
std::cin>>n;
car* cars=new car[n];
for(int i=0;i<n;++i)
{
std::getline(cars[i].owner,std::cin);
// and something other you'd like to do, like to test its validity
}
#include <iostream>
using namespace std;
class car{
public:
string owner;
string car_num;
string issue_date;
void cars(string o, string cn, string id)
{
owner = o;
car_num = cn;
issue_date = id;
getInfo();
}
void getInfo()
{
cout << "Car's Owner's Name : " << owner << endl;
cout << "Cars' Number : " << car_num << endl;
cout << "Car's Issue Date : " << issue_date << endl;
}
};
int main()
{
int n;
string a,b,c;
cout << "Enter total number of cars stored in your garage : \n";
cin >> n;
car cas[n]; //incomplete code due to the issue
for(int i=0;i<n;++i)
{
cout<<"value1:";
cin>>a;
cout<<"value2:";
cin>>b;
cout<<"value3:";
cin>>c;
cas[i].cars(a,b,c);
}
return 0;
}
I am learning c++ and I can't wrap my head around this problem. I have created a class object which hold information of a vehicle. And the class name is vehicle. Here is the class:
class vehicle {
private:
string vehicleNumber;
int vehicleType;
public:
//Default Constructor
vehicle();
//Overload Constructor - #params<vehicleNumber, vehicleType>
vehicle(string vehicleNo, int type){
vehicleNumber = vehicleNo;
vehicleType = type;
}
//Some stuff to test
string getNo(){
return vehicleNumber;
}
int getType(){
return vehicleType;
}
};
And now in my main I have a void method which then takes in user input and puts the object in a vector. So in my main:
//Ref
void storeVehicle(vector<vehicle>&);
void storeVehicle(vector<vehicle>& createNewVehicle){
string number;
int type;
cout << "Enter Vehicle Number: ";
cin >> number;
cout << "Enter the vehicle type: ";
cin >> type;
vehicle newV(number, type);
createNewVehicle.push_back(newV);
cout << endl;
}
//
Now here is the problem I am facing. Inside of my main method, I am creating the object. And this works perfectly find except if I call the main method again, it initializes the object again and I loose my previous data. I am not sure how to tackle this.
Here is the main method:
int main(){
vector<vehicle> newVehicle;
storeVehicle(newVehicle);
return main();
}
So here I am returning main() again so that it reruns. But when it does, i loose my previous vector which held the data. Now how can I keep the data and keep calling the storeVehicle method?
Edit
I also have a switch case which I am using to determine what the user chooses as an option. It may be to display the vehicle information or it maybe to add a new vehicle. In this case too, how can I add the vehicle without loosing previous data. Here is my switch which is inside another method:
void mainMenu(){
int option;
cin >> option;
switch(option){
case 1: {
vector<vehicle> newVehicle;
storeVehicle(newVehicle);
break;
}
default:
cout << "Wrong option";
}
}
So now in my main method, I am simply calling this switch method. Either way, I loose the data yes?
EDIT
I don't understand why people keep downvoting. Aren't we all here to learn? And yet I get a downvote. Sooner or later, stackoverflow decides to block me from asking questions.
Main isn't intended to be used like that, it's just an entry point for your application.
For what you're looking to do, you would be interested in looping. This way a certain section of your code can be ran repeatedly until a condition is met.
int main(){
vector<vehicle> newVehicle;
while(true)
{
storeVehicle(newVehicle);
}
return 0;
}
Take a look at how different loop types work. https://www.tutorialspoint.com/cplusplus/cpp_loop_types.htm
Also, the one in my example is an infinite loop, since the condition is always true.
EDIT The question was changed.
The problem is that each time you call the mainMenu function that the vector is recreated. Create the vector in your Main function and then pass it by ref into the mainMenu function, so that it can then be passed into your storeVehicle function.
int main()
{
vector<vehicle> newVehicle;
while (true)
{
mainMenu(newVehicle);
}
return 0;
}
void mainMenu(vector<vehicle>& createNewVehicle) {
int option;
cin >> option;
switch (option) {
case 1: {
storeVehicle(createNewVehicle);
break;
}
default:
cout << "Wrong option";
}
}
You'd have to add a header for this function to work.
#include <limits>
void storeVehicle(vector<vehicle>& createNewVehicle) {
string number;
int type;
cout << "Enter Vehicle Number: ";
cin >> number;
cout << "Enter the vehicle type: ";
cin >> type;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
vehicle newV(number, type);
createNewVehicle.push_back(newV);
cout << endl;
}
Could someone please explain how to bring a value from a variable in one function to another function. I know that as soon as the function ends that variable's value in the function is cleaned out. But how do I tell it not to do that.
I am trying to bring the int ppl; value from the candidates function into the votes function. But as you can see it won't do it on its own.
void candidates()
{
int ppl;
cout << "Hello please how many candidates are there?: ";
std::cin >> ppl;
string *cans = new string[ppl];
for (int i = 0; i < ppl; i++)
{
cout << "Please type in the last name of candidate number: " << i + 1 << endl;
cin >> cans[i];cout << endl << endl;
}
for (int a = 0; a < ppl; a++)
{
cout << cans[a] << endl << endl;
}
}
void votes()
{
int *vote = new int[ppl];
// ...
}
The pattern you want is probably:
std::vector<string> gather_data() {...}
void use_data( std::vector<string> data ) { ... }
And then you can do:
auto data = gather_data();
use_data( data );
It would be better practice to make sure that use_data can't modify its argument, and that this argument is passed by reference. So:
void use_data( const std::vector<string>& data ) { ... }
A more advanced pattern would be to use a class:
class Foo {
std::vector<string> data;
public:
void gather() {...}
void use() {...}
}
Foo myFoo;
myFoo.gather();
myFoo.use();
In this case you can see that Foo's instance methods have access to its data.
You certainly don't want to be using global variables without very good reason.
However, if you're asking a question at this basic level, it means you need to read a book.
You will find it is impractical to try learning what is one of the most difficult languages around just by asking questions. Each answer will raise 10 more questions.
Use return:
int candidates()
{
int ppl;
std::cin >> ppl;
...
return ppl;
}
Function candidates() now receives an int so now you can do this:
void votes()
{
int *vote = new int[candidates()];
}
You can also use global variables, or pass the variable ppl as int& to function candidates() as argument, so ppl had to be created out of the function (let's say in main function), therefore it's available for every function you need.
Please guide me with this.I have to write a program containing a class called VectorCollection that will be used to store a collection of vectors whose instances are of type string. I get the following error
no match for operator<< in std::cout
when i try to output the vector using cout << (*it) << endl;
I was a bit reluctant to put the full assignment question up on the forum but to avoid confusion here it is. I think i might be totally off track so any guidence will be appriciated.
Write a cpp program containing a class called VectorCollection that will be used to store a collection of vectors whose instances are of type string.
Write a single parameter constructor that receives an array of strings for initializing values in the collection.
Add functions to add instances to the collection, remove instances from the collection, delete all entries from the collection and display the entire collection.
Also overlad the * operator so that it returns the intersection of two VectorCollection objects.
Write a program to test all member functions and overloaded operators in your class.
Next, modify the main function so that instead of creating seperate variables for each Movie object, an array of at least 4 Movie objectsis created with sample data. Loop through the array and output the name, MPAA rating and average rating for each of the four movies.
//movies.h
//******************************************************************************************************
using namespace std;
#ifndef movies_H
#define movies_H
class VectorCollection
{
//member variables
string newtitle,newgentre,newmpaa,newrating;
vector<VectorCollection> movies;
public:
//function declarations
//default constructor
VectorCollection();
//overload constructor
VectorCollection(string,string,string,string);
//destructor
~VectorCollection();
void settitle(string);
void setgentre(string);
void setmpaa(string);
void setrating(string);
void display(vector<VectorCollection>);
};
#endif // MOVIES_H_INCLUDED
//movies.cpp
//******************************************************************************************************
//constructor definition
VectorCollection::VectorCollection()
{
}
//overloaded constructor def
VectorCollection::VectorCollection(string title,string gentre,string mpaa,string rating)
{
newtitle = title;
newgentre = gentre;
newmpaa = mpaa;
newrating = rating;
}
//destructor def
VectorCollection::~VectorCollection()
{
}
//mutator function
void VectorCollection::settitle(string title)
{
newtitle = title;
}
//mutator function
void VectorCollection::setgentre(string gentre)
{
newgentre = gentre;
}
//mutator function
void VectorCollection::setmpaa(string mpaa)
{
newmpaa = mpaa;
}
//mutator function
void VectorCollection::setrating(string rating)
{
newrating = rating;
}
void VectorCollection::display(vector<VectorCollection> movies)
{
vector<VectorCollection>::iterator it;
for ( it = movies.begin(); it < movies.end(); ++it)
{
//copy(movies.begin(),movies.end(),ostream_iterator<string>(cout," "));
cout << (*it) << endl;
}
}
//main.cpp
//******************************************************************************************************
#include <iostream>
#include <string>
#include "movies.h"
using namespace std;
int main()
{
string title,gentre,mpaa,rating;
vector<VectorCollection> movies;
movies.assign(4,VectorCollection());
VectorCollection *a_movie;
VectorCollection list;
for (int i = 0; i < 3; i++)
{
cout << "Enter the title : ";
cin >> title;
cout << "Enter the gentre: ";
cin >> gentre;
cout << "Enter the MPAA: ";
cin >> mpaa;
cout << "Enter the rating: ";
cin >> rating;
a_movie = new VectorCollection;
a_movie ->settitle(title);
a_movie ->setgentre(gentre);
a_movie ->setmpaa(mpaa);
a_movie ->setrating(rating);
movies.push_back(*a_movie);
cin.get();
}
list.display(movies);
return 0;
}
Besides all the other problems already pointed out, you have a std::vector<VectorCollection> in your VectorCollection class.
Standard containers cannot hold incomplete types. If you want to do this, you should have a vector of pointers to VectorCollection or use boost::ptr_vector which is designed specifically to hold pointers to classes.
Boost.Container will also allow you to do what you're trying.
You have a vector of VectorCollections. There is no << ostream operator for your VectorColections object defined. To be able to print contents of your own class using << operator you have to properly implement it for your class.
You may find an answer how to do it here:
How to properly overload the << operator for an ostream?
You need to provide an output stream operator for VectorCollection:
std::ostream& operator<<(std::ostream& os, const VectorCollection& v)
{
return os << "booh!";
}