1

So i have made this task system, or i'm trying to make it, so that if someone has done more than seven tasks, the next person has to do seven.

the doubles (Bodine, Finn, Tycho) are the persons. Now i dont know if i used it correctly,(if they need to be doubles) and how i use them in this line of code:

if (taskNumbers == 7)
{
    std::cout << "It's " + /*what to do here? */ + "time!";

what i want is that if the task numbers are higher than seven, and Bodine has done 7 tasks, it says "Its finn his time!"

#include <iostream>

using namespace std;

double Bodine;
double Finn;
double Tycho;
bool tasksDone = true;
int taskNumbers = 0;

int main()
{
  if (taskNumbers > 7)
  {
    std::cout << "It's " + /*what to do here? */ + "time!";
    return 1;
  }
}

This is one of my first projects yet(im 13, so yeah....). I only need to know how to use the next variable!

tadman
  • 208,517
  • 23
  • 234
  • 262
Rohan
  • 23
  • 6
  • 6
    It's not clear from your question what the goal is here. How are tasks recorded? How do you save this information between runs of the program? The way this is defined, `taskNumbers` is and always will be zero. – tadman Dec 18 '18 at 15:37
  • i just edited it, my question is how i use the next variable, and if i need to use doubls for this situation – Rohan Dec 18 '18 at 15:38
  • 1
    While C++ can be taught to just about anyone, it's a lot more nuanced and tricky than others to pick up on. You may want to start out with something a bit more forgiving like Python, Ruby or JavaScript to get a handle for how programming works in general before diving head-long into something like C++ which has other layers like compiling, linking, strong typing and so on. – tadman Dec 18 '18 at 15:38
  • You need a double if you want to represent non-integer numeric values, like `3.92` or what have you. Since these values aren't used in your code, you really don't need them. The correct type for a given variable depends on what data it will store. – tadman Dec 18 '18 at 15:39
  • @tadman i think its good for me to start out with c++, i heard that if you master c++, you'll easily understand all the others. – Rohan Dec 18 '18 at 15:44
  • @tadman just names, do i need chars for these? – Rohan Dec 18 '18 at 15:45
  • If you're looking to print the names (Bodine, Finn, Tycho) you should use `std::string` to store the names. Maybe even a `std::vector` to store all the names in one container. – super Dec 18 '18 at 15:45
  • 1
    That's a big *if*. Unless you have a mentor who knows C++ well this can be a very difficult road to travel. C++ is extremely unforgiving, if you make a tiny mistake your program will abruptly crash or behave very strangely, leading to hours of frustrating debugging. That's presuming it compiles in the first place, and that can be tricky to resolve as well. I'm not saying you can't learn C++, but as a "first" language it's quite a challenge. – tadman Dec 18 '18 at 15:46
  • @Rohan If you want to learn C++, it'll be good for you to get a [good book](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). It'll help you avoid many newbie's mistakes. – Rhathin Dec 18 '18 at 15:46
  • that's usefull @super – Rohan Dec 18 '18 at 15:46
  • JavaScript is a good place to get familiar with the general principles, it doesn't take long to pick up the basics, and once you get comfortable with the general idea of variables, functions, return values, conditionals and so on, then you can pivot back to C++ and try again. You'll find JavaScript and C++ have a fairly similar syntax for a lot of things, there's a lot of overlap, but JavaScript won't randomly crash or explode like C++ does because of simple mistakes. – tadman Dec 18 '18 at 15:47
  • For names, those are string values, so `std::string` it is. You won't get very far here without a really solid [reference guide to C++](https://en.cppreference.com/w/) and a [complete reference book](http://www.stroustrup.com/4th.html) of some sort. Both of these are highly technical reads, so be prepared for a lot of challenges. – tadman Dec 18 '18 at 15:49
  • 1
    There's no concept in C++ of a 'next variable' (or any other language as far as I know). What you working towards is the idea of a data structure, that defines an order for the people in your simulation. For that the simple choice would be a vector of people and a variable indicating who the current person is. – john Dec 18 '18 at 15:50
  • There are many tutorials on YouTube which could be useful to you. Check out the VoidRealms channel for an easy to follow introduction. – Michael Surette Dec 18 '18 at 16:20

2 Answers2

2

Well, you're not really keeping track of whose turn it is. Also, double is not the right tool for the job here. I would do something like this:

std::vector<std::string> users = { "Bodine", "Finn", "Tycho" };
int currentUser = 0;

Now we have a list of names as well as a counter that says whose turn it is. 0 is for the first person, 1 for the second person, and 2 for the third person. Then we need the logic to advance that counter:

void advanceUser() {
    if (++currentUser >= users.size()) {
    currentUser = 0;
    }
}

This increases currentUser, and when it is bigger than the amount of people, it loops back to 0, so the people take turns correctly.

Next about the task logic, I would suggest something like this:

int tasksDone = 0;
void incrementTasksDone() {
    if (++tasksDone >= 7) {
        advanceUser();
        std::cout << "It's " + users[currentUser] +"'s time!" << std::endl;
        tasksDone = 0;
    }
}

Here we have a counter that keeps track of the amount of tasks, and when it hits 7, it sets it back to 0 and announces that it's the next user's turn after callling advanceUser to set that right.

You can then call incrementTasksDone however you want, for instance I tested it like this:

int main()
{
    for (int i = 0; i < 100; i++) {
        incrementTasksDone();
    }
}

That would get 100 tasks done, for instance, so the turns would change 14 times in the process and it would print the message every time.

Also, to get this example to run, be sure to add the following includes:

#include <vector>
#include <string>
#include <iostream>
Blaze
  • 16,736
  • 2
  • 25
  • 44
0

Hello and welcome to C++. Many will say that C++ is a bad language of choice for starters. Well I started with C++ myself a long time ago and I'm still learning to this day. I am 100% self taught and I didn't have the advantages that people do today with the amount of information that is available over the internet as well as the modern formats that are available. When I first started learning C++, the internet was in the stage of booming; but most websites back then were nearly pure text and even simple pictures or graphics took a while to load to the screen because this was in the era of Dial Up. Today, people who are starting out have the advantages of both this website, other similar sites and even youtube videos. However, I still enjoy helping where I can because it doesn't only help you, but it also helps me to improve what I have already learned. C++ has evolved over the years so what I'll do here is demonstrate to you a small application that I believe mimics the behavior of what you have described you are trying to do. Some of these techniques are a little advanced especially for beginners, however I think it is a good fit that someone who is new learns these concepts early.


  • Storage Types & Lifetime - There are basically 4 main storage types in C++: Automatic, Dynamic, Static and Thread. I mostly focus on the first 3.

    • Automatic: It has the lifetime of the scope that it is declared in and will automatically be destroyed once that scope exits from its closing brace }
    • Dynamic: Memory that is represented by pointers but declared with new and must have a matching delete, or arrays new[] and delete[] respectively. They can live longer than the scope they are declared in. They will live until their matching delete is called. If no matching delete takes place, this leads to a memory leak, invalid pointers, dangling pointers & references and undefined behavior. Special Care needs to be taken when using raw-pointers; it's advisable to use either containers or smart pointers.
    • Static: These are typically found in the global namespace and or global filespace. If a static is declared in the main.cpp it will have a lifetime of the application and the scope of the whole program. If they are declared in other cpp files, they will have the scope of that file, unless if they are declared in some header file, then they will have the scope of what other translation unit includes that header. They are similar to Automatic in the sense they will automatically be destroyed, but they differ as in the fact that they are initialized only once, the maintain their state and you can only have a single instance of them.
    • For a demonstration of the different types of storage classifications you can see my previous answer to this Q/A.
  • Classes and Inheritance: - (I will not involve Polymorphism).

    • Classes:
      • Classes and Structs are user defined data types.
      • The difference between the two is the default access
      • By default: Structs have Public Members & Classes have Private Members
      • Members of a Class or Struct can be any built in type, pointers to types, another user defined data type, and methods or functions.
      • Member Variables can be of any Storage Type: Automatic, Dynamic, Static and Thread, however, member functions are usually Automatic but can be Static. If you have a member variable it has to be initialized outside of the Class's Declaration to resolve it's symbols.
      • They have Constructors and Destructors by default, but one can create their own custom Constructor or Destructor. You will typically see people mention them by their short names: ctor & dtor respectively.
      • One class can inherit from another.
    • Inheritance:
      • You have Base or Super Classes, and you have Derived or Child Classes
      • When Inheriting from a Base class, if the Base class's ctor is Public, this means you can create an object of both the Base & Derived Classes. Sometimes you want this kind of design, but there are times when you don't.
      • If you do not want the user to be able to create an instance of the Base Class, but are able to create an instance of the Derived Class then all you need to do is make sure that 1st its ctor is Protected. If you declare it Private, then even your Derived Classes can not access it and therefore they can not be declared. *2nd You want to make sure that your Destructors - dtors are Virtual; otherwise you will have issues with the order in which classes are destroyed.
      • A Base Class can have Member Functions that are Virtual which means All Derived Classes must Implement that Function.
      • A Base Class can have Member Functions that are Purely Virtual which is similar above, but also prevents anyone from declaring an instance of this Base Class because this makes the Base Class Abstract which means it's an idea for an interface.
      • Example Virtual Function: virtual update();
      • Example Purely Virtual : `virtual update() = 0;
  • Containers - (I will use a std::container, but I won't involve any Algorithms)

    • There are many kinds of containers for different needs; these containers help to keep your program simple, easy to manage and debug, user friendly and to prevent many future headaches instead of using basic C Arrays.
    • There are a few different types and they each have their own purpose and properties which I will not go over all of their details as you can find a plethora of information on the net regarding them, but I will label and group them to their similar properties: The groupings are Sequence Containers, Associative Containers, & Unordered Containers and these all belong to the std:: namespace. The major difference between the groupings are: Sequence Containers are like arrays and linked lists, Associative Containers are binary trees, and Unordered Containers are similar to the binary trees except they are not in order, they are considered hash tables.
      • Sequence: vector, dequeue, queue, list, forward_list, array
      • Associative: set, multiset, map, multimap
      • Unordered: unordered_set, unordered_multiset, unordered_map, unordered_multimap`
    • What makes these containers powerful is the ability to either traverse them quickly or to insert and find quickly depending on which container you are using. Another good feature is helping in the process of memory management. Finally is the numerous algorithms and iterators that can do work on them.
    • For more information on the stl I advise to watch this youtube series by Bo Qian
  • Smart Pointers There are a few different types, but the most important two are std::shared_ptr<T> and std::unique_ptr<T>. The major difference between the two is that shared has a reference count to how many objects have access to it; it means it has a public type interface and can use copy semantics; unique on the other hand has only 1 owner at a time, it can transfer ownership but once it does the original owner no longer has access to it. You can not copy unique, but you can move them. These smart pointers help with the use of dynamic memory and life time object management to prevent memory leaks, invalid pointers, dangling pointers and references, undefined behavior etc. They help to minimize the use of new & delete and new[] & delete[] respectively.


Now that you have an understanding of some of the concepts that you will see quite often in C++ programs; I will now show you the simple application that I have written based off of what it was that I perceived you were trying to do:

#include <array>
#include <exception>
#include <memory>
#include <string>
#include <iostream>  

class Person {
protected:      
    std::string name_;
    int tasksCompleted_;
public:
    const std::string& whoIs() const { return name_; }
    int numberTasksCompleted() const { return tasksCompleted_; }

    virtual void performTask() = 0;

protected:
    explicit Person(const std::string& name) : name_{ std::move(name) } {}
    virtual ~Person() = default;
};

class Bodine final : public Person {
private:
    static int currentTask;
public:
    explicit Bodine(const std::string& name = std::string("Bodine")) : Person(name) {}
    virtual ~Bodine() = default;

    virtual void performTask() { currentTask++; tasksCompleted_ = currentTask;  }
};
int Bodine::currentTask = 0;

class Finn final : public Person {
private:
    static int currentTask;
public:
    explicit Finn(const std::string& name = std::string("Finn")) : Person(name) {}
    virtual ~Finn() = default;

    virtual void performTask() { currentTask++; tasksCompleted_ = currentTask; }
};
int Finn::currentTask = 0;

class Tycho final : public Person {
private:
    static int currentTask;
public:
    explicit Tycho(const std::string& name = std::string("Tycho")) : Person(name) {}
    virtual ~Tycho() = default;

    virtual void performTask() { currentTask++; tasksCompleted_ = currentTask; }
};
int Tycho::currentTask = 0;

int main() {
    try {
        std::array<std::shared_ptr<Person>, 3> people{
            std::shared_ptr<Person>(new Bodine()),
            std::shared_ptr<Person>(new Finn()),
            std::shared_ptr<Person>(new Tycho())
        };

        // For each person in array
        const int MAX_TASKS = 7;
        int currentPerson = 0;
        for (auto& p : people) {
            std::cout << p->whoIs() << " has performed task #:\n";
            while (p->numberTasksCompleted() < 7) {
                p->performTask();
                std::cout << p->numberTasksCompleted() << '\n';
                if (p->numberTasksCompleted() == MAX_TASKS) {
                   currentPerson++;
                   if (currentPerson <= (people.size() - 1) ) {
                       std::cout << "It's your turn " << people[currentPerson]->whoIs() << " to do some tasks.\n";
                   }
                   break;
                }
            }
        }

    } catch( std::runtime_error& e ) {
        std::cerr << e.what() << std::endl;
        return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;    
}

-Output-

Bodine has performed task #:
1
2
3
4
5
6
7
Finn has performed task #:
1
2
3
4
5
6
7
Tycho has performed task #:
1
2
3
4
5
6
7

Link to above program.


I know this is quite a bit to read; but please look closely over the application to try and see what it is doing. You can copy and paste this right into your own IDE and try to build and run it to see it in action. Hopefully this will give you a grasp of what C++ is.


-Edit-

About the code above: it is a little more complex than what it truly needs to be. First off you would not really see a single person's identity as it's own class. I only did this to demonstrate what inheritance is. I choose to use std::array instead of std::vector mainly due to the fact that you had 3 specific people from your proposal. If you have an unknown amount of people at compile time then std::vector would be the correct container to use. You wouldn't really need to use inheritance either. Also if you look at the 3 derived classes there is a lot of duplicate code. I also used shared_ptrs to show how they can be used, but are not necessary in your specific situation. I also used static member variables in the Derived Classes to show static storage.

Here is a simplified version of the above code to mimic your behavior. Both programs do the same task similarly, the only major differences are: The use of inheritance with purely virtual methods, static member storage, container type, and dynamic memory via the use of shared_ptr.

#include <exception>
#include <iostream>
#include <string>
#include <vector>    

class Person {
private:    
    std::string name_;
    int tasksCompleted_;
public:
    explicit Person(const std::string& name) : name_(name), tasksCompleted_(0) {}

    const std::string& whoIs() const { return name_; }
    int numberTasksCompleted() const { return tasksCompleted_; }

    void performTask() { tasksCompleted_++; }
};

int main() {
    try {
        std::vector<Person> people{
            Person( "Bodine" ),
            Person( "Finn" ),
            Person( "Tycho" )
        };

        // For each person in array
        const int MAX_TASKS = 7; // Don't like magic numbers!        
        int currentPerson = 0; // Needed variable
        for (auto& p : people) {
            std::cout << p.whoIs() << " has performed task #:\n";
            while (p.numberTasksCompleted() < MAX_TASKS) {
                p.performTask();
                std::cout << p.numberTasksCompleted() << '\n';
                if (p.numberTasksCompleted() == MAX_TASKS) {
                   currentPerson++;
                   if (currentPerson <= (people.size() - 1) ) {
                       std::cout << "It's your turn " << people[currentPerson].whoIs() << " to do some tasks.\n";
                   }
                   break;
                }
            }
        }

    } catch( std::runtime_error& e ) {
        std::cerr << e.what() << std::endl;
        return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;    
}

Here is the link for this version of the program!

Francis Cugler
  • 7,788
  • 2
  • 28
  • 59
  • i think my c++ version is too old... it cant run – Rohan Dec 18 '18 at 18:15
  • what IDE do you use for your projects? – Rohan Dec 18 '18 at 18:18
  • @Rohan I use Visual Studio 2017 Community Edition and I have the language settings set to `C++17` or `newest standard draft`. – Francis Cugler Dec 18 '18 at 18:21
  • did you teach this all to yourself? Were you just testing it out? Or were you searching the web, looking at online tutorials? because I'd say you are a professional! – Rohan Dec 18 '18 at 19:18
  • and about your code, I was more looking for a program that says after 7 tasks, okay, now it's your turn, you know? – Rohan Dec 18 '18 at 19:28
  • @Rohan, I've taught myself the basics of C++ programing by learning the syntax, the concepts, and by doing. Learning how to use the debugger and so on. I've learned most of it through tutorials over the years, and I improved my knowledge of proper use mostly from here at stack. The biggest part of programming, is first breaking down your problem into parts. You first need to know what your program has to do. Then you need to know what components you need. Then you write a small part or simple function to test it, then build upon that. – Francis Cugler Dec 18 '18 at 19:30
  • @Rohan, you can add that to the `cout` statements. I'd update my examples but currently atm I'm running Visual Studio Installer for an update. I can try to do it here in place, but I won't be able to run & debug it. – Francis Cugler Dec 18 '18 at 19:31
  • my visual studio says i need to include pch.h, now you dont do that? how? – Rohan Dec 18 '18 at 19:34
  • dont you use pch.h, because my visual studio says i need it to compile and run – Rohan Dec 18 '18 at 19:56
  • @Rohan I made an update to the programs. I'll even add them to an online compiler that you can view. – Francis Cugler Dec 18 '18 at 19:59
  • @When you load up visual studio and you select `file->project->new`; Look for the `C++` section on the left, then on the right choose `empty` project; give it a name and say okay... Then it will generate an empty solution and project for your. In the Solution Explorer look for the nested project under the current solution you just created, and you will see folders. Where it says `source` for the folder name, right click on it and from the context menu select new file. In the window that comes up, make sure `cpp` is selected, at name it main and hit okay. Then open main.cpp and begin typing... – Francis Cugler Dec 18 '18 at 20:03
  • where does it say source, it says the name of the project --> references --> external dependencies, resource files, header files, source files https://imgur.com/a/Y7AOmmZ – Rohan Dec 18 '18 at 20:11
  • @Rohan In the solution explorer under your project there is a tree structure that has folders, one of them will say headers and the other will say source. The one that says `Source Files` you will right click on that to create a new file. – Francis Cugler Dec 18 '18 at 20:16
  • because i get that... im not thaaat new – Rohan Dec 18 '18 at 20:17
  • @Rohan; Check the links to the programs above, they will direct you to an online compiler of the working applications: both versions. I also updated some of the code and made a comment about it and why... – Francis Cugler Dec 18 '18 at 20:19
  • is there really a difference? because i dont know, but the first one looks like way too much effort for exactly the same thing, is it just rewritten, the second one? – Rohan Dec 18 '18 at 20:22
  • @Rohan the first one uses `std::array` instead of `std::vector`; both containers have their uses. `std::array` has to know its size at `compile time` as its internal structure is wrapped around a `C style array` and is of a fixed size. `std::vector` is similar as it is also wrapped around `c array` but it will grow dynamically in size as you put things into it. In the first example I also demonstrated `Inheritance of classes`, `Static Storage`, `Dynamic` memory via the use of `std::shared_ptr`. It all depends on your need and use... – Francis Cugler Dec 18 '18 at 20:27
  • @Rohan ...continued both applications do the same exact task, but they are doing them differently. Sometimes you just need a container of objects, sometimes you need those objects to live longer so you need pointers to them so their memory has to be dynamic instead of automatic. – Francis Cugler Dec 18 '18 at 20:29