How to solve undeclared variable in the case below - c++

I am a beginner at c++ and I want to ask about this specific error. I don't know why it always appears that I didn't declare the variable wherein in fact, I did (see my code below).

You initiated the decoder array in both cases in an if statement. So the compiler does not know it outside of the if. Write the variable before your first if-else statement and than change it, if needed, within the if statement.

The problem is in the array declaration, it is declared inside of a scope:
#include <iostream>
using namespace std;
int main()
{
int a = 2; // local variable
if (true)
{
int a = 4; // local if statement variable
cout << a << endl; // here the output will be 4
}
cout << a << endl; // here the output will be 2, also here 'a' from the if statement, does not longer exist, when the if statement is ended all the variables declared inside will be deleted
return 0;
}
You can also create your own scope with out 'if' statement:
int a = 2; // local variable
{
int a = 4; // local scope statement variable
cout << a << endl; // here the output will be 4
}
cout << a << endl; // here the output will be 2, also 'a' from the previous scope does not exist

Here is a useful link to learn about local variables and scope.
Your particular problem is that your variable decoder is local to the block scope (you declared it within a if statement), and you try to use it outside that scope. However, once exited the scope, all variables local to that scope are destroyed.
if (number = 987)
{
int decoder[3] = {0, 1, 2};
} // and here decoder is destroyed
You could declare decoder outside the block and define it inside the block:
int decoder[3];
if (number = 987)
{
// populate decoder
}
// decoder still exists

Related

While loop not breaking (I believe)

I don't understand if I have created an infinite loop or it is just taking long.
int wuerfeln_bis_wurfverteilung(Wurfverwaltung ww) { //takes object of class with x number of die rolls
Wurfverwaltung xx(ww.anzahl); //creates object with x (from param.) no. of rolls
cout << xx << endl;
int z=0;
while (!(xx == ww)){ // while the two objects are unequal
Wurfverwaltung xx(ww.anzahl); //keep creating new objects
z++; //and increase z by one
cout <<xx<< " " << z<< " ";
}
return z;
}
//class looks like this
class Wurfverwaltung{
friend int wuerfeln_bis_wurfverteilung(Wurfverwaltung&);
private:
unsigned int anzahl;
Wurf *w; // pointer to an array of objects from a previous class
... bunch of functions
Question: is it always testing for xx from the before the while loop and comparing to ww? or is xx getting updated every loop? the code doesn't seem to break even if I take 2 as the no. of rolls. (answered. Thanks!)
Edit:
The point of the function is to take an object with a random array and recreate an array with the same combination and return the number of attempts it took.
You are shadowing a variable by creating a new variable with the same name in a new scope.
int wuerfeln_bis_wurfverteilung(Wurfverwaltung ww) {
Wurfverwaltung xx(ww.anzahl); // 1
cout << xx << endl;
int z=0;
while (!(xx == ww)){
Wurfverwaltung xx(ww.anzahl); // Creates new variable, doesn't change (1)
z++;
cout <<xx<< " " << z<< " ";
}
return z;
}
If you change it to x = ww.anzahl; you'll be changing the values and maybe exit the loop.
You compiler can help you detect these kind of issues, but you have to activate more flags (-Wshadow in this case on GCC)
The condition of the while loop
while (!(xx == ww)){ // while the two objects are unequal
Wurfverwaltung xx(ww.anzahl); //keep creating new objects
z++; //and increase z by one
cout <<xx<< " " << z<< " ";
}
deals with the variable xx declared before the loop
Wurfverwaltung xx(ww.anzahl);
The variable xx declared within the loop does not influence on the condition of the loop. It just hides the variable declared before the while loop in the compound statement of the while loop. That is the declaration region of the variable declared in the while loop is the compound statement. Outside the compound statement the variable does not exists.
So the initial value of the condition of the while loop
while (!(xx == ww)){
is not being changed and you have an infinite loop.

Advice on Sentinel loops C++

so i get how sentinel loops work, they use the expression at the beginning of the the loop declaration to determine where the loop stops. However i don't understand how to connect variables in the scope of the loop and outside the scope. For example
int i;
int sum = 0;
cout << "Enter a number" << endl;
cin>> i;
while (i > 0)
{
sum = sum + i;
cout << "Enter a number" << endl;
cin>> i;
}
cout << "The sum of the numbers entered is" << endl;
cout << sum;
return 0;
So the sum in the loop is correct since its within scope but the i or number entered to define i out of the scope in the initial i . How do you go about this, can you connect the variables inside and outside the loop? Or can you use uninitialized memory to make a sentinel loop? Do you have to add a separate variable outside the loop and connect the sum of i outside and inside the loop? So just trying to understand how you'd connect the variables inside and outside the scope. If sentinels need to have the variable defined prior to the loop.
Thank you for any light you can shed on this.
Variables are defined in a particular scope and become visible to all scopes within the outer scope unless overwritten (which most programmers tell you is a very, very bad idea). For instance:
#include
using std::cout;
using std::endl;
int main(int, char **) {
int i = 5;
int k = 10;
if (true) {
int j = 15;
int i = 20;
cout << "i inside if: " << i << ". J: " << j << endl;
}
cout << "i outside if: " << i << ". K: " << k << endl;
}
Running it produces:
i inside if: 20. J: 15
i outside if: 5. K: 10
In this case, the scope of method main() contains two variables, i and k. Those variables are also available inside the if-statement. The if also defines two variables, j and i. They are only available inside the if-statement.
The i inside the if-statement hides the larger i (which is dangerous / confusing), but I wanted to demonstrate it. As you can see, i outside the if retains it's original value -- it wasn't modified when we declared the inner copy.
In your code, i and sum are defined outside the if-statement, so they're available inside it, and changes you make to them persist. That is, because you haven't defined new variables, everything just works.

Symbol table using vectors

I've been racking my brain trying to figure out the logic with implementing my symbol table & now I'm waving the white flag and asking for some help. I'm creating a symbol table using vectors but I'm having trouble putting the symbol table entry (a string for now, a struct later) in the right scope. My code has an int scopenum that increments every time a block is opened { and decrements every time a block is closed }. However this line causes a problem:
{ a { b } { q } } because it puts q in scope 2 when it should be in scope 3. My code pushes a new row onto the vector but it doesn't use it in the insert. How can I modify my code to correctly account for opening & closing scopes?
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
int stacknum=-1;
vector< vector<string> > v;
void display(){
for(int i=0; i<v.size(); i++){
cout << "Scope " << i+1 << ": " << endl;
for(int j=0; j<v[i].size(); j++)
cout << v[i][j] << endl;
cout << endl;
}
}
void insert(string s){
v[stacknum].push_back(s);
}
int main(){
string data;
ifstream file;
file.open("input");
if(!file.is_open()) {
cout << "Input file not found";
return 1; }
while(file >> data){
if(data=="{"){
stacknum++;
vector<string> row;
v.push_back(row);
continue;
}
if(data=="}"){
stacknum--;
continue;
}
insert(data);
}
file.close();
display();
return 0;
}
You can't track the current scope with just a index; you need a stack. Alternatively (and probably more usefully) you need to record the parent scope for each scope, which you can do with a second vector or by including an extra data member in the scope object.
In either case, when you enter a new scope, you create a new scope object (a vector of symbols, with associated parent scope index) at the end of the vector of scope objects, and make that object's index the "current scope index". When you leave a scope, the current scope index is set to the current scope's parent.
The parent pointers are useful when you are searching for a symbol; you need to search all of the parents of the current scope until you find the symbol.
Depending on the scoping rules you are trying to model, that might not be adequate. It doesn't accurately model C's scoping rules, for example, because in C, the scope of a declared variable starts at the declaration, not at the beginning of the enclosing block. However it may be good enough for building an AST, as long as you do all symbol lookups in order as you parse the input left to right.

inner loop with same variable name as outer loop

assuming the following simple code:
for(int i=0; i < 1000; i++)
{
cout << "Outer i: " << i << endl;
for(int i=0; i < 12; i++)
{
cout << "Inner i:" << i << endl;
}
}
Works very nice. The same variable name in both loops used and the output is fine.
Do I understand it right that both variables are created on stack, and when the outer loop comes to the new inner loop, a new "namespace" (maybe the wrong name..) is created? But why is it overwritten? If I choose another name for the variable in inner loop I can also access the i from outer loop.
A bit confused I am.
"Namespace" is kinda close.. but it is more about scope. The inner i hides/surpresses the outer i. You could think of another example:
{
int i=0; //outer scope i.
{
int i =0; //this hides the outer scope i.. I can't use outer i here
}
i =1 ; //inner i is out of scope.. outer i is set to 1
}
Your understanding is correct. The code is technically valid. However, this practice has many problems and is therefore a bad idea.
Each for loop has a separate scope associated with it. The variable declared in the inner loop shadows the variable declared in the outer loop. There is no way to access the outer i from the inner loop.

How can I keep variables from being re-initialized every time I call a C++ function?

How do I get past this variable initialization problem? If I only could figure out how to only initialize them only once...
* Main.cpp : main project file.
/************************** Begin Header **************************/
#include "stdafx.h" //Required by Visual C ++
#include <string> //Required to use strings
#include <iostream> //Required for a bunch of important things
#include <iomanip> //Required for manipulation of text and numbers
using namespace System; // Automatically uses System namespace
using namespace std; // Automatically uses std namespace
#pragma hdrstop // Stops header here
/*************************** End Header ***************************/
//* Begin Function Headers *//
void inputData(); // This will be used to organize class member calls when setting and getting new data.
int getData(); // Will get user data, input in character string, convert to an integer and then perform data validation.
void createReport(int place, int number, string type); // Will organize commands to create the report and display it on the screen.
//* End Function Headers *//
class JarsSold // Begin Class -- JarsSold
{
/* Begin Initialization & Creation of important resources */
private:
static const int MaxArray = 5; // Value for the size of array JARS_SOLD
int JARS_SOLD[MaxArray]; // Creation of array with size of MaxArray
/* End Initialization & Creation of important resources */
public: // Makes underlining elements Public instead of the default Private
JarsSold() // Begin Constructor
{ // Put something in num array
JARS_SOLD[0] = 0; // [1]
JARS_SOLD[1] = 0; // [2]
JARS_SOLD[2] = 0; // [3]
JARS_SOLD[3] = 0; // [4]
JARS_SOLD[4] = 0; // [5]
} // End Constructor
~JarsSold(){}; // Destructor
/* Put all members for JarsSold class below here */
void setNumber(int num, int value) // Set the number of jars sold with number placement in array and value to replace it with
{
JARS_SOLD[num] = value; // Stores value into JARS_SOLD at whatever num is at the time
}; // End setNumber class member
int getNumber(int num) // Get the current number held for jars sold with number placement in array
{
return JARS_SOLD[num]; // Returns whatever is in JARS_SOLD depending on what num is at the time
} // End getNumber class member
/* Put all members for JarsSold class above here */
}; // End Class -- JarsSold
class SalsaTypes // Begin Class -- SalsaTypes
{
/* Begin Initialization & Creation of important resources */
private:
static const int MaxArray = 5; // Value for the size of array JARS_SOLD
string SALSA_TYPES[MaxArray]; // Creation of array with size of MaxArray
/* End Initialization & Creation of important resources */
public: // Makes underlining elements public instead of the default Private
SalsaTypes() // Begin Constructor
{ // Add default strings to str array
SALSA_TYPES[0] = "Mild"; // [1] Stores Mild into SALSA_TYPES at 0 spot
SALSA_TYPES[1] = "Medium"; // [2] Stores Medium into SALSA_TYPES at 1 spot
SALSA_TYPES[2] = "Sweet"; // [3] Stores Sweet into SALSA_TYPES at 2 spot
SALSA_TYPES[3] = "Hot"; // [4] Stores Hot into SALSA_TYPES at 3 spot
SALSA_TYPES[4] = "Zesty"; // [5] Stores Zesty into SALSA_TYPES at 4 spot
} // End Constructor
~SalsaTypes(){}; // Destructor
/* Put all members for SalsaTypes class below here */
void setType(int num, string type) // Set salsa type with number placement in array and string value to replace with
{
SALSA_TYPES[num] = type; // Stores the string type into SALSA_TYPES at whatever num is at the time
}; // End setType class member
string getType(int num) // Get the Salsa Type with number placement in array
{
return SALSA_TYPES[num]; // Returns SALSA_TYPES depending on what is in num at the time
}; // End getType class member
/* Put all members for SalsaTypes class above here */
};// End Class -- SalsaTypes
void main( void ) // Begin Main Program
{
cout << fixed << setprecision(1) << setw(2); // Do a little customization with IoManip, might as well, we just might need it
// Main Program Contents Begin Here //
// Opening Credits for Program
cout << "Welcome to the /Professional Edition\\ of the Chip and Salsa Sale Tool EXPRESS." << endl;
cout << "This handy-dandy tool will make a chip and salsa manufacturer's job much easier!" << endl;
cout << endl << endl << endl;
cout << "Press any key to begin inputing the number of jars sold for these salsa flavors: " << endl << endl;
cout << "-Mild" << endl << "-Medium" << endl<< "-Sweet" << endl << "-Hot" << endl << "-Zesty" << endl << endl << endl;
system("pause"); // Pause here. After this begin data input
cout << endl << endl << endl;
inputData(); // Will deal with data input, validation, and reports
// Main Program Contents End Here //
} //End Main Program
// All Content for Functions Begin Here //
void inputData() // Begin inputData Function
{
// Begin Create Class Obects //
SalsaTypes salsa;
JarsSold jars;
// End Create Class Objects //
// Variable Creation Begin //
// Variable Creation End //
// All Content for Functions Begin Here //
for (int i = 0 ; i < 5 ; i++) // Start For Loop
{
cout << "Input how many Jars were sold for \"" << salsa.getType(i) << "\"" << ": "; // Displays which Salsa we are reffering to
jars.setNumber(i,getData()); // Will use getData() to determine what value to send to the JarsSold class.
createReport(i,jars.getNumber(i),salsa.getType(i)); // Send these numbers to another function so it can make a report later
cout << endl << endl; // Using this as a spacer
}
// All Content for Functions End Here //
}; // End inputData Function
int getData() // Begin getData Function
{
// Variable Creation Begin //
char charData[40]; // Will be used to store user data entry
int numTest; // Will be used for Data Validation methods
// Variable Creation End //
// Main Contents of Function Begin Here //
retry: // Locator for goto command
cin >> charData; // Ask user for input. Will store in character string then convert to an integer for data validation using 'Atoi'
numTest = atoi ( charData ); // Convert charData to integer and store in numTest
if (numTest < 0) { numTest = 0; cout << endl << endl << "You can't enter negative numbers! Try Again." << endl << endl << "Re-enter number: "; goto retry;} // Filter out negative numbers
// Main Contents of Function End Here //
return numTest; // If it makes it this far, it passed all the tests. Send this value back.
}; // End getData Function
void createReport(int place, int number, string type) // Begin createReport Function
{
// Variable Creation Begin //
int const MAX = 5; // Creat array size variable
int lowest; // The integer it will use to store the place of the lowest jar sales in the array
int highest; // The integer it will use to store the place of the highest jar sales in the array
int total; // The integer it will use to store total sales
int numArray[MAX]; // Create array to store jar sales (integers)
string typeArray[MAX]; // Create array to store types of salsa (strings)
// Variable Creation End //
// Main Contents of Function Begin Here //
numArray[place] = number; // Store number into new array
typeArray[place] = type; // Store type into new array
if (place = 4) // If the array is full it means we are done getting data and it is time to make the report.
{ // Begin making report, If statement start
for ( int i = 0 ; i < 5 ; i++ ) // Using a for-loop to find the highest and lowest value in the array
{ // For Loop to find high and low values BEGIN
if ( lowest < numArray[i]) // Keep setting lowest to the lowest value until it finds the lowest one
{ // Start If
lowest = numArray[i]; // Lowest equals whatever is in numArray at i spot
} // End If
if ( highest > numArray[i]) // Keep setting highest to the highest value until it finds the highest one
{ // Start If
highest = numArray[i]; // Highest equals whatever is in numArray at i spot
} // End If
total += numArray[i]; // Will continually add numArray at i spot until it has the total sales
} // For Loop to find high and low values END
// Main Contents of Function End Here //
} // END creatReport Function
// All Content for Functions Ends Here //
Well my problem is...I need to get my data across from one function to another. I thought I could figure out how to create Global Class Objects but I couldn't. So I thought I could get around just passing the arguments to another function and then restoring them in its own arrays and then keep doing that until i've completely copied all number arrays and string arrays. Well...yeah that does work EXCEPT this part in createReport():
// Variable Creation Begin //
int const MAX = 5; // Create array size variable
int lowest; // The integer it will use to store the place of the lowest jar sales in the array
int highest; // The integer it will use to store the place of the highest jar sales in the array
int total; // The integer it will use to store total sales
int numArray[MAX]; // Create array to store jar sales (integers)
string typeArray[MAX]; // Create array to store types of salsa (strings)
// Variable Creation End //
What happens is, I guess I am so tired that I missed it, every time I call that function it re-initializes those same variables again. I will put variables into another variable and then it will get re-initialized to default values.
I tried using a counter variable that counted to one after it initialized and then after it was 1 it wouldnt initialize again. No that didn't work because the variables werent initialized outside the scope of the if statement. I then tried a GOTO statement that would skip the initialization after it happened once. Nope something went wrong with the first initialization phase and no compilation.
I need to figure out how I can either
keep those variables from getting re-assigned or initialized so they can maintain their values. Or
figure out how to create global class objects (and yes I've tried the extern classes with multiple source files. No luck just lots of errors)
I'm not very good at programming yet. But I assure you I've been working on this piece for hours and hours and hours and I stayed up all night just constantly trial and error. I really proud of myself because this code is pretty advanced for me. I've looked at every tutorial on Google and I'm fresh out of luck -- you guys are my last hope!! Sorry again guys. I know this is a dumb question...
One last quick question. How do you create Global Class Objects? For example
MyClass
{
MyClass(){};
~MyClass(){};
}
MyClass MyClassObject;
How do I use MyClassObject throughout my entire program?
The only way I can use it is if I create a new object every time with every function I use. And that means I lose all data stored inside my class?
I've read that having global object isn't a good idea though. I would love to not have to use them but I have no clue on any alternatives that I can actually understand.
Any other critiques or tips is GREATLY appreciated. I love this stuff I just don't have many people to ask questions to.
You're doing really well! The simple answer is to write static in front of your variables:
static int const MAX = 5; // Creat array size variable
static int lowest; // The integer it will use to store the place of the lowest jar sales in the array
static int highest; // The integer it will use to store the place of the highest jar sales in the array
static int total; // The integer it will use to store total sales
static int numArray[MAX]; // Create array to store jar sales (integers)
static string typeArray[MAX]; // Create array to store types of salsa (strings
I think I can give you better advice though, I'll look at your code for a bit longer. As for global variables, what you wrote there with MyClassObject would work fine. You'd use it like this:
MyClass {
public:
MyClass(){};
~MyClass(){};
int variable;
};
MyClass MyClassObject;
// in a method you'd do this
void whateverMethod() {
MyClassObject.variable = 5;
std::cout << MyClassObject.variable << std::endl;
}
That kind of thing. There are some style issues that could be fixed but to be honest I say just get it working first and then we can talk about those.
1) Make them static eg
static string typeArray[MAX];
Initialise them once, they'll remain the same until you change them. Don't try and use them at the same time from two threads.
2) You can create a global object by declaring it at file scope:
class CFoo;
CFoo s_foo;
class CFoo
{
public:
CFoo();
~CFoo();
}
Then s_foo is going to be an instance of CFoo available anywhere which can see s_foo (this file and others which have extern CFoo s_foo;)