Programming C, C++, Java, PHP, Ruby, Turing, VB
Computer Science Canada 
Programming C, C++, Java, PHP, Ruby, Turing, VB  

Username:   Password: 
 RegisterRegister   
 A Start on C++ Some First Programs/Questions
Index -> Programming, C++ -> C++ Help
Goto page Previous  1, 2, 3, 4, 5  Next
View previous topic Printable versionDownload TopicSubscribe to this topicPrivate MessagesRefresh page View next topic
Author Message
[Gandalf]




PostPosted: Mon Jun 27, 2005 6:54 pm   Post subject: (No subject)

Yes... ::blank face::

Thanks for fixing my program... Smile Ok, now I spend the next 2 years trying to figure all that out. I got lost somewhere between defining constructors and the rest of the explanation. I'm learning from a book too, and I was just starting constructors. I think you just got to about the end of the book and beyond (its mostly about C, but it has some C++).

Well, ok, erm... I guess I will try understanding all that. One step at a time. I was aware of private, public, and protected variables and member functions, but the book just left it at public till a bit later.

Your final class is very confusing, I will read your post a few more times.
Do you think I should leave classes till later? Or well, what do you suggest? Should I try and push myself to figure out everything you posted? From what I have right now, this is how I would edit the program.
c++:
#include <iostream>
#include <string>

class sum {
private:
          int current;
public:
          sum(void);
          void add(int value);
} number;

sum:sum()
{
     current = 0;
}

void sum::add(int value)
{
     current += value;
}

int main()
{
    int x1, y1, x2, y2;
    std::string name;

    std::cout << "Hello, what is your name? ";
    std::cin >> name;
    std::cout << std::endl << "Input the first x coordinate: ";
    std::cin >> x1;
    std::cout << "Input the first y coordinate: ";
    std::cin >> y1;
    std::cout << "Input the second x coordinate: ";
    std::cin >> x2;
    std::cout << "Input the second y coordinate: ";
    std::cin >> y2;
    double slope(static_cast<double>(y2 - y1) / (x2 - x1));
    std::cout << std::endl << name << ", the slope is: " << slope << "." << std::endl;

    std::cout << std::endl << "Input the number you want to start with: ";
    std::cin >> number.current;
    number.add(5);
    std::cout << std::endl << "That number plus 5 is " << number.current << "." << std::endl;
    number.add(78);
    std::cout << "That number plus 78 is " << number.current << "." << std::endl;

    std::cout << std::endl << "Press any key to exit.";
    std::cin.ignore(1,'\n');
    std::cin.ignore();

    return 0;
}

Am i correct in assuming that when you do something like sum(void); and sum(); that they are the same?

Also, I also realized that you can declare the object in three different kinds of ways (from what I know). Personally, I don't know the difference yet, but having it right after the class seems simplest to me.

Thanks for the detailed help. I'll get back to this later.

Oh, and importantly, the thing that got me lost at the constructors was that you were declaring it with arguments? So what would that do, allow you to set the initial value of "current"?
Sponsor
Sponsor
Sponsor
sponsor
wtd




PostPosted: Mon Jun 27, 2005 9:03 pm   Post subject: (No subject)

Yes, a constructor that takes arguments can be used to initialize member variables. Since your member variables are almost always going to be private or protected, this should be the only way you have available to initialize them.

For instance, you have "current" being private, but then you try to access it externally:

code:
std::cin >> number.current;


The private qualifier means that "current" is inaccessible from outside the class. This prevents any bit of code from changing the internal state of an object in weird ways.


One classic example is a car. Let's give our car four wheels. Let's also make everything public.

c++:
struct car
{
   int wheels[4];

   car()
   {
      for (int i (0); i < 4; ++i)
         wheels[i] = 0;
   }

   car(const int initial_speed)
   {
      for (int i (0); i < 4; ++i)
         wheels[i] = initial_speed;
   }
};


Now, maybe I'll add an increase speed function.

c++:
struct car
{
   int wheels[4];

   car()
   {
      for (int i (0); i < 4; ++i)
         wheels[i] = 0;
   }

   car(const int initial_speed)
   {
      for (int i (0); i < 4; ++i)
         wheels[i] = initial_speed;
   }

   void increase_speed(const int amount)
   {
      for (int i (0); i < 4; ++i)
         wheels[i] += amount;
   }
};


But, we can still individually access the wheels.

c++:
car elise(40);

car.wheels[2] += 80;


Now, what happens when we have three wheels going 40KPH, and one going 120KPH? Bad, bad things happen. Smile

If the wheels array was private, it wouldn't be a problem.
[Gandalf]




PostPosted: Tue Jun 28, 2005 3:28 pm   Post subject: (No subject)

Ok, so how would I change "current" in my program, should I make a seperate member function in the class, or something else?

This is what I was working on today, I think I got the while loop in proper C++ style.

c++:
#include <iostream>
#include <string>

class counter {
public:
       int count;
       counter(int start);
       ~counter(void);
       void adder(int amount);
};

counter::counter(int start)
{
                     count = start;
                     std::cout << std::endl << "The counter's initial value is: " << count << "." << std::endl;
}

void counter::adder(int amount)   
{
     count += amount;
     std::cout << "The counter is currently at: " << count << ".\n";
}

counter::~counter()
{
                   std::cout << "The final value of the counter is: " << count << "." << std::endl;
}                   

void getlimits(void);
void countloop(void);
int tempstart;   // For the counter constructor.
int tempamount;  // For the adder function in the counter class.
int countlimit;

main()
{
    std::string name;

    std::cout << "Hello, what is your name? ";
    std::cin >> name;
    getlimits();
    countloop();
    std::cout << std::endl << "Press any key to exit.";
    std::cin.ignore(1,'\n');
    std::cin.ignore();
    return 0;
}

void getlimits()
{   
     std::cout << "What integer would you like the counter to start at? ";
     std::cin >> tempstart;
     std::cout << "What integer would you like the counter to end at? ";
     std::cin >> countlimit;
     std::cout << "By how much (integer) would you like the counter to count by? ";
     std::cin >> tempamount;
}

void countloop()
{
     counter doloop(tempstart);
     
     std::cout << std::endl << "Beginning of counting loop." << std::endl;
     while (doloop.count < countlimit - tempamount)
               doloop.adder(tempamount);
     std::cout << "End of the counting loop." << std::endl << std::endl;
}
wtd




PostPosted: Tue Jun 28, 2005 4:24 pm   Post subject: (No subject)

Well, there are several points I should make.

General Theory

First off, in object-oriented programming, we have both member variables, and member functions. Understanding the different roles of these is critical.

Member variables exist to keep track of the internal state of an object. In the car example, we had a 4 element array of integers to represent the speed of each of the wheels on a car.

Member functions exist to manipulate those variables in a controlled way.

Because of this relationship, we want member variables generally to be private, and thus inaccessible from outside the class, and member functions to be public.

On Constructors & Destructors

Constructors and destructors should not print output. This makes it impossible to use them in places where you don't want that output.

Constructors should always use initialization syntax unless it's not possible. Rather than:

c++:
class name
{
   private:
      std::string first, last;
   public:
      name(std::string f, std::string l)
      {
         first = f;
         last = l;
      }
};


I should use:

c++:
class name
{
   private:
      std::string first, last;
   public:
      name(std::string f, std::string l)
      : first(f), last(l)
      { }
};


Destructors should only be used where you have some dynamically allocated member variable(s). Otherwise there's no need to create a destructor.

Member Names

Member functions names should fall into a few categories. Functions swhich return some value should have noun names. You may wish to prefix these with "get" in some way. Member functions which return a boolean value should have names starting with something like "is" or "has".

Member functions that change something about the object should have verb names like "add", "subtract", etc.
[Gandalf]




PostPosted: Thu Jun 30, 2005 9:16 pm   Post subject: (No subject)

Ok, I understand that, thanks.

I'm not sure though. I can't make up my mind as to which language I should learn. Do you think I am getting a pretty good start on C++? Or should I try going down a step to C, without worrying about all the object-oriented stuff? I was also looking at Java, it seems a bit easier, and closer to Turing, which I already have some experience with. For example this:
Java:
import java.util.*;

public class fiveElDoubleArray
{
        public static void main (String[] args)
        {
       
        for (int i = 0; i < 5; i++) {
                sum +=  rand.nextInt
                       
        double[] array = {45.6745, 45345.2342, 67353231.135452431, -341.23, 101.98};
        System.out.println(array);
        }
        }
}


Not sure, C++ seems useful, and I think I know most of what I've read, but it might get too complicated later on...
*sigh* I have no idea... I might just try a little bit of everything and see which works best? I've gained a lot of programming knowledge since I last tried Java, and C as well.
wtd




PostPosted: Thu Jun 30, 2005 9:40 pm   Post subject: (No subject)

Well, C++ and Java may seem useful to you, but here's a handy tip: if it frustrates you to the point where you never get to the useful stuff... then it's not useful to you.

I say keep going. You're doing well. Just take it one step at a time, and if you have questions... ask!
[Gandalf]




PostPosted: Fri Jul 01, 2005 7:35 pm   Post subject: (No subject)

Alright then.

Something that came across me when writing my small answers to your questions was; the reason that my program doesn't output the numbers properly is probably because it is using the postfix form of incrementing. So, how would I use the prefix form when I'm not doing it by 1, but by a variable? The 'problem' i speak of is that it doesn't output the final value of the counter.

Also, what does "static" mean? When you say something like static int 4; or something of that sort.

I am having trouble changing everything from public in my previously posted program. Could you give an example of how it would work in this case? I'll have to work on it some more.

Also, what is an "object stack"? Is it just a group of objects from the same class? What do "[]" those mean as opposed to "()"?
wtd




PostPosted: Fri Jul 01, 2005 7:55 pm   Post subject: (No subject)

[Gandalf] wrote:
Alright then.

Something that came across me when writing my small answers to your questions was; the reason that my program doesn't output the numbers properly is probably because it is using the postfix form of incrementing. So, how would I use the prefix form when I'm not doing it by 1, but by a variable? The 'problem' i speak of is that it doesn't output the final value of the counter.


I know this doesn't directly answer your question, but you should avoid use of global variables, as you did in the code you posted.

Variables should be declared with functions, and then passed to other functions as arguments. Now this becomes slightly different when dealing with objects, where the object's state is maintained by variables declared outside of a function's scope.

So, you want to write a counter class?

c++:
class counter
{

};


There's the basic framework. Now, we want a constructor which setsup the class with a default state.

c++:
class counter
{
   public:
      counter();
};


And we'll want a constructor to setup the object with an initial value of our choosing.

c++:
class counter
{
   public:
      counter();
      counter(const int initial_value);
};


We don't need to allocate any memory, so we don't need a destructor.

We will want to be able to get the current value of the counter object, so we'll have a member function to retrieve that information.

c++:
class counter
{
   public:
      counter();
      counter(const int initial_value);

      int current_value() const;
};


Now, we want a way to increment the counter by one.

c++:
class counter
{
   public:
      counter();
      counter(const int initial_value);

      int current_value() const;

      void increment();
};


And we'll overload that member function's name so we can deal with incrementing by an arbitrary amount.

c++:
class counter
{
   public:
      counter();
      counter(const int initial_value);

      int current_value() const;

      void increment();
      void increment(const int amount);
};


Now, let's implement this. But of course, we need some state to modify first.

c++:
class counter
{
   private:
      int value;
   public:
      counter();
      counter(const int initial_value);

      int current_value() const;

      void increment();
      void increment(const int amount);
};


Our default constructor, which sets value to zero:

c++:
counter::counter() : value(0) { }


Our other constructor:

c++:
counter::counter(const int initial_value) : value(initial_value) { }


The member function to retrieve the current value:

c++:
int counter::current_value() const
{
   return value;
}


And the increment member functions, with one defined in terms of the other:

c++:
void counter::increment()
{
   increment(1);
}

void counter::increment(const int amount)
{
   value += amount;
}


Now, taking this, we can declare a counter in our main function, with an initial value of 0, and loop until counter is 9, incrementing by 1 each time.

c++:
int main()
{
   counter c;

   while (counter.current_value() <= 9)
   {
      std::cout << counter.current_value() << std::endl;
      counter.increment();
   }
}


We could also put ths into for loop format:

c++:
int main()
{
   counter c;

   for ( ; counter.current_value() <= 9; counter.increment())
   {
      std::cout << counter.current_value() << std::endl;
   }
}
Sponsor
Sponsor
Sponsor
sponsor
[Gandalf]




PostPosted: Sat Jul 02, 2005 4:06 pm   Post subject: (No subject)

I'm pretty sure I got it. Still, I'm not really sure why and when to use classes, would it really be useful in that case?

Here, tell me if I got the whole passing to other functions as arguments things right. This is the guessing game I was working on yesterday. It works, but it seems like more trouble than it should be, maybe because I overused functions?
c++:
/*
Guessing Game Program Version 0.4
Started: July 1, 2005
*/


#include <iostream>
#include <string>
#include <ctime>

using namespace std;
void start(void);
void generate_number(int min, int max);
void check_limits(int min, int max);
void guess_time(int min, int max, int random_num, int guess_count);
void check_guess(int number, int random_num, int min, int max, int guess_count);

main()
{     
      start();     
      cin.ignore(1,'\n');
      cin.ignore();
      return 0;
}

void start()
{
     string name;
     int min_range, max_range;
     
     cout << "Gandalf's Guessing Game Version 0.4" << endl << "\n";
     cout << "Hello, what is your name? ";
     cin >> name;
     cout << "Hope you have fun playing the guessing game, " << name << "!" << endl;
     cout << endl << "Minimum number for the range of numbers? ";
     cin >> min_range;
     cout << "Maximum number for the range? ";
     cin >> max_range;
     check_limits(min_range, max_range);
     generate_number(min_range, max_range);
}

void check_limits(int min, int max)
{
     if (min > max | max < min)
        cout << "Invalid input, the program will not run properly, this bug will be fixed later";
}

void generate_number(int min, int max)
{   
     srand((unsigned)time(NULL));
     int random_number(rand() % (max-min+1) + min);
     cout << "Game starting... \n" << endl;
     int guess_count(0);
     guess_time(min, max, random_number, guess_count);
}

void guess_time(int min, int max, int random_num, int guess_count)
{
     int guess;
           
     cout << "Enter your guess (between " << min << " and " << max << "): ";
     cin >> guess;
     check_guess(guess, random_num, min, max, guess_count);     
}

void check_guess(int number, int random_num, int min, int max, int guess_count)
{
     if (number > random_num)
     {
        cout << "Too high!" << endl;
        ++guess_count;
        guess_time(min, max, random_num, guess_count);
     }
     else
     if (number < random_num)
     {
        cout << "Too low." << endl;
        ++guess_count;
        guess_time(min, max, random_num, guess_count);
     }
     else
     if (number == random_num)
     {
        cout << "You got the number!  Good job!" << endl;
        ++guess_count;
        cout << "It took you: " << guess_count << " guesses to get the number.";
     }
     else
         cout << "Invalid number" << endl;
}

I spent a long, long time on that Smile.
wtd




PostPosted: Sat Jul 02, 2005 4:33 pm   Post subject: (No subject)

Speaking of places where you might want to use classes...

Notices how you pass along a min/max combination of numbers frequently? Well, what if we wrap that up into one package?

c++:
class bounds
{
   private:
      int min_bound, max_bound;
   public:
      bounds(const int initial_min, const int initial_max)
      : min_bound(initial_min)
      , max_bound(initial_max)
      { }
   
      int min() const { return min_bound; }
      int max() const { return max_bound; }
};


Of course, we can realize here that the state of the member variables will never change, so why not make them constant.

c++:
class bounds
{
   private:
      const int min_bound, max_bound;
   public:
      bounds(const int initial_min, const int initial_max)
      : min_bound(initial_min)
      , max_bound(initial_max)
      { }
   
      int min() const { return min_bound; }
      int max() const { return max_bound; }
};


And if the member variables can't be changed after initialization, why not allow direct access to them?

c++:
struct bounds
{
   const int min, max;
   
   bounds(const int initial_min, const int initial_max)
   : min(initial_min)
   , max(initial_max)
   { }
};
[Gandalf]




PostPosted: Wed Jul 06, 2005 9:32 pm   Post subject: (No subject)

I see, so in this case it wouldn't matter that you can access the variables outside of the class/struct? The thing that really held me back from understanding your class/struct was the syntax you are using.

A question, is there a more 'convenient' way of defining many things as one... This is what I mean, is there a way to change it?

c++:
#define yes "ya"
#define yes "yep"
#define yes "y"
#define no "nope
#define no "n
//and so on...
1of42




PostPosted: Wed Jul 06, 2005 9:54 pm   Post subject: (No subject)

[Gandalf] wrote:
I see, so in this case it wouldn't matter that you can access the variables outside of the class/struct? The thing that really held me back from understanding your class/struct was the syntax you are using.

A question, is there a more 'convenient' way of defining many things as one... This is what I mean, is there a way to change it?

c++:
#define yes "ya"
#define yes "yep"
#define yes "y"
#define no "nope
#define no "n
//and so on...


Well, you could make a const array of strings, but jut for the record, your code there is not valid - the preprocessor will overwrite each successive definition after it's defined, only "y" and "n" will remain defined.
wtd




PostPosted: Wed Jul 06, 2005 10:10 pm   Post subject: (No subject)

Please don't use preprocessor macros.

As 1of42 alluded to, use an array, or some other kind of collection-ish thing.

An array:

c++:
const std::string valid_affirmative_answers[] = {"ya", "yep", "y"};


And then to check and see if we have a valid answer...

code:
// assume the answer is stored in "answer"

bool valid_answer(false);

for (int i(0); i < 3 && !valid_answer; ++i)
{
   if (answer == valid_affirmative_answers[i])
      valid_answer = true;
}
[Gandalf]




PostPosted: Wed Jul 06, 2005 10:21 pm   Post subject: (No subject)

Thanks! I wasn't thinking 'outside the' little box I created for myself Smile. Should I never use macros? or just not in this way?
wtd




PostPosted: Wed Jul 06, 2005 10:24 pm   Post subject: (No subject)

[Gandalf] wrote:
Thanks! I wasn't thinking 'outside the' little box I created for myself Smile. Should I never use macros? or just not in this way?


Try not to use them ever in C++.

The biggest problem, as I see it, is that with macros you end up seeing a different piece of source code than the compiler.
Display posts from previous:   
   Index -> Programming, C++ -> C++ Help
View previous topic Tell A FriendPrintable versionDownload TopicSubscribe to this topicPrivate MessagesRefresh page View next topic

Page 3 of 5  [ 64 Posts ]
Goto page Previous  1, 2, 3, 4, 5  Next
Jump to:   


Style:  
Search: