#include <iostream>
#include <vector>
using namespace std;
struct multa{
int data;
};
struct veiculos{
string placa;
vector<multa*> multas;
};
int tam = 0;
vector<veiculos*> carros;
void insereVeiculos(){
veiculos *carrosparaadd = new veiculos;
cout << "digite a placa do veiculo:" << endl;
cin >> carrosparaadd->placa;
carros.push_back(carrosparaadd);
cout << carros[].placa;
tam++;
}
void inseremultas(){
int cont = 0 ,i = 0;
cout << "Quantas multas vocĂȘ quer adicionar?" << endl;
cin >> cont;
for(i=0;i<cont;i++){
multa *multasparaadd = new multa;
cout << "Digite a data da multa para add:" << endl;
cin >> (*multasparaadd).data;
cout << (*multasparaadd).data;
carros[0]->multas.push_back(multasparaadd);
}
}
why can not I access the vector cars?
with carros[0].placa?I tested it and saw that it is getting the right value from the keyboard
Thanks.
Your expression
cout << carros[].placa;
lacks an index for the array access and since it's a vector of pointers you also need to dereference the accessed element. A correct expression which compiles is for example:
cout << carros[0]->placa;
If you want to print the element you just inserted, you can use either:
cout << carros.back()->placa;
or, since you're inserting a pointer, simply:
cout << carrosparaadd->placa;
Related
I'm trying to create a simple quiz with struct. But my program here is very repetitive. How can I modify it and make it more efficient? Especially to check if the answers are correct I do not want to declare a separate variable and store it as int correct. Thank You.
#include <iostream>
using namespace std;
struct Quiz{
string question;
string answers[3];
};
struct Quiz2{
string question2;
string answers2[3];
};
int correct;
int main()
{
Quiz Question;
Question.question = "What is the smallest county?";
cout << Question.question << endl;
Question.answers[0] = "1. USA";
cout << Question.answers[0] << endl;
Question.answers[1] = "2. India";
cout << Question.answers[1] << endl;
Question.answers[2] = "3. Vatican City";
cout << Question.answers[2] << endl;
cout << endl;
cout << "Choose 1-3: ";
cin >> correct;
if(correct == 3)
cout << "Correct!";
else
cout << "Incorrect!";
cout << endl;
cout << endl;
// Question 2
Quiz2 Question2;
Question2.question2 = "What is the biggest animal in the world?";
cout << Question2.question2 << endl;
Question2.answers2[0] = "1. Elephant";
cout << Question2.answers2[0] << endl;
Question2.answers2[1] = "2. Blue Whale";
cout << Question2.answers2[1] << endl;
Question2.answers2[2] = "3. Great white shark";
cout << Question2.answers2[2] << endl;
cout << endl;
cout << "Choose 1-3: ";
cin >> correct;
if(correct == 2)
cout << "Correct!";
else
cout << "Incorrect!";
return 0;
}
That's as much as non-repetitive as I can imagine after a few minutes of thinking. Maybe it can become smaller, but for my taste this looks alright.
You basically rely on std::vector class, instead of a typical array, because vectors can be of dynamic size. This allows us to use only one struct, but make as many answers as we want (3, 5, 10, whatever). We then create the whole quiz as another vector of questions. We're only left with printing to the console - for that we use loops, as our quiz structure is very simple and self-repetitive.
#include <iostream>
#include <vector>
using namespace std;
struct Question{
string question;
int correct_idx;
vector<string> answers;
Question(string question, int correct_idx, vector<string> answers)
:question(question), correct_idx(correct_idx), answers(answers)
{}
};
int main()
{
vector<Question> whole_quiz = {
Question{
"What is the smallest country?",
2, // indexes start from 0, e.g. 0, 1, 2. So 2 is correct
{"USA", "India", "Vatican City"}
},
Question{
"What is the biggest animal in the world?",
1,
{"Elephant", "Blue Whale", "Great white shark"}
},
};
for(auto question : whole_quiz) {
cout << question.question << endl;
for(int i = 0; i < question.answers.size(); ++i) {
cout << i+1 << ". " << question.answers[i] << endl;
}
cout << "Choose 1-" << question.answers.size() << endl << endl;
int guess;
cin >> guess;
if (guess-1 == question.correct_idx) {
cout << "Correct!" << endl << endl;
} else {
cout << "Incorrect!" << endl << endl;
}
}
return 0;
}
I would propose a more complicated, but also a more fun solution. Have a huge list of answers, like 100, or 1000, or as many as you like. Then in your struct have a std::string question, and std::vector<int> possible answers that are indexes in the huge list. First answer in the list is the correct one. So when you ask a question you pick first index, and three more indexes at random, and you shuffle them up, and present this to the user. The quiz will be different every time.
struct acts as a template, not a single variable. so there's no need to create 2 different struct. Also, a correct variable can be added to the struct for ease of checking.
Code (I split it into different functions for clearer understanding):
#include <iostream>
#include <string>
#include <vector>
using namespace std;
struct quiz
{
int correct;
string question;
vector<string> answers;
};
vector<quiz> questionsToAsk;
void addNewQuestion(string ques, vector<string>ans, int cor)
{
quiz q1;
q1.question = ques;
q1.answers = ans;
q1.correct = cor;
questionsToAsk.push_back(q1);
}
void displayQuestion(int idx)
{
quiz cur = questionsToAsk[idx];
cout << cur.question << '\n';
for (int i = 0; i < cur.answers.size(); i++)
{
cout << cur.answers[i] << '\n';
}
cout << "Choose 1-3: "; int inp; cin >> inp;
if (inp == cur.correct) {cout << "Correct";} else {cout << "Incorrect";} cout << '\n';
}
int main()
{
vector<string> ans1({"1. USA", "2. India", "3. Vatican City"});
vector<string> ans2({"1. Elephant", "2. Blue Whale", "3. Great white shark"});
addNewQuestion("What is the smallest county?", ans1, 3);
addNewQuestion("What is the biggest animal in the world?", ans2, 2);
for (int i = 0; i < questionsToAsk.size(); i++)
{
displayQuestion(i);
}
}
Result:
What is the smallest county?
1. USA
2. India
3. Vatican City
Choose 1-3: 1
Incorrect
What is the biggest animal in the world?
1. Elephant
2. Blue Whale
3. Great white shark
Choose 1-3: 2
Correct
You can use a template like
<typename T = int>
T get_answer(std::istream& in) {
T res;
in >> res;
return res;
}
...
if(get_answer(std::cin) == 3)
cout << "Correct!";
else
cout << "Incorrect!";
You can also overload operator<<.
#include <iostream>
#include <string>
template<typename T = int>
T get_answer(std::istream& in) {
T res;
in >> res;
return res;
}
class Quiz{
public:
Quiz(const std::string& q, const std::string& a1, const std::string& a2, const std::string& a3, unsigned correct)
: question(q), answers{a1, a2, a3}{
CheckAnswer(correct);
}
friend std::ostream& operator<<(std::ostream& os, const Quiz& quiz) {
os << quiz.question << "\n";
unsigned i = 1;
for (const auto & answer : quiz.answers) {
os << i++ << ". " << answer << "\n";
}
os << "\n";
return os;
}
void CheckAnswer(unsigned correct) {
std::cout << *this << "Choose 1-3: ";
if(get_answer(std::cin) == correct)
std::cout << "Correct!";
else
std::cout << "Incorrect!";
std::cout << std::endl;
std::cout << std::endl;
}
private:
std::string question;
std::string answers[3];
};
int main()
{
Quiz Question("What is the smallest county?", "USA", "India", "Vatican City", 3);
// Question 2
Quiz Question2("What is the biggest animal in the world?", "Elephant", "Blue Whale", "Great white shark", 2);
return 0;
}
The only thing you can do is define the correct variable in the struct itself. You can use a loop for decreasing the repetitiveness but obviously the question and the answers will have to be stored, it cannot be simplified further.
I have a program that takes in information through a struct and puts it into a vector, and I'm trying to print that information out but instead get an address. The structure should hold the values correctly so I think it's either my pointers or the way I'm printing it out.
#include <iostream>
#include <cstring>
#include<vector>
using namespace std;
struct student
{
char* fName;
char* lName;
int id;
float gpa;
};
void add(vector<student*>*);
int main()
{
vector <student*>* list = new vector<student*>();
if (strcmp(cmd,"ADD") == 0)
{
add(list);
}
else if (strcmp(cmd,"PRINT") == 0)
{
for(vector<student*>::iterator i = list->begin(); i != list->end(); i++)
{
cout << *i;
}
cout << "print" << endl;
}
}
void add(vector<student*>* paramlist)
{
student* s = new student();
s->fName = new char[25];
s->lName = new char[25];
cout << "Enter first name" << endl;
cin >> s->fName;
cout << "Enter last name" << endl;
cin >> s->lName;
cout << "Enter id number" << endl;
cin >> s->id;
cout << "Enter GPA" << endl;
cin >> s->gpa;
paramlist->push_back(s);
}
Or it might have something to do with the way I iterate through the vector.
You need to add an operator overload for your struct, to define how the struct should appear when printed. You also need to dereference the pointer as well as the iterator.
// Define how the struct should look when printed.
// This function makes it appear like:
// Name: John Smith, ID: 1235, GPA: 4.0
std::ostream &operator<<(std::ostream &os, const student &val) {
os
<< "Name: " << val.fname << " " << val.lname
<< ", ID: " << val.id
<< ", GPA: " << val.gpa
<< endl;
return os;
}
Then later...
for(vector<student*>::iterator i = list->begin(); i != list->end(); i++)
{
// Dereference twice, once for the iterator, and again for the pointer.
cout << **i << endl;
}
You have to dereference twice **i.
With *i you get the address of vector<student*> element that is student*.
You get student, you need other *.
You may use for (auto i: list) to make your life easier.
hello all i am working on a school prject called inventory inquisitor. the specifications are as follows:
enter image description here
so far i have created a class in which contains a struct and a vector of this struct.
all im trying to do so far is get the class to display the struct just to know it works but when i compile it and run it nothing happens. here is the code. excuse whatever rookie mistakes i have made i am very new with classes, and vectors. thanks you in advance!
//Inventory Inquisitor.cpp
#include <iostream>
#include <string>
#include <cctype> //for toupper
#include <fstream>
#include <vector>
using namespace std;
class Inventory
{
private:
struct item
{
string Description = " ";
double Quantity = 0;
double Wholesalescost = 0;
double Retailcost = 0;
string Dateadded = " ";
};
vector<item> Inv;
public:
void Display();
};
void Inventory::Display()
{
Inv[0].Description = "english";
Inv[0].Quantity = 1;
Inv[0].Wholesalescost = 100;
Inv[0].Retailcost = 200;
Inv[0].Dateadded = "3/8/2018";
cout << Inv[0].Description << endl;
cout << Inv[0].Quantity << endl;
cout << Inv[0].Wholesalescost << endl;
cout << Inv[0].Retailcost << endl;
cout << Inv[0].Dateadded << endl;
}
int main()
{
Inventory inst1;
inst1.Display();
}
You have to put something into the vector before accessing it:
// Create an item
item i;
i.Description = "english";
i.Quantity = 1;
i.Wholesalescost = 100;
i.Retailcost = 200;
i.Dateadded = 3/8/2018;
// The vector is empty, size() == 0
// Add it to the vector
Inv.push_back(i);
// Now the vector has 1 item, size() == 1
// Now you can print it
cout << Inv.at(0).Description << endl;
cout << Inv.at(0).Quantity << endl;
cout << Inv.at(0).Wholesalescost << endl;
cout << Inv.at(0).Retailcost << endl;
cout << Inv.at(0).Dateadded << endl;
According to your assignment, you will most likely change to function to print an existing item. You will have another function to add items to the vector.
void Inventory::Display(int index)
{
// Print an item already in the vector
if (index >= 0 && index < Inv.size()) {
cout << Inv.at(index).Description << endl;
cout << Inv.at(index).Quantity << endl;
cout << Inv.at(index).Wholesalescost << endl;
cout << Inv.at(index).Retailcost << endl;
cout << Inv.at(index).Dateadded << endl;
}
}
I am the new kid in the block, studying C++. I have loaded a file stream in a list container, using variables. I want to be able to access and change the value of any of those variables. I've been trying for weeks to no avail. Can somebody help?
This is the external text file: flightBoard1.txt
Delta 3431 Paris JFK
Usair 2275 EWR London
Delta 1500 Bonn Milan
This is the main.cpp
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <list>
using namespace std;
template<class T, class U, class V>
void changeFlight(list<string> &myFlight, T loc, U value, V newVal);
int main()
{
string _company;
int _flight;
string _origin;
string _destination;
list<string> flightBoard;
stringstream *ssPtr;
int counter = 0;
ifstream myFile("flightBoard1.txt");
while(myFile >> _company >> _flight >> _origin >> _destination ){
++counter;
ssPtr = new stringstream; // you want to put each line in a different slot in the flightBoard list object
*ssPtr << counter << " " << _company << "\t" << _flight << "\t" << _origin << "\t" << _destination << endl;
flightBoard.push_back(ssPtr->str()); // You need an arrow, this is a pointer
}
list<string>::iterator it;
for(it = flightBoard.begin(); it != flightBoard.end(); it++){
cout << *it ;
}
int oldFlight, newFlight;
cout << endl << "Enter old flight number: ";
cin >> oldFlight;
cout << "Enter new flight number: ";
cin >> newFlight;
changeFlight(flightBoard, ssPtr, oldFlight, newFlight);
delete ssPtr;
myFile.close();
return 0;
}
template<class T, class U, class V>
void changeFlight(list<string> &myFlight, T loc, U value, V newVal){
list<string>::iterator it;
cout << endl << "Flight: " << value << " has been changed to: " << newVal << endl;
for(it = myFlight.begin(); it != myFlight.end(); it++){
// THIS IS WHERE I AM HAVING A PROBLEM
// PLEASE UN-COMMENT BELOW TO SEE PROBLEM
/*if(it -> myFlight -> loc -> value){
value = newVal;
}*/
}
}
To solve your problem I think you should use the better structure for storage of your flights. string is not a good type if you need to manipulate data further. I suggest to introduce class Flight:
class Flight
{
public:
string company;
int flight;
string origin;
string destination;
Flight(const string& _company, int _flight, const string& _origin, const string& _destination)
: company(_company), flight(_flight), origin(_origin), destination(_destination)
{
}
string ToString() const
{
stringstream printer;
printer << company << "\t" << flight << "\t" << origin << "\t" << destination << endl;
return printer.str();
}
};
Also there are a number of problems in code snippet you have posted.
Memory leak inside while loop. You are allocating ssPtr = new stringstream; on each iteration, but delete it only once at the end.
changeFlight has too much template type arguments. If U value should be changed to V newVal inside changeFlight probably it should have the same types.
Hard to change type of flightBoard, list<string> copied everywhere. It's better to create typedef for list<string> type to make your code simpler. E.g. typedef list<string> FlightListType;.
Here is your code with all the mentioned problems fixed:
typedef list<Flight> FlightListType;
template<class T>
void changeFlight(FlightListType& myFlight, T value, T newVal);
int main()
{
string _company;
int _flight;
string _origin;
string _destination;
FlightListType flightBoard;
ifstream myFile("flightBoard1.txt");
while(myFile >> _company >> _flight >> _origin >> _destination )
{
flightBoard.push_back(Flight(_company, _flight, _origin, _destination));
}
FlightListType::const_iterator it;
int counter = 0;
for(it = flightBoard.begin(); it != flightBoard.end(); it++)
{
cout << counter << " " << (*it).ToString();
++counter;
}
int oldFlight, newFlight;
cout << endl << "Enter old flight number: ";
cin >> oldFlight;
cout << "Enter new flight number: ";
cin >> newFlight;
changeFlight(flightBoard, oldFlight, newFlight);
myFile.close();
return 0;
}
template<class T>
void changeFlight(FlightListType& myFlight, T value, T newVal)
{
FlightListType::iterator it;
cout << endl << "Flight: " << value << " has been changed to: " << newVal << endl;
for(it = myFlight.begin(); it != myFlight.end(); it++)
{
if ((*it).flight == value)
{
// TODO: Here you can do with the Flight what ever you need
// For example change it's number
(*it).flight = newVal;
}
}
}
I have this program, and I'm still getting used to C++ pointers, so It's probably an issue with that. But I am having the program crash when the getStructData() function is called. I've probably messed up something to do with the pointer to the struct that i've used, but I'm really not sure at this point. Any tips or help are appreciated. Thanks, and before people start the mad downvoting, this isn't a homework assignment from my school, I'm just going over other schools homework to practice during the christmas break.
Prog1Struct.h
#ifndef INCLUDED_PROG1STRUCT
#define INCLUDED_PROG1STRUCT
struct Prog1Struct
{
int m_iVal;
double m_dArray[5];
char m_sLine[80];
};
#endif
Prog1Class.h
#ifndef PROG1CLASS
#define PROG1CLASS
#include "Prog1Struct.h"
class Prog1Class
{
private:
Prog1Struct myStruct[5];
public:
/*Prog1Class();
~Prog1Class();*/
void setStructData();
void getStructData(int structureArrayIndex, struct Prog1Struct *info);
void printStruct(int indexPriv);
void printData();
};
#endif
Prog1Class.cpp
#ifndef INCLUDED_PROG1CLASS
#define INCLUDED_PROG1CLASS
#include <iostream>
#include <string>
#include "Prog1Class.h"
#include "Prog1Struct.h"
#include <time.h>
using namespace std;
void Prog1Class::setStructData()
{
for (int i = 0; i<5; i++)
{
cout << "Enter an integer: ";
cin >> myStruct[i].m_iVal;
for (int j = 0; j < 5; j++)
{
cout << endl << "Enter a double: ";
cin >> myStruct[i].m_dArray[j];
}
cout << endl << "Enter a string: ";
cin.ignore(256, '\n');
cin.getline(myStruct[i].m_sLine, 80, '\n');
cout << endl;
}
}
//takes in index for array, and pointer to a struct of the type in Prog1Struct.h. Copies all data from the private struct at the given index into the struct of the pointer argument.
void Prog1Class::getStructData(int structureArrayIndex, struct Prog1Struct *info)
{
*info = myStruct[structureArrayIndex];
cout << "Printing *info from getStructData function" << endl;
cout << info;
}
void Prog1Class::printStruct(int indexPriv)
{
cout << myStruct[indexPriv].m_iVal << " ";
for (int k = 0; k < 5; k++)
{
cout << myStruct[indexPriv].m_dArray[k] << " ";
}
cout << myStruct[indexPriv].m_sLine << " ";
}
int main(void)
{
Prog1Class c;
Prog1Struct *emptyStruct = '\0';
cout << "setStructData called:" << endl;
c.setStructData();
cout << "getStructData called:" << endl;
//error comes here, at getStructData.
c.getStructData(2, emptyStruct);
cout << "printStruct called:" << endl;
c.printStruct(2);
cin.get();
}
#endif
You are trying to assign a value to a null pointer.
Prog1Struct *emptyStruct = '\0';//set emptyStruct to 0 (This means it points at address 0, not holding a 0 value)
cout << "setStructData called:" << endl;
c.setStructData();
cout << "getStructData called:" << endl;
//error comes here, at getStructData.
c.getStructData(2, emptyStruct);//emptyStruct is still = 0
So in the function, info = 0.
void Prog1Class::getStructData(int structureArrayIndex, struct Prog1Struct *info)
{
*info = myStruct[structureArrayIndex];//This line is trying to write to a section of memory you don't have access to (address 0)
I think you want this instead. (untested) This will make info point to myStruct[structureArrayIndex] (Not copy the contents of myStruct[structureArrayIndex] to info). Pointers only point to things (like structs or some other type), they cannot contain a struct.
info = &myStruct[structureArrayIndex];