Computer Science Canada

transferring to different functions

Author:  signal_1001 [ Wed May 26, 2004 8:07 pm ]
Post subject:  transferring to different functions

i'm making a SIMPLE game of wheel of fortune because im not very good and i was trying to transfer to different functions in order to have just one for spinning the wheel and buying a vowel and solving the puzzle. but it's not carrying the declared variables and stored information. is there anyway i can transfer it without copying the same code over and over?
code:
bool guessed=false;
        while(guessed==false)
        {
cout<<"\n"<<blankPhrase<<endl;
                cout<<"\n\n\tWould you like to a) spin the wheel\n";
                cout<<"\t                  b) buy a vowel\n";
                cout<<"\t                  c) solve the puzzle\n";
                char option;
                cin>>option;                                                  cin.ignore(10,'\n');
                switch (toupper (option)) //giving options
                {
                case 'A':
                        spin();
                        break;
                case 'B': //next option
                        vowel();
                        break;
                case 'C': //last option
                        answer();
                        break;
                default:
                        bred();
                        cout<<"\tInvalid choice, please enter a, b, or c\n";
                        pause();
                }
}

void spin()
{
}

any ideas???

Author:  Mazer [ Wed May 26, 2004 8:31 pm ]
Post subject: 

From what you're saying, you'll either need to make the variables global or pass them to your functions as parameters.

Author:  Andy [ Wed May 26, 2004 8:33 pm ]
Post subject: 

not sure what ur asking, but i think what your trying to say ask is how to use variables in functions. you could either declare your variables local or passes them through parameters...

Author:  guruguru [ Thu May 27, 2004 3:45 pm ]
Post subject: 

You have declared option in the while loop. This means that its scope is only for the while loop. YOu may have other variables declared that way, for I don't know the rest of the program. The procedures cant access local loop variables. I know option isnt important to the function, but you may have made the same mistake with other variables. Otherwise, the procedures can access the global variables (exceptions occur but its a SIMPLE game :p).

Author:  Andy [ Thu May 27, 2004 6:24 pm ]
Post subject: 

guruguru wrote:
exceptions occur
no not really... since well there is no such thing as a procedure and the point of a global variable is so to allow it to be accessed by different functions

Author:  wtd [ Thu May 27, 2004 6:56 pm ]
Post subject: 

Asking the question then getting a correct answer, and then doing something based on that answer should be in separate functions.

code:
char ask_question(std::ostream& out = std::cout, std::istream& in = std::cin)
{
   char option = '\0';
   do
   {
      out << "Would you like to:" <<std::endl
          << "\ta)\tSpin the wheel? << std::endl
          << "\tb)\tBuy a vowel?" << std::endl
          << "\tc)\tSolve the puzze?" << std::endl;
      in >> option;
      option = toupper(option);
   } while (option != 'A' && option != 'B' && option != 'C');
   return option;
}

void do_action(char option_selected std::ostream& out = std::cout)
{
   switch (option_selected)
   {
      case 'A':
         spin_the_wheel();
         break;
      case 'B':
         buy_a_vowel();
         break;
      case 'C':
         solve_the_puzzle();
         break;
      default:
         out << "Bad option!" << std::endl;
         break;
   }
}

Author:  guruguru [ Thu May 27, 2004 6:57 pm ]
Post subject: 

Umm... a procedure is another way of saying function. Some people call them different things... live with it Evil or Very Mad . They are called many things... functions one of the main ones, but I refer to different types of 'functions' differently, big deal. And as for your second point, that was implied and was what I basically said. And yes depending on your definition of global exceptions due occur.

Author:  wtd [ Thu May 27, 2004 7:04 pm ]
Post subject: 

The difference between procedures and functions exists in at least the vast majority of programming languages. However, C and C++ do not enforce that difference.

The difference is that a function does not alter the state of the machine, but returns a new value.

code:
int times_two(int input)
{
   int new_value = input * 2;
   return new_value;
}


A procedure, however, may alter the state of the machine (in the form of variables), but it cannot return a value.

Eiffel is among the few languages which enforce the difference between procedures and functions. Together they are known as "routines".

Author:  guruguru [ Thu May 27, 2004 7:07 pm ]
Post subject: 

Thank you. My point exactly.

Author:  Andy [ Thu May 27, 2004 7:56 pm ]
Post subject: 

wtf you talking about??? he just said they are different... and go ahead and give me your definition of global

Author:  guruguru [ Thu May 27, 2004 8:13 pm ]
Post subject: 

Myself:
Quote:
I refer to different types of 'functions' differently


wtd:
Quote:
The difference is that a function does not alter the state of the machine, but returns a new value.

A procedure, however, may alter the state of the machine (in the form of variables), but it cannot return a value.


I refer to something that returns a value as 'functions', and other as 'procedures'. What wtd said!

I rest my case.

And for global: There can be variables in different files that are global, maybe you call variables in a class a global variable for the class... it depends a lot on what the user defines it as. Not that I agree with all of these, but people can refer to global as many things.

Author:  wtd [ Thu May 27, 2004 8:50 pm ]
Post subject: 

Perhaps the best definition of a global variable is: "a variable which exists independent of any other context."

If for instance, I write a simple Hello, world! in C++:

code:
#include <string>
#include <iostream>

std::string hello_world = "Hello, world!";

int main()
{
   std::cout << hello_world << std::endl;

   return 0;
}


Then hello_wrld exists no matter what else I include in the program, though it may be superseded by a local variable by the same name.

If, however, I put the declaration and initialization of hello_world inside main, then that variable would only exist in the context of any given call to main.

Similarly, if I include the declaration for hello_world as a member of a struct or class (really the same thing in C++) then it only exists in the context of that class (or an instance of that class).

If I include it in a namespace, then it only exists in the context of that namespace.

Author:  guruguru [ Thu May 27, 2004 8:54 pm ]
Post subject: 

Good definition! I assume you're saying that something in a class or main is local.? Or are you tryng to say its global?!?! When I was talking about exceptions, I was glancing at namespaces. Anyways...

Author:  wtd [ Thu May 27, 2004 9:04 pm ]
Post subject: 

A variable declared in a function is local to that function. It has no meaning (or existence) outside of that function.

A "variable" declared in a class declaration isn't really a variable at all. It's more like a mold (seeing as how "template" has it's own meaning in C++) for a variable, and the entire class declaration is merely a blueprint for an object of that class.

In very few programming languages are classes actually "things" in and of themselves, and those tend to be the more dynamic languages, along the lines of Python, Ruby, or Dylan.

Author:  guruguru [ Thu May 27, 2004 9:10 pm ]
Post subject: 

Ok. I agree.

Quote:
In very few programming languages are classes actually "things" in and of themselves


What do you catagorize classes as in C++? A blueprint? It can also be seen as a thing that contains other things can it not be? Because theoretically, a blueprint by itself would do nothing- you have to activate one of its components. But a class can activate its components automatically at creation and destruction. So it's not quite a blueprint and more of a 'designer' that mainly lays out plans but can also implement.

Author:  wtd [ Thu May 27, 2004 9:47 pm ]
Post subject: 

guruguru wrote:
Ok. I agree.

Quote:
In very few programming languages are classes actually "things" in and of themselves


What do you catagorize classes as in C++? A blueprint? It can also be seen as a thing that contains other things can it not be? Because theoretically, a blueprint by itself would do nothing- you have to activate one of its components. But a class can activate its components automatically at creation and destruction. So it's not quite a blueprint and more of a 'designer' that mainly lays out plans but can also implement.


Not really. In the end a class (in C++) is merely a blueprint. A class inside a class merely gets "name-mangled" into something else by the compiler. As for "members" of a class... well, they merely describe what an object of that class should have.

Trust me, this is coming from someone who's currently making the latest of several attempts to develop an assembler for a simple virtual machine that does several of these things. In the end, you have two choices:

  • A really complex computer that can understand ideas like classes as first class objects themselves. Or...
  • A really simple machine that expects the compiler to break sophisticated programming concepts down into simple instructions.


The latter is the route that C and C++ take, since they're compiling to native code for very simple machines. Languages with virtual machines (like the aforementioned Python, Ruby, etc.) can afford the former approach, since their machine exists only in software and isn't limited by the actual silicon.

Author:  guruguru [ Thu May 27, 2004 9:53 pm ]
Post subject: 

Very interesting... I'm not trying to argue with you btw :p. I'm curious, for what virtual machine are you developing an assembler for?

Author:  wtd [ Thu May 27, 2004 10:01 pm ]
Post subject: 

My own "Flick" virtual machine.

The design has gone through various stages, depending on my mood at the time.

The latest incarnation featured two accumulator registers (one 64-bit int register and one 64-bit floating point register), a branch link register, a stack, and a flat memory space.

My next design will likely have a large number of general purpose registers.

Author:  signal_1001 [ Fri May 28, 2004 8:32 pm ]
Post subject: 

Well thank you for your arguments, unfortunately im still quite confused. I had heard about global variables but apparently we're not suppose to use them for one reason or another i'm not sure. how exactly do you pass variables through functions as parameters. That may be what i want. What i sort of need is for example to be able to get the name of the player during my puzzles() when they entered it during the main().
I really liked that code that was used.
Quote:
Code:
char ask_question(std::ostream& out = std::cout, std::istream& in = std::cin)
{
char option = '\0';
do
{
out << "Would you like to:" <<std::endl
<< "\ta)\tSpin the wheel? << std::endl
<< "\tb)\tBuy a vowel?" << std::endl
<< "\tc)\tSolve the puzze?" << std::endl;
in >> option;
option = toupper(option);
} while (option != 'A' && option != 'B' && option != 'C');
return option;
}

void do_action(char option_selected std::ostream& out = std::cout)
{
switch (option_selected)
{
case 'A':
spin_the_wheel();
break;
case 'B':
buy_a_vowel();
break;
case 'C':
solve_the_puzzle();
break;
default:
out << "Bad option!" << std::endl;
break;
}
}
it looks a lot more cleaned up than mine, unfortunatly im only using a simple application, and my teacher may have taught us more C than C++ because we use iostream.h, etc. and no std:: .... i'm not really sure though. anyways... basically now im asking how passing through parameters work. Rolling Eyes thanks

Author:  wtd [ Fri May 28, 2004 10:49 pm ]
Post subject: 

You're using those things because your teacher is teaching you C++ with an old compiler (or with a recent compiler, but with an outdated mindset).

Arguments to routines (functions and procedures) are passed by value by default in C and C++. This means the only thing a routine gets is a copy of whatever variable was passed in. That function cannot then make any changes to the original. Think about going to a library's reference section and not being allowed to take a book from the library, but being allowed to photocopy it. You can't do anything to the original, but you can mark up and alter your copy in any way you'd like.

For a practical example, let's say you want to pass a player's name, and their score into a function which displays their name and score, and adds $100 to their score.

Well, let's start with just displaying these things.

code:
void display_info(std::string player_name, int player_score)
{
   std::cout << player_name << " has " << player_score << std::endl;
}


Ok, that's pretty straightforward.

But, if we now want to add some amount of money to the player_score we can't. Well, we can but since the value inside the function is merely a copy of what was passed in, the addition won't have any effect outside of the function.

In order to achieve this we'll make use of C++'s pass-by-reference syntax. Using this we give the function an actual reference to the variable we originally passed in.

code:
void display_info_and_add_to_player_score(std::string player_name, int& player_score)
{
   std::cout << player_name << " has " << player_score << std::endl;
   player_score += 100;
}


On terminology

Typically the "player_name" and "player_score" in the routine header are referred to as parameters. The actual variables supplied when the routine is used are known as arguments.

And now for something entirely different

So we've got player_name and player_score parameters for functions. These are obviously related variables, yet for each player in the game we're keeping track of them with separate variables that are easy to get mixed up. It'd be pretty easy to display Mike's name with Bob's score, for instance.

Fortunately C++ gives us a solution in the form of structs by which we can create data types that don't normally exist in the language. So, let's create a player data type that can store a player's name and score.

code:
struct player
{
   std::string name;
   int score;
};


Now, structs in C++ as well as being able to contain information, can also describe actions associated with that information. In fact, those actions are how we should interact with that information, rather than having direct access to it. So we make those internal variables private, rather than publicly accessible.

code:
struct player
{
   private:
      std::string name;
      int name
};


The first publicly available thing should be the constructor. This is a special routine (unlke other routines) that initializes the state of an object. It's always given the same name as the struct/class.

code:
struct player
{
   private:
      std::string name;
      int name
   public:
      player(std::string init_name) : name(init_name), score(0) { }
};


So now we can create a player and then do absolutely nothing with it. So, le's see, we wanted to be able to print the information out.

The proper way to do this in C++, as you've doubtless seen is using the << operator.

code:
std::cout << "Hello, world!" << std::endl;


But that only works on a few types. It won't work on our player data type. But, with operator overloading, we can make it work with player variables.

The basic syntax for overloading the << operator is:

code:
std::ostream& operator<<(std::ostream& out, const player& p)


Let's take this apart. std::ostream is the type of output streams like std::cout (or just "cout" if you're "using namespace std;"). The & indicates we're returning a reference to an output stream.

Similarly, we're passing in a reference to an output stream.

The other variable we'll be passing in is a constant reference to a player object. The const doesn't mean we can't pass in a normal player variable, but once we do, we won't be able to change that object. Since we don't want the simple act of printing out the object's state to change that state, this is a good thing.

Now this is all good, but this routine also needs access to the innards of the player object, which are normally inaccessible. But, if we declare the routine as a friend of the player object, we can get around this limitation.

code:
struct player
{
   private:
      std::string name;
      int name
   public:
      player(std::string init_name) : name(init_name), score(0) { }
      friend std:ostream& operator<<(std::ostream& out, const player& p)
      {
         out << p.name << " has " << p.score;
         return out;
      }
};


Now, all that's left to do is increment the player's score. Well, we can overload the += and -= operators to do this to.

code:
struct player
{
   private:
      std::string name;
      int name
   public:
      player(std::string init_name) : name(init_name), score(0) { }
      friend std:ostream& operator<<(std::ostream& out, const player& p)
      {
         out << p.name << " has " << p.score;
         return out;
      }
      void operator+=(int increment_by)
      {
         score += increment_by;
      }
      void operator-=(int decrement_by)
      {
         score -= decrement_by;
      }
};


Now, to deal with players...

code:
int main()
{
   player mike("Mike");

   std::cout << "Mike before winning $100:" << mike << std::endl;
   mike += 100;
   std::cout << "Mike after winning $100:" << mike << std::endl;
}

Author:  signal_1001 [ Sat May 29, 2004 12:26 pm ]
Post subject: 

Wow... that was a big help, sort of, i understood 95% of it. but now i feel like a bit of an idiot cuz since i havent been taught how to use std:: or what it really does or means, i've been trying to figure out how it all works through reading other peoples problems on this site and the tutorials and stuff. And it seems like my teacher is just out of date because we're using MVC++ 6.0 so why he didnt teach use using namespace std and all im not too sure. anyways thanks for the help though

Author:  guruguru [ Sat May 29, 2004 12:30 pm ]
Post subject: 

Using the std namespace as in typing "using namespace std" isnt bad, it's just a different way of accessing std functions. I don't know the deatils (wtd can help you more) buy I believe using std:: before the function is more reliable and faster since you are not imporiting the whole namespace.

Author:  wtd [ Sat May 29, 2004 2:29 pm ]
Post subject: 

The standard (std) namespace contains a lot of stuff, and bringing all of that into your program's namespace is generally a bad idea. If you do use:

code:
using namespace std;


Make sure it's only on a function by function basis, and that whenever you define class members, or function parameters, you use the "fully qualified" name (as in "std::ostream").


: