'fArray' was not declared in this scope - c++

Hello I'm having this issue with my C++ problem I'm working on.
Here is the code
Cell.h
#ifndef CELL_H
#define CELL_H
#include <iostream>
#include <stdlib.h>
#include <time.h>
using namespace std;
class Cell
{
private:
int level;
int row;
int column;
//declares a variable called ptrFunction_array which is an array of 3 function pointers.
typedef void (*ptrFunction[])(void);
static void function1()
{
cout << "I'm function 1";
}
static void function2()
{
cout << "I'm function 2";
}
static void function3()
{
cout << "I'm function 3";
}
public:
Cell(int currentLevel, int currentRow, int currentColumn)
{
level = currentLevel;
row = currentRow;
column = currentColumn;
ptrFunction = new *fArray[3];
fArray[0] = function1();
fArray[1] = function2();
fArray[2] = function3();
}
virtual ~Cell();
void tick()
{
int randomNumber = rand() % 3;
cout << "Cell(" << level << ", " << row << ", " << column << ") ";
fArray[randomNumber];
}
};
#endif // CELL_H
Main.cpp
#include <iostream>
#include <stdlib.h>
#include <time.h>
#include "Cell.h"
using namespace std;
Cell ****myArray;
int main()
{
int level = 0;
int row = 0;
int column = 0;
char userInput = 'y';
srand (time(NULL));
do
{
cout << "Please input the amount of levels: ";
cin >> level;
cout << "Please input the amount of rows: ";
cin >> row;
cout << "Please input the amount of columns: ";
cin >> column;
cout << endl;
myArray = new Cell *** [level];
// Set random number to the elements of the array
for (int currentLevel = 0; currentLevel < level; currentLevel++)
{
myArray [currentLevel] = new Cell ** [row];
for (int currentRow = 0; currentRow < row; currentRow++)
{
myArray [currentLevel][currentRow] = new Cell * [column];
for (int currentColumn = 0; currentColumn < column; currentColumn++)
{
myArray [currentLevel][currentRow][currentColumn] = new Cell (currentLevel, currentRow, currentColumn);
myArray [currentLevel][currentRow][currentColumn] -> tick();
cout << " ";
}
cout << endl;
}
cout << endl;
}
cout << "Do you want to try again? (y / n) ";
cin >> userInput;
cout << endl;
if ((userInput == 'y') || (userInput == 'Y'))
{
for (int currentLevel = 0; currentLevel < level; currentLevel++)
{
for (int currentRow = 0; currentRow < row; currentRow++)
{
for (int currentColumn = 0; currentColumn < column; currentColumn++)
{
delete[] myArray[currentLevel][currentRow][currentColumn];
}
delete[] myArray[currentLevel][currentRow];
}
delete[] myArray[currentLevel];
}
delete[] myArray;
myArray = NULL;
}
}while (userInput != 'n');
return 0;
}
I notice that my fArray isn't inside the scope. the Line ptrFunction = new *fArray[3]; is where my error is. I've recently started learning C++ so I'm in the process of trying to understand why my typedef void (*ptrFunction[])(void); isn't correctly initializing the fArrayfor my program. The goal of my program is to be able to create a 3 dimensional array and be able to point to the Cell Objects and be able to track the location x,y,z.
Why does an error like this happen?

I'm going to ignore the four star pointer for now and stick to what's giving OP the most immediate grief.
A quick walk-through:
Cell(int currentLevel, int currentRow, int currentColumn)
{
level = currentLevel;
row = currentRow;
column = currentColumn;
Not bad to here. But...
ptrFunction = new *fArray[3];
This says assign to the variable ptrFunction, which must already exist and doesn't, a newly allocated array of 3 fArrays. The problem here is ptrFunction has been defined as a type, not a variable. fArray is not a type.
fArray[0] = function1();
fArray[1] = function2();
fArray[2] = function3();
Use fArray as a variable, making what's gone wrong here somewhat clear.
}
Cell needs to look a bit more like this, but not exactly. More on that later.
Cell(int currentLevel, int currentRow, int currentColumn)
{
level = currentLevel;
row = currentRow;
column = currentColumn;
ptrFunction * fArray = new ptrFunction[3];
Now fArray is a variable that points to one or more objects of type ptrFunction (but the definition of ptrFunction is somewhat broken), and points fArray at three ptrFunctions. Technically it points at the first of three ptrFunctions.
fArray[0] = function1();
fArray[1] = function2();
fArray[2] = function3();
}
Now we have an fArray, but it is a local variable and it only exists between the curly braces of Cell's constructor. When the constructor exists, the pointer goes away. The memory allocated does not and is lost. Without fArray pointing to it, you can't easily find it to use or delete it. fArray needs wider scope so that A) the memory isn't lost, and B) so that tick and other members of Cell can see it.
class Cell
{
private:
ptrFunction * fArray;
int level;
and in the constructor:
Cell(int currentLevel, int currentRow, int currentColumn)
{
level = currentLevel;
row = currentRow;
column = currentColumn;
fArray = new ptrFunction[3];
That fixes the can't find fArray.
My recommendation is to get one Cell working and then take a stab at getting a 1 dimensional array of Cells working. When you have one dimension, then try two. You might find that's all you need.
Edit
Forgot to mention this: Function pointers to members functions are an absolute expletive deleted to get right. Here is a page on common pitfalls and how to avoid them.
And here is how we avoid this smurf in the here and now of Modern C++: std::bind and std::function. The tutorials at the bottom of the linked document pages probably describe how to use them for simple cases better than I can.

Related

How to call multiple classes in C++

Here is the code I'm trying to create, and yes its messy for now. To give some back story I'm trying to figure out how to call a class multiple times without doing it seperately. What I mean is instead of performing:
Dice diceOne;
Dice diceTwo; and so on, I want to know if it is possible to just put it as Dice dicewhatever(*) and have that be a modifiable variable. This is so that I can set that variable to a number and then decrement it based on a score.
I dont know if this is even possible, but at this point I've beat my head against this so much I'm just pulling at straws to see if it would be a fit.
class Dice {
public:
Dice();
int Roll();
int currentDiceSide();
private:
int diceRoll;
int diceReRoll; //Declares and initializes the number of dice to allow for roll next dice throw.
};
Dice::Dice()
: //This is the beginning of the class and sets diceRoll to zero
diceRoll(0)
{
}
int Dice::Roll()
{ //This function actually does the random roll within the class Dice.
diceRoll = ((rand() % 6) + 1);
return diceRoll;
}
int Dice::currentDiceSide()
{ //This function returns the value of the dice roll for the class call.
return diceRoll;
}
void Game::Rules()
{
ifstream inFile;
inFile.open("Farkle Rules.txt");
string line;
if (inFile.fail()) {
cerr << "Error opening file" << endl;
exit(1);
}
if (inFile.is_open()) {
while (inFile.good()) {
getline(inFile, line);
cout << line << endl;
}
inFile.close();
}
}
void Game::GetPlayerInput(int playerInput)
{
cin >> playerInput;
}
void Game::RunGame()
{
Rules();
bool farkle = false;
double turnSum = 0;
double value = 0;
int i = 0;
int w = 6;
int players = 0;
int numPlayer = 0;
int diceOneValue = 0;
int diceTwoValue = 0;
int diceThreeValue = 0;
int diceFourValue = 0;
int diceFiveValue = 0;
int diceSixValue = 0;
int num1s = 0; //Declaring and initializing the variables to hold how many times a number shows up in a roll.
int num2s = 0;
int num3s = 0;
int num4s = 0;
int num5s = 0;
int num6s = 0; //
srand(static_cast<unsigned int>(time(0)));
cout << "Welcome to Farkle!" << endl
<< endl;
cout << "Please enter the number of players " << endl;
cin >> players;
//Dice diceOne;
//diceOne.currentDiceSide();
//Dice diceTwo;
//diceTwo.currentDiceSide();
//Dice diceThree;
//diceThree.currentDiceSide();
//Dice diceFour;
//diceFour.currentDiceSide();
//Dice diceFive;
//diceFive.currentDiceSide();
//Dice diceSix;
//diceSix.currentDiceSide();
Dice diceOne(w);
< -this is the line that I would like to create with a variable that is modifiable.
You cannot give each Dice object a name, but you can create a Vector of Dice object pointers (vectors are basically resizable arrays), like this:
#include <vector>
#include <iostream>
//...
std::cout << "Please enter the number of players " << std::endl;
std::cin >> players;
// do something to make sure players is an integer
// initialize the empty playerDice vector
std::vector<Dice*> playerDice = {};
for (unsigned i = 0; i < players; ++i) {
playerDice.push_back(new Dice); // this adds a new Dice object pointer to the end of the vector
playerDice.at(i)->currentDiceSide();
}
You have then called the currentDiceSide() function on each Dice object you created, and have neatly organized them in a Vector, which you can access like this:
// say we want to access the third Dice Object,
// Vectors start counting at 0, so we acces the element at Index 2.
playerDice.at(2)->doSomething();
Now because you instantiated those Dice objects with new you have to remember to delete them when you're finished with them, otherwise this will create a memory leak.
//...
// this deletes all the Dice objects in the vector, and points the remaining pointers to null
for (auto d : playerDice) {
delete d;
d = nullptr;
}
Or, better yet, if you're using C++11, you can use std::unique_ptr instead of the raw C-style pointers. Those will prevent you from creating memory leaks, because they will be deleted when they go out of scope. Note you have to #include <memory> to use these.
The vector definition then turns into:
std::vector< std::unique_ptr<Dice> > playerDice = {};
And the creation of the objects would look like this
for (unsigned i = 0; i < players; ++i) {
Dice* temp = new Dice;
temp->currentDiceSide();
std::unique_ptr<Dice> uPtr{ temp };
playerDice.push_back(std::move(uPtr));
}
You can then just clear the vector when you're done with all the objects:
playerDice.clear();
which will delete all the Dice objects that you put into the vector.

C++ beginner declaring a function involving array of structures

There is a few lines of my code that I would like to define as a function because I plan to use it multiple times. portion of code is as follows:
// loop within loop used to reorder with highest price at the top
for(i=0;i<x;i++){
for(t=i;t<x;t++){
if(f[i].price < f[t].price) {
temp = f[i].price;
f[i].price = f[t].price;
f[t].price = temp;
}
}
}
I hope to be able to enter new values for x and f each time I call the function. I have included all of my code below. If I'm unclear about my objective in anyway please feel free to ask. I apologize in advance for the improper terminology I am new to this. Thank you
#include <iostream>
using namespace std;
struct List
{
char name[10];
int price;
};
int main()
{
//x represents number of structures within array!
int x;
cout << "How many items would you like to list under the fruit menu?\n";
cin >> x;
//array of structures fruit
struct List f[x];
int i;
//input values into structure
for (i = 0; i < x; i++) {
cout << "\nEnter fruit name, and price.\n";
cin >> f[i].name;
cin >> f[i].price;
};
//variables for reordering
int temp;
int t;
// loop within loop used to reorder with highest price at the top
for(i=0;i<x;i++){
for(t=i;t<x;t++){
if(f[i].price < f[t].price) {
temp = f[i].price;
f[i].price = f[t].price;
f[t].price = temp;
}
}
}
//Output of menus
//fruit Menu
cout << "\n\nFruit Menu";
for (i = 0; i < x; i++) {
cout << "\n" << f[i].name << " $" << f[i]. price;
};
return 0;
}
I suppose it is an assignment that says "implement your own sort function for sorting an array of fruits", so I take the data structure "array of fruits" as given. You can, of course, change this to vector<struct Fruit> as well, but that's a different topic.
Maybe the following fragments help you finishing your code. It contains functions for entering, sorting, and printing the array with some samples how to deal with the parameters and the calls. You'll have to finalise the code.
Have fun!
#include <iostream>
using namespace std;
struct Fruit
{
char name[10];
int price;
};
// enter up to nrOfFruis; return number of fruits actually entered
int enterFruits(struct Fruit *fruits, int maxNrOfFruits) {
int entered = 0;
while (entered < maxNrOfFruits) {
cin >> fruits[entered].name;
entered++;
}
return entered;
}
void sortFruits(struct Fruit* fruits, int nrOfFruits) {
// your sort code goes here
// example for swaping two elements:
Fruit temp = fruits[0];
fruits[0] = fruits[1];
fruits[1] = temp;
}
void printFruits(struct Fruit *fruits, int nrOfFruits) {
cout << "\n\nFruit Menu";
for (int i = 0; i < nrOfFruits; i++) {
cout << "\n" << fruits[i].name << " $" << fruits[i]. price;
};
}
int main()
{
// Your task: put a proper loop and exit condition arround the following lines...
int x;
cout << "How many items would you like to list under the fruit menu?\n";
cin >> x;
struct Fruit fruits[x];
int entered = enterFruits(fruits, x);
sortFruits(fruits, entered);
printFruits(fruits, entered);
return 0;
}
You cannot allocate an array on the stack if you do not know it's size at compile time. Therefore, you need to dynamically allocate memory for it(you also need to remember to delete it):
//x represents number of structures within array!
int x;
cout << "How many items would you like to list under the fruit menu?\n";
cin >> x;
//array of structures fruit
struct List * f = new List[x];
//...
delete [] f;
Alternatively, you could do it the C++ way, using vector, having the vector elements on the stack:
int x;
std::cin>>x;
std::vector<A> v(x);
for( size_t i = 0; i < x; i++)
{
std::cin >> v[i].x;
}
If you just want to pass an array to a function you can do so like this:
void sortArray(struct List list[]);
void sortArray(struct List* list, int n); // n = size of array
may be better to just use std::vector or some other list container instead. :)
Sounds like you want a function that receives an array t and index x, and you want to mutate the array in the function?
C++ is "pass by value", so to mutate the array you have to have your function take a reference (or pointer) to the array so that you're mutating the original array and not a copy of it, so just have your function signature like this: func(T& t, int x) (assuming T is the type of array t).

Passing arrays and pointers with access violation

I am working on an assignment which must pass pointers for all function
parameters. No global variables are allowed except global constants.
I'm to create an array of "bids" in main and fill it with readBids() function. This works, but I am then supposed to pass it to a function to bubble sort it. My program breaks once my sortBids function is called. I'm learning pointers now and I can't see what I am doing wrong. The Call Stack gives Project4.exe!main()Line32, which points to sortBids(bidArray, numBids);
Any help and an explanation would be very appreciated.
#include <iostream>
#include <string>
using namespace std;
string* readProductName();
int* readNumBids();
double* readBids(string,int);
void sortBids(double*, int*);
void averageBid();
void maxBid();
void totalBid();
void printReport();
int main(){
string* productName;
int* numBids;
productName = readProductName();
numBids = readNumBids();
double* bidArray = readBids(*productName, *numBids);
sortBids(bidArray, numBids);
cout << *productName << " " << *numBids << endl;
for (int i = 0; i < *numBids; i++){
cout << bidArray[i] << endl;
}
system("PAUSE");
delete productName;
delete numBids;
delete bidArray;
return 0;
}
string* readProductName(){
string* productName = new string;
cout << "\n Please enter a product name\n";
cin >> *productName;
return productName;
}
int* readNumBids(){
int* numBids = new int;
cout << "\n Please enter the number of bids\n";
cin >> *numBids;
return numBids;
}
double* readBids(string productName, int numBids){
int* size = new int;
size = &numBids;
string* productNamePtr = new string;
productNamePtr = &productName;
double *bidArray;
bidArray = new double[*size];
cout << "\nHow many bids for the " << *productNamePtr << endl;
for (int i = 0; i < *size; i++){
cout << "Please enter bid #" << i + 1 << endl;
cin >> bidArray[i];
if (bidArray[i] <= 0){
cout << "\nPlease enter an amount larger than 0\n";
i--;
}
}
return bidArray;
}
void sortBids(double* array, int *size){
bool* swap = bool{ false };
double* temp = new double;
do
{
*swap = false;
for (int count = 0; count < *size - 1; count++)
{
if (array[count] > array[count + 1])
{
*temp = array[count];
array[count] = array[count + 1];
array[count + 1] = *temp;
*swap = true;
}
}
} while (*swap);
}
Problem:
You intialise swap to 0. As swap is a pointer to bool, you have a null pointer.
You later dereference this pointer without ever having it point to a valid bool object:
*swap = true;
Tha is UB and this is why you get an access violation !
Solution
Either you define this variable as plain object bool swap = false; and use swap everywhere. Or you initialize it correctly bool *swap = new bool{false}; and you use *swap everywhere.
Miscellaneous advice:
Attention: bidArray is allocated with new[], so you have to delete[] it or risk undefined behaviour !
In pointer definitions, take the habit of puting the star next to the variable and not to the type. Why ? Because optically it is confusing:
bool* a,b; // defines a pointer to bool a, but a PLAIN BOOL b !
bool *a,b; // invites otpically to right interpretation by human reader

Incorrect Variable output with Vector Class C++

My output for the call to the temporary array size wont correctly output. It resizes as according, but I can't get the MAX to display the new value of the new array. My error is within the Resize function within the class.
#include <iostream>
#include <vector>
#include <string>
#include <math.h>
#include <ctime>
using namespace std;
class VectorClass {
private:
int * Vector;//This will be our resizeable array
int Size; //Keep track of vector current size
int MAX=10;
int growth = 5;
int num;
int Resize(int growth, int MAX);
public:
VectorClass(int growth, int Size);
~VectorClass();
int AddItem(int num);
void RemoveItem();
void Print(void);
};
VectorClass::VectorClass(int growth, int Size)
{
Size = 10;
growth = 5;
Vector = new int[Size];
}
VectorClass::~VectorClass()
{
cout << "Destructor was called." << endl;
}
//Will insert num into the vector at the current open position
int VectorClass::AddItem(int num)
{
Vector[Size] = num;
Size++; //Indicate that there isnt as much free space
if (Size == MAX)
{
Resize(Size, MAX);
}
Print();
return num;
}
//Get rid of the most recently added item
void VectorClass::RemoveItem()
{
Size--; //Tricks the vector into one fewer elements in it it currently does
Print();
}
int VectorClass::Resize(int growth, int MAX)
{
cout << "Array is full! Resizing the Array!" << endl;
//Step 1: make a copy
int * temp = new int[MAX]; //Make a new array, same size as exiting array
//loop that copies the original into the copy
for (int i = 0; i<MAX; i++)
{
temp[i] = Vector[i];
}
//Step 2: Delete the original
delete[] Vector; //Deletes all elements in the array Vector from the Heap
//Step 3: Make a bigger vector
Vector = new int[MAX + growth];
//Step 4: Reverse the copy and record the size change
for (int i = 0; i<MAX; i++)
{
Vector[i] = temp[i];
}
MAX = MAX + growth;
//Step 5: Delete the copy
delete[] temp;
cout << "Resize was called.\n" << endl;
return MAX;
}
void VectorClass::Print()
{
cout << "*******************************************************" << endl;
for (int i = 0; i< Size; i++)
{
cout << Vector[i] << endl;
}
cout << "Size = " << Size << "\tMAX = " << MAX << "\t Growth = " << growth << endl << endl;
cout << "*******************************************************" << endl;
}
int main(void)
{
VectorClass V(5,10);
for (int i = 0; i <= 4; i++)
{
int x = rand();
V.AddItem(x);
}
//Print the Vector #1
V.Print();
//Delete 2 Items
V.RemoveItem();
V.RemoveItem();
//Add 9 random Numbers
for (int i = 0; i <= 8; i++)
{
int x = rand();
V.AddItem(x);
}
//Print the Vector
V.Print();
system("pause");
return 0;
}
Several things are wrong with you code. The first one, probably not the one you care about most, is that you never free the memory. You should do it in your destructor, or even better use a std::unique_ptr to handle your memory.
Now, i believe you are yourself confused about your own variables. I see that you possess a variable member named num that you never use. Even worse, you have a parameter in AddItem with the same name. Are you sure it does what you want? The same is true for growth. I would advise you to name your member variable differently, so that you know what they are quickly. I prefixe them with "m_" for example, but you can do as you wish.
You do not need to declare your function parameters inside your class. Only in the function prototype.
Then, in your AddItem function, you use your variable Size to determine where to add the new element, but you initialize your array with it too, which means that not only you do not add your elements at the beginning of your array, you try to write them in memory you do not own!
I could continue for a long time. I am sorry but it only appears to me that you do not know C++ at all. You should go learn the basics again, and maybe start with an easier project to begin your C++ learning.
Good luck :-)

C++ code breaks into line and for the love of me I can't fix it

Basically my code is supposed to take input from the user about the runners of a marathon, and then display the 3 best times and have the ability to search and display any runner. Right now the code is still pretty bare-bones, but it should at least take the input it, organize the info in ascending order (winners function) and I was in the middle of writing the display function when I decided to compile the code to test, and then it all goes down hill.
Basically when I have to input the name of the first runner, the code breaks into this line:
static void __CLRCALL_OR_CDECL assign(_Elem& _Left, const _Elem& _Right) _NOEXCEPT
{ // assign an element
_Left = _Right;
}
First of all I have no idea what that means or why left = right, and second a friend ran my code on his machine and told me he encountered no errors.
Here is my code:
#include <iomanip>
#include <iostream>
#include <math.h>
#include <string>
using namespace std;
#pragma once
#include <string>
using namespace std;
class race
{
private:
public:
int timeH, timeM, timeS, timeT;
int number;
string name;
void input();
};
int size;
race *runner = new race[size];
void input();
void winners();
void display();
int main(){
input();
winners();
display();
system("pause");
}
void input(){
cout << "Indique la cantidad de corredores: ";
cin >> size;
for (int i = 0; i < size; i++){
cout << "Nombre del corredor ";
cin >> runner[i].name;
cout << "Numero del corredor # "<<i;
cin >> runner[i].number;
cout << "Tiempo del corredor # " << i << endl << "Indique cuantas horas tardo :";
cin >> runner[i].timeH;
runner[i].timeH = runner[i].timeH * 3600;
cout << "Cuantos minutos: ";
cin >> runner[i].timeM;
runner[i].timeM = runner[i].timeM * 60;
cout << "Cuantos segundos: ";
cin >> runner[i].timeS;
runner[i].timeT = runner[i].timeH + runner[i].timeM + runner[i].timeS;
}
}
void winners(){
race temp;
int flag = 1;
for (int j = 1; (j <= size) && flag; j++){
flag = 0;
for (int i = 0; i < size-1; i++){
if (runner[i + 1].timeT < runner[i].timeT)
{
temp = runner[i];
runner[i] = runner[i + 1];
runner[i + 1] = temp;
flag = 1;
}
}
}
}
Thanks in advance, any help is appreciated.
int size;
race *runner = new race[size];
That's a problem right there. You're allocating memory, but you haven't set size yet (that allocation runs before main() is invoked). That means you are doing new race[0] (because size is initialized to zero, since it's a global int). Ergo, the rest of your program is invoking undefined behavior, because runner is an empty array, which you're trying to (illegally) access.
You're also leaking memory, as you never delete [] the memory you allocate with new []. I suggest heading Joachim's advice and using std::vector.
The problem is this:
int size;
race *runner = new race[size];
Uninitialized global variables are zero initialized, so size will be initialized to zero, so you're allocating a zero-sized array which means any access to the array will be out of bounds and lead to undefined behavior.
There are two ways of solving this:
Wait with the allocation until you know the size. (Not the solution I recommend.)
Use std::vector which is a dynamically sized "array" type (the solution I do recommend).