bad access error when pushing back vector - c++

I have these two classes:
class card { //class that represents a card
int cardNumber; //the ID of the card that give it itse level and suit
std::vector<std::string> suits = { "hearts", "spades", "diamonds", "clubs" };
std::vector<std::string> levels { "Ace", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King"};
std::string suit;
std::string level;
public:
card(int nCardNumber) { //constructor that initiliazes all properties of the card
cardNumber = nCardNumber;
level = levels[cardNumber%13];
suit = suits[cardNumber/13];
}
void printValue() { //prints the cards level and suit
using namespace std;
cout << level << " of " << suit << endl;
}
};
and
class hand { //represents the hand a player is holding
int playerNumber;
std::vector<card> playerHand; //vector of carsa
public:
hand(int m_playerNumber) {
playerNumber = m_playerNumber;
}
void addCard(int cardNumber) { //adds a card to the hand
card cardToBeAdded(cardNumber);
cardToBeAdded.printValue();
playerHand.push_back(cardToBeAdded);
}
void printHand() {
using namespace std;
cout << "Player " << playerNumber << " has:" << endl;
for (int i = 0; i < 2; i++) {
playerHand[i].printValue();
}
}
};
and whenever I call the addCard function in hand, I get EXC_BAD_ACCESS (code=1).
I've tried some debugging by declaring two members in the playerHandVector and changing the function to rewrite those values as opposed to appending new ones to the vector, but same error.
Any help would be appreciated!

With some proper debugging, it's pretty easy to see what's going on. I've reduced your example to the very minimum that will reproduce your bug, because I don't believe it's to do with std::vector::push_back.
#include <iostream>
#include <vector>
#include <string>
class card { //class that represents a card
int cardNumber; //the ID of the card that give it itse level and suit
std::vector<std::string> suits = { "hearts", "spades", "diamonds", "clubs" };
std::vector<std::string> levels { "Ace", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King"};
std::string suit;
std::string level;
public:
card(int nCardNumber) { //constructor that initiliazes all properties of the card
cardNumber = nCardNumber;
std::cout << cardNumber % 13 << std::endl;
std::cout << cardNumber / 13 << std::endl;
level = levels[cardNumber%13];
suit = suits[cardNumber/13];
}
void printValue() { //prints the cards level and suit
using namespace std;
cout << level << " of " << suit << endl;
}
};
int main() {
std::vector<card> v;
for (size_t n = 0; n <= 52; ++n)
{
// Replicate "addCard" function
card c(n);
c.printValue();
v.push_back(c);
}
return 0;
}
You'll notice two things here: I've added some debugging help to the card constructor because I believed the problem was the access of the std::vector<std::string> and I'm attempting to add all 52 cards. 'lo and behold, the first 51 cards add successfully; however, trying to add the king of clubs has an error. Let's see why:
card(int nCardNumber) { // nCardNumber = 52;
cardNumber = nCardNumber; // 52
const int nCard = cardNumber % 13; // King
const int nSuit = cardNumber / 13; // 4
level = levels[nCard];
suit = suits[nSuit]; // whoops, out of bounds!
}
You can see here that you are trying to access the suits[4] which is out of bounds.

You probably have some code (which you haven't shown) which is using cardNumber as an array index, not cardNumber % 13 or similar and going out of array bounds.
Using cardnumber/13 as an array index will also fail if cardNumber is 52 or more.
Also .....
suits and levels are non-static members of card, so every instance of card will have its own copy of those vectors.
I wouldn't expect a problem to occur with every call of hand::addCard() but, if your code is creating lots of hands, adding lots of cards to them, and not cleaning up - then it will exhaust available memory quicker than you probably intend.
If you are then running into limits on available memory (that depends on you OS, available RAM, etc) then that would explain your problem.

This compiles and runs "correctly" on Visual Studio 2013 Community. Well, except that VS2013 doesn't do member initalizer lists so I had to, ugh, type those out. The only way I could get an error was to have a value outside of the obvious range of cards (>52, <0). Is that what you're doing?
Other issues: normal card decks don't have a '1' card, delete the 1 from the levels vector. After doing that, run this in main:
for (int i = 0; i < 52; ++i)
playerHand.addCard(i);
On mine it spits out all the cards, A to K, for all 4 suits, in order. However if I give it a value outside of those bounds it will give an error.
It's safer to get a value from the vector using vector.at(index) than the [] operator. The [] operator on a vector treats it just like a raw C-array, so if you don't have some kind of debugger running to catch it, it'll be undefined behavior if you feed it an inappropriate value. That means if you're lucky it crashes with no explanation. One of the advantages of a vector is that you can use the at method to summon the index, and throw an exception with a pretty clear name.
Also, if you have a function that calls for user input and it's possible to feed wrong numbers (as it is in this case), then it's a good idea to check the input to make sure it's good.
As Peter points out, using vectors in the class just to hold labels is inelegant, and wastes memory. An easy solution would be to make the variables:
static std::vector<std::string suits...
The static keyword means, among other things that you should definitely look into, that they will only be created once and persist across all instances of the class.

Related

How to transfer objects from an array of objects to another in C++?

I have an array of objects and I want to transfer the objects to another array. I've written the code bellow to do so but it did not work. It is basically a code where 52 card objects are created in one array and distributed between two arrays.Can anyone help me?
class card
{
public:
string suit;
string value;
void setValue(string v);
void setSuit(string s);
};
void card::setValue(string v)
{
value=v;
}
void card::setSuit(string s)
{
suit=s;
}
int main()
{
string suites[]={"Spades","Hearts","Diamonds","Clubs"};
string values[]={"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
card cards[52];
int i=0;
for(int j=0;j<4;j++){
for(int k=0;k<13;k++){
cards[i].setSuit(suites[j]);
cards[i].setValue(values[k]);
i++;
}
}
card player1_cards[26];
card player2_cards[26];
for(int a=0;a<52;a++){
if(a%2==0){
player1_cards[a]=cards[a];
}
else{
player2_cards[a]=cards[a];
}
}
return 0;
}
If you want every 2nd card to be added to player1_cards and the others to be added to player2_cards you can change your for-loop to:
for(int a=1;a<26;a++) {
player1_cards[a] = cards[2*a];
player2_cards[a] = cards[2*a-1];
}
As Eljay said in the comment to your question your index went past the end of the array.
I tried to compile the code myself and it seems like the following code splits the cards in to two different arrays, althought it is not random (which you might want to add if you are doing a card game).
#include <iostream>
#include <string>
class card
{
public:
std::string suit;
std::string value;
void setValue(std::string v);
void setSuit(std::string s);
std::string printSV();
};
void card::setValue(std::string v)
{
value=v;
}
void card::setSuit(std::string s)
{
suit=s;
}
std::string card::printSV() {
return suit + ": " + value + "\n";
}
int main()
{
std::string suites[]={"Spades","Hearts","Diamonds","Clubs"};
std::string values[]={"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
card cards[52];
int i=0;
for(int j=0;j<4;j++){
for(int k=0;k<13;k++){
cards[i].setSuit(suites[j]);
cards[i].setValue(values[k]);
i++;
}
}
card player1_cards[26];
card player2_cards[26];
for(int a=1;a<26;a++){
player1_cards[a] = cards[2*a];
player2_cards[a] = cards[2*a-1];
// prints the suite and value for each card in player1's and player2's hand.
std::cout << player1_cards[a].printSV();
std::cout << player2_cards[a].printSV();
}
return 0;
}
Outputs Suite: Value for each of the cards in cards[52].
As #Eljay notes, you are trying to access elements past the end of the arrays. If you were to use a debugger to step through your program, you would see this.
However, this is also a lesson for you to be careful of writing raw loops, with a lot of "magic-number" indices, and prefer using pre-existing patterns from the libraries (especially std::algorithm) when relevant. See this talk by Sean Parent about this general principle.
Specifically, you could have written your program as follows:
#include <range/v3/view.hpp>
#include <string>
#include <array>
#include <iostream>
struct card {
std::string suite;
std::string value;
};
std::ostream& operator<<(std::ostream& os, const card& c)
{
return os << c.value << " of " << c.suite;
}
int main()
{
using namespace ranges;
std::array suites {"Spades","Hearts","Diamonds","Clubs"};
std::array values {"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
auto cards =
views::cartesian_product(suites, values) |
views::transform([](const auto& suite_and_value) -> card {
return { std::get<0>(suite_and_value), std::get<1>(suite_and_value) };
});
auto num_players { 2 };
auto player1_cards =
cards | views::stride(num_players);
auto player2_cards =
cards | views::drop(1) | views::stride(num_players);
std::cout << "Player 1 got: " << player1_cards << '\n';
std::cout << "Player 2 got: " << player2_cards << '\n';
}
in which case you don't use any loops and any index variables. This uses Eric Niebler's ranges-v3 library. See also this quick reference to understand faster what's going on in this code if you're not familiar with the terms.
See this Live on GodBolt.

Vector Isn't Creating Multiple Class Objects

I have a vector that stores multiple class objects for later access. This way my program can create new objects during runtime. This is done like so:
vector<Person> peopleVector;
peopleVector.push_back(Person(name, age));
for (int i = 0; i < peopleVector.size(); i++) {
cout << peopleVector[i].name << endl;
}
This function should print out each objects "name" every time the code runs (it's a function that runs multiple times). However, when I run this, somehow the vector does not increase in size. If you add cout << peopleVector.size(); to that code, you will find that each time it runs, it gets one (obviously assuming you also have the class code which I have below).
I'm curious why I can't create multiple objects in the class.
Class.h
#pragma once
#include <iostream>
using namespace std;
class Person {
public:
Person(string personName, int personAge);
string name;
int age;
};
Person::Person(string personName, int personAge) {
name = personName;
age = personAge;
}
Main.cpp
#include "Class.h"
#include <random>
int main() {
// Necessary for random numbers
srand(time(0));
string name = names[rand() % 82]; // Array with a lot of names
int age = 4 + (rand() % 95);
}
// Create a new person
void newPerson(string name, int age) {
vector<Person> peopleVector;
peopleVector.push_back(Person(name, age));
for (int i = 0; i < peopleVector.size(); i++) {
cout << peopleVector[i].name << endl;
}
}
Just FYI those #includes might be a little bit off because I took that code out of a large section that had like 15 includes.
You are creating an empty vector each time you call your newPerson() function, and then you add a single person to it.
You then display the contents of that vector. What else can it contain, other than the single person that you added?
Problem
Every time a function runs, all local variables inside the function are re-created in their default state. That means that every time you call newPerson, it just recreates peopleVector.
Solution
There are two solutions:
Have newPerson take a reference to a vector, and add it on to that
make peopleVector static, so that it isn't re-initialized every time
First solution:
// Create a new person; add it to peopleVector
// The function takes a reference to the vector you want to add it to
void newPerson(string name, int age, vector<Person>& peopleVector) {
peopleVector.push_back(Person(name, age));
for (int i = 0; i < peopleVector.size(); i++) {
cout << peopleVector[i].name << endl;
}
}
Second solution: mark peopleVector as static
// create a new person; add it to peopleVector
void newPerson(string name, int age) {
// Marking peopleVector as static prevents it from being re-initialized
static vector<Person> peopleVector;
peopleVector.push_back(Person(name, age));
for (int i = 0; i < peopleVector.size(); i++) {
cout << peopleVector[i].name << endl;
}
}

void class Arrays Sequential and Binary Search Using

I'm currently at my wits end trying to figure out how to do this, and was hoping someone could help.
The objectives the assignment is to:
Display the original sorted array of student records.
Display the sequential search result of student records.
Display the binary search result of student records.
The Full Instructions are:
a. Create three array of 12+ students records including ID’s, student names, and
the corresponding e-mail address’,– student ID’s are sorted in order. (No sort program needed for now.)
b. Sequential Search five ID’s which are from the sorted array and a 6th ID which is not from the array.
c. Binary Search five ID’s which are from the sorted array and a 6th ID which is not from the array.
d. Execution and output:
Display the original sorted array of student records.
Display the sequential search result of student records.
Display the binary search result of student records.
Any Help would be greatly appreciated
#include <iostream>
#include <iomanip>
#include <string>
#include <cmath>
#include <algorithm>
using namespace std;
struct Student {
string name;
int stuID;
string email;
};
// Show the student information
void showAllInfo(Student *studentArray, int stuCount) {
cout << "Student Info: "<<endl <<endl<<
"\t\tStudent Name"<<"\t\tStudent ID"<<"\t\tStudent Email"<<endl<<endl ;
for (int i = 0; i < stuCount; i++)
{
cout<<"\t\t"<< studentArray[i].name<<"\t\t"<<studentArray[i].stuID<<"\t\t\t"<< studentArray[i].email<<endl;
}
cout << endl;
}
//Sort out the arrays for the student information
void firstArray()
{
Student studentArray[12];
studentArray[0].name = "Bob McBoberston";
studentArray[0].stuID = 00;
studentArray[0].email = "BMcboberts#txstate.edu";
studentArray[1].name = "Shelby Donald";
studentArray[1].stuID = 1;
studentArray[1].email = "SDonald#txstate.edu";
studentArray[2].name = "Ronald Mcdonald";
studentArray[2].stuID = 2;
studentArray[2].email = "RMcdonald#txstate.edu";
studentArray[3].name = "Dick Cheney";
studentArray[3].stuID = 3;
studentArray[3].email = "DCheney#txstate.edu";
studentArray[4].name= "Ben Dover";
studentArray[4].stuID=4;
studentArray[4].email="BDover#txstate.edu";
studentArray[5].name="Ash Katchum";
studentArray[5].stuID=5;
studentArray[5].email="AKatchum#txstate.edu";
studentArray[6].name="Brock Whatever";
studentArray[6].stuID=6;
studentArray[6].email="BWhatevr#txstate.edu";
studentArray[7].name="Yugi Oh";
studentArray[7].stuID=7;
studentArray[7].email="YugiOh#txstate.edu";
studentArray[8].name="Johnny Bravo";
studentArray[8].stuID=8;
studentArray[8].email="JBravo#txstate.edu";
studentArray[9].name="Tom N. Jerry";
studentArray[9].stuID=9;
studentArray[9].email="Tnjerry#txstate.edu";
studentArray[10].name="Fred Flinstone";
studentArray[10].stuID=10;
studentArray[10].email="FFlinstone#emial.com";
studentArray[11].name="Son Goku";
studentArray[11].stuID=11;
studentArray[11].email="sGoku#txstate.edu";
studentArray[12].name="Johnny Test";
studentArray[12].stuID=12;
studentArray[12].email="JTest#txstate.edu";
}
void secondArray()
{
Student studentArray2[12];
studentArray2[0].name = "Rick Sanchez";
studentArray2[0].stuID = 13;
studentArray2[0].email = "RSanchez#txstate.edu";
studentArray2[1].name="Morty Smith";
studentArray2[1].stuID = 14;
studentArray2[1].email = "MSmith#txstate.edu";
studentArray2[2].name = "Summer Smith";
studentArray2[2].stuID = 15;
studentArray2[2].email = "SSmith#txstate.edu";
studentArray2[3].name = "Jerry Smith";
studentArray2[3].stuID = 16;
studentArray2[3].email = "JSmith#txstate.edu";
studentArray2[4].name="Mr. Meeseeks";
studentArray2[4].stuID=17;
studentArray2[4].email="MMeeseeks#txstate.edu";
studentArray2[5].name="Mr. PoopyButtHole";
studentArray2[5].stuID=18;
studentArray2[5].email="MPoopyButt#txstate.edu";
studentArray2[6].name="Tiny Rick";
studentArray2[6].stuID=19;
studentArray2[6].email="TRick#txstate.edu";
studentArray2[7].name="Pickle Rick";
studentArray2[7].stuID=20;
studentArray2[7].email="PRick#txstate.edu";
studentArray2[8].name="Beth Smith";
studentArray2[8].stuID=21;
studentArray2[8].email="BSmith#txstate.edu";
studentArray2[9].name="Bird Person";
studentArray2[9].stuID=22;
studentArray2[9].email="BmPerson#txstate.edu";
studentArray2[10].name="Squanchy";
studentArray2[10].stuID=23;
studentArray2[10].email="Squanchy#txstate.edu";
studentArray2[11].name="King Flippy Nips";
studentArray2[11].stuID=24;
studentArray2[11].email="KFlippyNipa#txstate.edu";
studentArray2[12].name="Mr> Goldenfold";
studentArray2[12].stuID=25;
studentArray2[12].email="MGoldenfold#txstate.edu";
}
void thirdArray()
{
Student studentArray3[13];
studentArray3[0].name = "Santa Claus";
studentArray3[0].stuID = 26;
studentArray3[0].email = "SClause#txstate.edu";
studentArray3[1].name = "Jason Riha";
studentArray3[1].stuID = 27;
studentArray3[1].email = "JRiha#txstate.edu";
studentArray3[2].name = "B-Rad Cragg";
studentArray3[2].stuID = 28;
studentArray3[2].email = "BRad#txstate.edu";
studentArray3[3].name="Roger Legrand";
studentArray3[3].stuID = 29;
studentArray3[3].email = "RLegrand#txstate.edu";
studentArray3[4].name="David De La O";
studentArray3[4].stuID=30;
studentArray3[4].email= "DDelao#txstate.edu";
studentArray3[5].name="Ian Sporn";
studentArray3[5].stuID=31;
studentArray3[5].email="ISporn#txstate.edu";
studentArray3[6].name="Morgan Taylor";
studentArray3[6].stuID=32;
studentArray3[6].email="Mytaylor#txstate.edu";
studentArray3[7].name="Sam Huggins";
studentArray3[7].stuID=33;
studentArray3[7].email="SHuggins#txstate.edu";
studentArray3[8].name="Shaun Huggins";
studentArray3[8].stuID=34;
studentArray3[8].email="ShuHuggins#txstate.edu";
studentArray3[9].name="Serena Huggins";
studentArray3[9].stuID=35;
studentArray3[9].email="SerHuggins#txstate.edu";
studentArray3[10].name="Kylie Parziale";
studentArray3[10].stuID=36;
studentArray3[10].email="KParziale#txstate.edu";
studentArray3[11].name="Jimmy Fallon";
studentArray3[11].stuID=37;
studentArray3[11].email="JFallon#txstate.edu";
studentArray3[12].name="Tom Goat Brady";
studentArray3[12].stuID=38;
studentArray3[12].email="TGBrady#txstate.edu";
studentArray3[13].name="Harry Giblets";
studentArray3[13].stuID=39;
studentArray3[13].email="HGiblets#txstate.edu";
}
int main() {
int stuCount = 39;
firstArray();
secondArray();
thirdArray();
showAllInfo(studentArray,stuCount);
return 0;
}
So you have a few problems. The first is that your arrays are declared inside the functions you've written, so no other code is going to be able to access them. You should declare your arrays inside the main function so that they can be passed as parameters to other functions. If you don't know how to pass an array as a parameter then the rest of this assignment is going to be difficult for you.
Anyway lets start like this, you don't need to write function to set up your arrays, you can do it directly in main, like this
int main()
{
Student firstArray[12] = {
{ "Bob McBoberston", 0, "BMcboberts#txstate.edu" },
...
};
Student secondArray[12] = {
...
};
Student thirdArray[12] = {
...
};
...
}
Now that the arrays are set up you need to write a function to do the sequential search (binary search is more complex, so leave that one for now).
Think about what parameters a function needs and what return value it has. This is always the first step when writing a function, but it's also one that many newbies struggle with.
In the case a sequential search function it needs to know 1) which array is it going to search, 2) how big that array is, 3) what id you are searching for. These are the parameters. It seems reasonable for the function to return the index in the array of the person it's found, or a special value -1 if it doesn't find the id. That's not the only way to do it, but it'll do for now. So putting that together we have
// look for 'id' in 'array' and returns the index if found or -1 if not found
int sequential_search(Person array[], int array_size, int id)
{
...
}
In your main function you would use this function something like this
int main()
{
...
// look for person with id 5
int id = 5;
int index = sequential_search(firstArray, 12, id);
if (index == -1)
cout << "ID " << id << " not found\n";
else
cout << "ID " << id << " is " << firstArray[index].name << "\n";
}
Get the idea? Hopefully this gives you a start. You can do the rest, and ask again if you get into difficulties.

computer lab with pointers

I have this assignment with managing computer labs. Specifically, there are 4 labs, each has a different number of computers. Hence, I want to create a 2D array with pointers, but after trying different stuff, I count on you for this error (please!!!). Below is a part of my programme, up to where the annoying bug comes up.
I got a run-time error after 1 run (terminate called after throwing an instance of std::bad_array_new_length what(): std::bad_array_new_length) when I leave the line with comment //PROBLEM HERE as such.
Add a & in front of lab room, the compiler gave me the error: lvalue required as left operand of assignment.
Newbie in C++, first time with pointers, I'd appreciate any help.
#include <iostream>
using namespace std;
//Global variables
const int SIZE = 4;
typedef int* Stations;
Stations *labroom;
//Function declaration:
void numberOfComputers();//Receive number of computers in each lab
int menu();//Display menu options for users
void menu_processor(int option);//process user's option
int main()
{
numberOfComputers();
menu();
menu_processor(menu());
return 0;
}
void numberOfComputers ()
{ char ans;
for (int i=0;i<SIZE;i++)
{
cout<<"Enter the number of computer stations in lab "<<i+1<<": ";
do
{
cin.get(ans);
} while (ans!='\n');
labroom [i] = new int [ans-'0'];//PROBLEM HERE
cout<<"\n";
}
}
That's not c++ code, it's just (ugly) C.
In C++ we have array for static arrays and vector for dynamic arrays.
First of all, choose the name of your variables or function in a smart way: prefer getNumberOfComputersFromUser instead of numberOfComputers. What numberOfComputers means? A function name must describe what it is doing.
Here a simplified snippet:
#include <vector>
#include <array>
#include <iostream>
using namespace std;
using Station = int;
using LabRooms = array<vector<Station>, 4>;
LabRooms getNumberOfComputersFromUser()
{
LabRooms labRooms;
int roomIndex = 0;
for(auto& computersInLab : labRooms)
{
cout << "Enter the number of computer stations in lab " << ++roomIndex << ": ";
auto computerCount = 0;
cin >> computerCount;
computersInLab.resize(computerCount);
}
return labRooms;
}
Explain
array requires two template arguments: the type and the size. Elements are statically allocated, no need to new because we already know how many rooms we have. The list of computers in each room is not know so we use vector that can dynamically increase or decrease.
using LabRooms = array<vector<Station>, 4>; it's the same of typedef array<vector<Station>, 4> LabRooms but it's clearer I think
for( auto& computersInLab : labRooms) iterate over labRooms and get a reference to its elements (in this case a reference to a vector of Station. This is the same of:
for(int i = 0; i < labRooms.size(); ++i)
{
auto& computersInLab = labRooms[i];
...
}
computersInLab.resize(computerCount); resize the list of computers with the value specified from the user.
Now, labRooms is an array of 4 elements, each element is a list of Station.

Argument of type "std::string (*)[10]" is incompatible with parameter of type "Movie *"

I'm just a beginning coder and all.. I was trying to create a printed table using a static array of top 10 movies from rotten tomatoes along with their critic and audience rating.
I was given struct Movie and void PrintMovies. When I try to call PrintMovies however, the title array doesn't work. The error keeps saying that the argument is incompatible. I don't understand what that means nor understand how to fix it.
Also if you anyone knows how to finish displaying the table, can you help me? I made a for loop for the 2-D array, but I don't know how to continue after it.
//--------------------------------Movie.h-------------------------------
#ifndef _Movie_
#define _Movie_
#include <iostream>
struct Movie
{
std::string title;
int criticRating; // from 0 to 100
int audienceRating; // from 0 to 100
};
#endif /*defined _Movie_*/
//-----------------------------------Movie.cpp-----------------------------
#include <iostream>
#include <string>
#include <algorithm>
#include "Movie.h"
#include <iomanip>
using namespace std;
void PrintMovies(Movie* movies, int numMovies);
int main()
{
std::string titles[3][10] = { "Kung Fu Panda", "Hail, Caesar!", "Star Wars: Episode VII - The Force Awakens",
"The Revenant", "The Choice","Pride and Prejudice and Zombies","The Finest Hours",
"Ride Along 2", "The Boy","Dirty Grandpa" };
PrintMovies(titles, 10);
return 0;
}
void PrintMovies(Movie* movies, int numMovies)
{
cout << "Movies\n";
cout << "Critic\t" << "Audience\t" << "Title\n";
for (int row = 0; row < 3; ++row)
{
}
}
std::string titles[3][10] = {...}
generates a two-dimensional array of strings, while your function expects to get a pointer to a Movie object. Those are different types and the compiler is not able to figure out how to convert one into the other.
One option is to use a vector like this:
std::vector<std::string> titles = {...};
std::vector<Movie> movies;
for(std::string title : titles)
movies.push_back({title,0,0}); //here the conversion happens:
// we use a string (title) and two ints to generate a movie
and then change the signatur of your function to
void PrintMovies(std::vector<Movie>& movies);
The line of code
std::string titles[3][10] = { "Kung Fu Panda", "Hail, Caesar!", "Star Wars: Episode VII - The Force Awakens",
"The Revenant", "The Choice","Pride and Prejudice and Zombies","The Finest Hours",
"Ride Along 2", "The Boy","Dirty Grandpa" };
erroneously tries to create a 3 x 10 array of movie titles, but you only pass it 10 movie titles. It's completely unclear what you were trying to do here. But I suspect what you wanted was:
std::string titles[10] = { "Kung Fu Panda", "Hail, Caesar!", "Star Wars: Episode VII - The Force Awakens",
"The Revenant", "The Choice","Pride and Prejudice and Zombies","The Finest Hours",
"Ride Along 2", "The Boy","Dirty Grandpa" };
Now you have the names of the movies, but they aren't Movies yet, they are std::strings. So you can't just pass them to your PrintMovies function. You'll need to create and populate an array of Movies
Here is a cleaned-up "SSCCE" of your code to help you get started.
#include <algorithm>
#include <iomanip>
#include <iostream>
#include <string>
#include <vector>
struct Movie
{
std::string title;
int criticRating; // from 0 to 100
int audienceRating; // from 0 to 100
};
void PrintMovies(Movie* movies, int numMovies)
{
std::cout << "Movies\n";
std::cout << "Critic\t" << "Audience\t" << "Title\n";
for (int row = 0; row < 3; ++row)
{
///TODO: Rethink this, you have to print numMovies movies.
}
}
int main()
{
constexpr auto NumMovies = 10;
// or static const size_t NumMovies = 10;
std::string titles[NumMovies] = { "Kung Fu Panda", "Hail, Caesar!", "Star Wars: Episode VII - The Force Awakens",
"The Revenant", "The Choice","Pride and Prejudice and Zombies","The Finest Hours",
"Ride Along 2", "The Boy","Dirty Grandpa" };
///TODO: array of critic ratings
///TODO: array of audience ratings.
///TODO: Create and populate array of Movies called "movies".
Movie movies[NumMovies]; // Something like this
for (auto i = 0; i < NumMovies; ++i)
{
movies[i].title = titles[i];
// ...
}
PrintMovies(movies, NumMovies);
}
Live demo: http://ideone.com/31z0u4
Notes:
. Instead of writing '10' everywhere, I created a constant alias for it -- NumItems. Within the scope it is declared in, i.e. main, you can use "NumItems" instead of the current number of movies. It helps keep things consistent.
. In the for loop I used the C++11 keyword "auto" to care about what type of value my invariant is,
. I've not solved a number of other problems with your implementation, since this seems to be an early learning phase of a C++ book/course.