Хранение списка имен, связанных с задачами - PullRequest
0 голосов
/ 18 декабря 2018

Итак, я создал эту систему заданий, или я пытаюсь ее создать, чтобы, если кто-то выполнил более семи заданий, следующий человек выполнил семь.

двойников (Бодин,Финн, Тихо) являются лицами.Теперь я не знаю, правильно ли я его использовал (если они должны быть двойными) и как я использую их в этой строке кода:

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

что я хочу, это чтобы номера задач были больше, чемсемь, и Бодин выполнил 7 заданий, он говорит: «Это его время!»

#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;
  }
}

Это один из моих первых проектов еще (мне 13, так что да ....).Мне нужно только знать, как использовать следующую переменную!

Ответы [ 2 ]

0 голосов
/ 18 декабря 2018

Привет и добро пожаловать в C ++.Многие скажут, что C ++ - плохой язык для начинающих.Ну, я давно начал с C ++ и до сих пор учусь.Я на 100% самоучка, и у меня не было преимуществ, которые люди имеют сегодня, с количеством информации, доступной через Интернет, а также с современными форматами, которые доступны.Когда я впервые начал изучать C ++, интернет находился в стадии бурного развития;но большинство веб-сайтов в то время представляли собой почти чистый текст, и даже простые картинки или графики требовали времени для загрузки на экран, потому что это было в эпоху Dial Up.Сегодня люди, которые начинают свою деятельность, имеют преимущества как этого сайта, так и других похожих сайтов и даже видео на YouTube.Тем не менее, я все еще люблю помогать, где могу, потому что это не только помогает вам, но и помогает мне улучшить то, что я уже изучил.C ++ развивался на протяжении многих лет, поэтому я покажу вам небольшое приложение, которое, как мне кажется, имитирует поведение того, что вы описали и пытаетесь сделать.Некоторые из этих методов немного продвинуты, особенно для начинающих, однако я думаю, что это хорошо, если кто-то новичок изучает эти концепции рано.


  • Storage Types & Lifetime - В C++ есть в основном 4 основных типа хранения: Automatic, Dynamic, Static и Thread.Я в основном сосредотачиваюсь на первых 3.

    • Automatic: У него есть срок действия области, в которой он объявлен, и он будет автоматически уничтожен, как только эта область выйдет из закрывающей скобки }
    • Dynamic: Память, представленная указателями, но объявленная с new и должна иметь соответствующие delete или массивы new[] и delete[] соответственно.Они могут жить дольше, чем область, в которой они объявлены. Они будут жить, пока не будет вызвано соответствующее удаление.Если соответствующее удаление не происходит, это приводит к утечке памяти, неверным указателям, висящим указателям и ссылкам и неопределенному поведению.Особое внимание необходимо уделять при использовании raw-pointers;Рекомендуется использовать containers или smart pointers.
    • Static: Они обычно находятся в пространстве имен global и или global filespace.Если static объявлено в main.cpp, у него будет время жизни приложения и область действия всей программы.Если они объявлены в других файлах cpp, они будут иметь область действия этого файла, если только они не объявлены в каком-либо файле header, тогда они будут иметь область действия того, что другой модуль перевода включает в себя этот заголовок.Они похожи на Automatic в том смысле, что они будут автоматически уничтожены, но отличаются тем, что они инициализируются только один раз, сохраняют свое состояние, и вы можете иметь только один их экземпляр.
    • Для демонстрации различных типов классификаций хранения вы можете увидеть мой предыдущий ответ на этот вопрос Q / A .
  • Classes and Inheritance: - (IPolymorphism).

    • Classes:
      • Classes и Structs - определяемые пользователем типы данных.
      • Разница между двумяэто доступ по умолчанию
      • По умолчанию: Structs имеет Public Members & Classes имеет Private Members
      • Членами Class или Struct могут быть любые встроенные типы, указатели на типы, другой определенный пользователем тип данных, а также методы или функции.
      • Member Variables может быть любого Storage Type: Automatic, Dynamic, Static и Thread однако функции-члены обычно Automatic, но могут быть Static.Если у вас есть member variable, он должен быть initialized вне Class's Declaration, чтобы разрешить его symbols.
      • У них есть Constructors и Destructors по умолчанию, но одинМожно создавать свои собственные Constructor или Destructor.Обычно вы видите, как люди упоминают их по коротким именам: ctor & dtor соответственно.
      • Один класс может наследовать от другого.
    • Inheritance:
      • У вас есть Base или Super Classes, и у вас есть Derived или Child Classes
      • Когда Inheriting из класса Base, если ctor класса Base имеет Public, это означает, что вы можете создать объект как Base & Derived Classes.Иногда вам нужен такой дизайн, но иногда вы этого не делаете.
      • Если вы не хотите, чтобы пользователь мог создать экземпляр Base Class, но можетечтобы создать экземпляр Derived Class, все, что вам нужно сделать, это убедиться, что 1 st его ctor равно Protected.Если вы объявите его Private, то даже ваш Derived Classes не сможет получить к нему доступ, и поэтому они не могут быть объявлены.* 2nd Вы хотите убедиться, что ваши Destructors - dtors равны Virtual;в противном случае у вас возникнут проблемы с порядком уничтожения классов.
      • A Base Class может иметь Member Functions, что означает Virtual, что означает, что все Derived Classes должны Implementчто Function.
      • A Base Class может иметь Member Functions, равные Purely Virtual, что аналогично приведенному выше, но также мешает любому объявить экземпляр этого Base Class, посколькуэто делает Base Class Abstract, что означает, что это идея для интерфейса.
      • Пример Virtual Function: virtual update();
      • Пример Purely Virtual: `virtual update () = 0;
  • Containers - (я буду использовать std::container, но я не буду привлекать Algorithms)

    • Существует множество видов контейнеров для разных нужд;Эти контейнеры помогают сделать вашу программу простой, легкой в ​​управлении и отладке, удобной для пользователя и предотвратить многие будущие головные боли вместо использования basic C Arrays.
    • Существует несколько различных типов, и каждый из них имеет свое собственное назначение исвойства, которые я не буду рассматривать все их детали, так как вы можете найти множество информации в сети, касающейся их, но я буду помечать и группировать их по аналогичным свойствам: группировки Sequence Containers, Associative Containers, & Unordered Containers и все они принадлежат std:: namespace.Основное различие между группировками: Sequence Containers похоже на arrays и linked lists, Associative Containers равно binary trees и Unordered Containers похоже на binary trees за исключением того, что они не в порядке, они считаютсяhash tables.
      • Sequence: vector, dequeue, queue, list, forward_list, array
      • Associative: set, multiset, map, multimap
      • Unordered: unordered_set, unordered_multiset, unordered_map, unordered_multimap`
    • Что делает эти контейнеры мощными, так это способностьлибо быстро пройти их, либо быстро вставить и найти в зависимости от того, какой контейнер вы используете.Еще одна полезная функция помогает в процессе управления памятью.Наконец, есть многочисленные algorithms и iterators, которые могут работать с ними.
    • Для получения дополнительной информации о stl я советую посмотреть эту серию youtube по Bo Qian
  • Smart Pointers Существует несколько различных типов, но наиболее важными являются std::shared_ptr<T> и std::unique_ptr<T>.Основное различие между ними состоит в том, что shared имеет reference count от того, сколько объектов имеет к нему доступ;это означает, что он имеет интерфейс открытого типа и может использовать семантику копирования;unique, с другой стороны, имеет только 1 owner за раз, он может передать право собственности, но как только он у первоначального владельца, к нему больше нет доступа.Вы не можете скопировать unique, но вы можете переместить их.Эти интеллектуальные указатели помогают с использованием dynamic memory и управления жизненными объектами для предотвращения утечек памяти, недействительных указателей, висячих указателей и ссылок, неопределенного поведения и т. Д. Они помогают минимизировать использование new & delete и new[] & delete[] соответственно.


Теперь, когда у вас есть понимание некоторых концепций, которые вы будете встречать довольно часто в C++ программах;Сейчас я покажу вам простое приложение, которое я написал на основе того, что, как я понял, вы пытались сделать:

#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;    
}

-Выход-

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

Ссылка на вышеуказанную программу.


Я знаю, что это совсем немного для чтения;но, пожалуйста, внимательно посмотрите на приложение, чтобы попробовать и посмотреть, что оно делает.Вы можете скопировать и вставить это прямо в вашу собственную IDE и попытаться собрать и запустить его, чтобы увидеть его в действии.Надеюсь, это даст вам понимание того, что такое C++.


-Edit-

О коде выше: он немного сложнее, чем он должен быть на самом деле.Во-первых, вы бы не увидели личность одного человека, как его собственный класс.Я только сделал это, чтобы продемонстрировать, что такое inheritance.Я решил использовать std::array вместо std::vector в основном из-за того, что у вас было 3 конкретных людей из вашего предложения.Если у вас есть неизвестное количество людей во время компиляции, тогда std::vector будет правильным контейнером для использования.Вам действительно не нужно было бы использовать наследование.Также, если вы посмотрите на 3 производное classes, там много кода duplicate.Я также использовал shared_ptrs, чтобы показать, как их можно использовать, но они не нужны в вашей конкретной ситуации.Я также использовал static member variables в Derived Classes, чтобы показать static storage.

Вот упрощенная версия приведенного выше кода, имитирующая ваше поведение.Обе программы выполняют одну и ту же задачу аналогично, единственными существенными различиями являются: * Использование inheritance с purely virtual methods, static member storage, container type и dynamic memory с использованием 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;    
}

Вот ссылка для этой версии программы!

0 голосов
/ 18 декабря 2018

Ну, вы на самом деле не отслеживаете, чья это очередь.Кроме того, double не является подходящим инструментом для работы здесь.Я бы сделал что-то вроде этого:

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

Теперь у нас есть список имен, а также счетчик, который говорит, чья это очередь.0 для первого лица, 1 для второго лица и 2 для третьего лица.Затем нам нужна логика для продвижения этого счетчика:

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

Это увеличивает currentUser, а когда оно больше, чем количество людей, оно возвращается к 0, поэтому люди по очереди корректно.

Далее о логике задач я бы предложил что-то вроде этого:

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

Здесь у нас есть счетчик, который отслеживает количество задач и когда он достигает 7, он устанавливает его обратно на 0 и объявляет, что это следующий ход пользователя после вызова advanceUser, чтобы установить это право.

Затем вы можете вызвать incrementTasksDone так, как хотите, например, я проверил это какthis:

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

Это позволит выполнить, например, 100 задач, поэтому ходы будут меняться 14 раз в процессе, и каждый раз будет печататься сообщение.

Кроме того, для полученияДля запуска этого примера обязательно добавьте следующее:

#include <vector>
#include <string>
#include <iostream>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...