• Как использовать "гибкость" двумерного массива, перед одномерным?

    @Mercury13
    Программист на «си с крестами» и не только
    Итак, перед нами задача: сделать динамический массив «умных указателей единоличного владения». Умный указатель единоличного владения (std::unique_ptr из C++11) — это указатель, который самолично владеет выделенной памятью; при исчезновении указателя исчезает и память.

    Раз мы только учимся, мы не будем влезать в самописные шаблоны C++, готовые шаблоны STL (кроме algorithm и string) и новый, но уже реализованный во всех компиляторах стандарт C++11. Это довольно серьёзное ограничение; если его снять, можно серьёзно упростить себе жизнь. А для этого мы отделим структуру данных от жизненных объектов и реализуем объект StudentList. Пишу с листа, возможны ошибки.

    Да, и без C++11 умный указатель единоличного владения реализовать довольно тяжело — поэтому структуру данных будем делать «монолитно», без разделения на умный указатель и динамический массив.

    #include <algorithm>
    
    class StudentList
    {
    public:
      StudentList();
      ~StudentList();
      Student& add();   // добавить пустого студента и выдать ссылку на новенького
      size_t size() const { return fSize; }
      Student& operator[](size_t i) { return *fData[i]; }   // можно также наладить проверку диапазона — сделай это сам…
      const Student& operator[](size_t i) const { return *fData[i]; }
      void clear();
    private:
      typedef Student* PStudent;
      PStudent* fData;
      size_t fSize, fCapacity;   // реальное кол-во студентов и на сколько студентов у нас заведено памяти.
                            // Указатели [fSize..fCapacity) резервные, их значение не определено и высвобождать
                            // их не надо.
      enum { BLOCK_SIZE = 16; };
      StudentList(const StudentList&) {}   // копирование запрещаем, хочешь — реализуй сам и вынеси в public
      StudentList& operator=(const StudentList&) { return *this; }  // аналогично
    };
    
    StudentList::StudentList(); : fData(NULL), fSize(0), fCapacity(0) {}
    
    Student& StudentList::add()
    {
      // Убедиться, что массива хватает; если нет — расширить
      if (fSize >= fCapacity) {
        size_t newCapacity = fCapacity + BLOCK_SIZE;
        PStudent* newData = new PStudent[newCapacity];
        std::copy(fData, fData + fSize, newData);
        delete[] fData;
        fData = newData;
        fCapacity = newCapacity;
      }
      // Завести нового студента
      Student* r = new Student;
      fData[fSize++] = r;
      return *r;
    }
    
    void StudentList::clear()
    {
       for (size_t i = 0; i < fSize; ++i)
         delete fData[i];
       delete[] fData;
       fData = NULL;
       fSize = 0;
       fCapacity = 0;
    }
    
    StudentList::~StudentList()
    {
       clear();
    }


    Удаление и прочее сам наладишь?

    А группа будет пользоваться нашим списком.

    #include <string>
    
    class AcademyGroup
    {
    public:
       std::string name;
       StudentList students;  // при желании можно заинкапсулировать и его.
    };


    Это перед нами, правда, не двухмерный массив, как я уже сказал. Массив, хоть и Student**, но одномерный; каждый элемент массива — умный указатель единоличного владения. Если бы мы писали на STL C++11, это был бы std::vector<std::unique_ptr<Student>>.

    Кроме УУЕВ, существует также умный указатель совместного владения std::shared_ptr.

    Можно сделать второй вариант — массив из одномерных массивов. Если он заполнился — заводим ещё один массивчик. Пишется немного сложнее, особенно если не пользоваться STL. На STL — std::deque<Student>.
    Ответ написан
    6 комментариев
  • Как заполнить массив в c++?

    @abcd0x00
    #include <iostream>
    
    using namespace std;
    
    struct package {
        int status;
        unsigned char data[20];
    };
    
    int main()
    {
        package pkg = { 0, { 0x01, 0x02, 0x03 } };
    
        cout << pkg.status << int(pkg.data[0]) << endl;
        return 0;
    }
    Ответ написан
    2 комментария
  • Растет ли стек, если рекурсивный вызов функции - последняя операция?

    sergey-gornostaev
    @sergey-gornostaev Куратор тега Java
    Седой и строгий
    В Java нет оптимизации хвостовой рекурсии.
    Ответ написан
    Комментировать
  • Растет ли стек, если рекурсивный вызов функции - последняя операция?

    maaGames
    @maaGames
    Погроммирую программы
    (С++)Сохраняется адрес возврата, так что растёт. Про Java не знаю, как ВМ реализована.
    Всегда можно запустить бесконечную рекурсию и посмотреть, растёт ли память.)
    Ответ написан
    7 комментариев
  • Почему не работает оператор &&?

    0neS
    @0neS
    Подумайте хорошенько что Вы вот тут написали:
    p <=0 && p >= 23
    Ответ написан
    3 комментария
  • Почему функция не возвращает нужное значение?

    @Alexander1705
    • Обнулить можно переменную, но не значение.
    • Обнулить - значит присвоить ноль.
    • Из предыдущего вытекает, что нельзя обнулить до заданного предела, потому ноль он и в Африке ноль, и нет у него никакого предела.
    • Какой ещё остаток при обнулении?
    • Остаток от деления 99 на 25 - это 24, а не 1
    • Зачем вы создали кучу переменных, которые не используете?
    • В условии цикла вы делаете проверку coin25 > 0, но зачем, если вы никогда не изменяете эту переменную?
    • Выражение surrender - coin25 вычисляет значение, но никуда его не записывает. Если хотите отнять что-то от переменной, можно использовать foo = foo - bar; или foo -= bar;


    Если я правильно понял, и нужно посчитать минимальное количество монет, то вам нужно что-то вроде этого:
    #include <iostream>
    
    int main()
    {
        const int N = 4;
        const int coinsValue[N] = {25, 10, 5, 1};
        int coinsCount[N] =       { 0,  0, 0, 0};
    
        int sum;
        std::cin >> sum;
    
        for (int i = 0; i < N; ++i)
        {
            while (sum >= coinsValue[i])
            {
                coinsCount[i]++;
                sum -= coinsValue[i];
            }
            std::cout << coinsCount[i] << " (" << coinsValue[i] << 
            (coinsCount[i] == 1 ? ") coin\n" : ") coins\n");
        }
    
    
    }
    Ответ написан
    3 комментария
  • Некорректное вычисление?

    gbg
    @gbg Куратор тега C++
    Любые ответы на любые вопросы
    Для C++ такая конструкция нарушает стандарт языка и приводит к неопределенному поведению. На C++ так писать нельзя.
    Ответ написан
  • Как быстро разобратся в сишном коде?

    @sitev_ru
    sitev.ru - мой блог ...
    Вы пишите
    Так как с C я "на вы"

    Не не намного сложнее, чем тотже php или js.

    Сейчас там 3ляма+ строк

    Зачем переписывать столько? Не проще найти ошибки?

    Люди решили всё переписать и выбор технологий оставили за мной

    Люди решили всё переписать доверили человеку, который с С на вы...

    Последний программист который мог объяснить как оно работает уволился с год назад

    Проблема в менеджменте. Не стали платить человеку за поддержку готового кода, а заплатили похоже в несколько раз больше, чтобы переписать всё с нуля... Неужто так всё плохо? )))

    Если присмотреться, то пхп и си - очень похожие по синтаксису языки. Читаю в википедии: "Синтаксис PHP подобен синтаксису языка Си." А вот что пишут тамже про Javascript "который, по замыслу разработчиков, должен был стать достаточно мощным, чтобы заменить макросы, сохраняя при этом схожесть с Си"

    Моё мнение, лучше изучить Си и просто доделать, исправить ошибки. Возможно двигаться в сторону С++, может быть Qt и т.д..
    Ответ написан
    Комментировать
  • Почему константное значение Qstring?

    @Free_ze
    Пишу комментарии в комментарии, а не в ответы
    Есть такое правило: "const по умолчанию", т.е. const нужно использовать везде, где это возможно. В данном случае QString передается по ссылке и планируется только для чтения, потому его делают константным.

    Кроме того, для копируемых объектов const не нужно, достаточно передавать их по значению (аргумент скопируется и нам будет доступна лишь его копия). Но QString может быть достаточно крупным, а вызовы метода - достаточно частыми, потому передается просто ссылка. Появляется возможность изменить объект через эту ссылку. Чтобы это снова запретить, в методе указывают const для аргумента-ссылки.
    Ответ написан
    Комментировать
  • Как применять перечисляемый тип enum?

    maaGames
    @maaGames
    Погроммирую программы
    В примере D,E,F не инициализирвоаны. В консоль выводится мусор.
    Ответ написан
    4 комментария
  • Как отсортировать двумерный массив на Swift?

    ManWithBear
    @ManWithBear
    Swift Adept, Prague
    Ну начнем с того, что это одномерный массив.
    arr.sort { (first, second) -> Bool in
        return first.type < second.type
    }

    Если вспомнить о особенностях кложур, то можно записать вот так:
    arr.sort { $0.type < $1.type }
    Ответ написан
    1 комментарий
  • Каковы условия труда в современной игровой индустрии?

    terrier
    @terrier
    Пункт номер 0 - не сомневайтесь, С++ - один из основных языков в гейм-индустрии.
    1. Гейм-индустрия сильно разная. Лабать инди-игру на кухне - это одно, фигачить очередную часть AAA-тайтла - это другое, делать веселую ферму с енотиками для вконташи - это третье
    2. Соответственно, если фирма еще не вышла из стадии "Вася и Петя решили сделать новый фэллаут и уже даже наняли одного программиста Толяна", то условия очевидны - Толян фигачит пока не упадет за копейки.
    3. А вот если фирма уже перешла на более индустриальный уровень, то тут обыкновенная IT-разработка, с некоторыми особенностями:
    - В индустрии вполне встречаются энтузиасты и кто-то в компании будет работать с восьми до восьми ( хорошо, если это продюсер ), но это совсем не обязательно должны быть вы.
    - В целом в управлении как правило бардак, для того чтобы рулить одновременно и художниками и программистами и геймдизаннерами нужны очень классные менеджеры, а таких в индустрии нет
    - Уровень технической организации ( CI, vcs, code-review, внятные стандарты кодирования ) колеблется от "стихийного" до весьма высокого, есть суперкрутые специалисты, работать с ними - большая удача, особенно для новичка.
    - Однако если вас интересует конкретно стек технологий с C++ - там крутых спецов вымывают яндекс/мэйл, они способны предложить условия получше
    - Переработки случаются, поскольку планирование как правило весьма "креативное". По идее разработчки должны с этим бороться, насколько успешно - другой вопрос
    - По деньгам - средне, вот тут сильно зависит от заказчика/проекта
    - Есть ли улучшение со временем? Ну, вот недавно тем, кто работает на западного заказчика одномоментно стало резко лучше, гггг))) Но в целом, вы правильно поняли, в плане условий труда индустрия эволюционировала от "Полный треш, подойдет только для долбанутых подростков" к "Можно рассматривать, если есть толерантность к некоторому творческому беспорядку"
    Ответ написан
    1 комментарий
  • Чему будет равно i при таком необычном указателе?

    Это на будущее. Char занимает 1 байт, так что адрес увеличится на 1 в шестнадцатеричном представлении, если к char прибавить 1, а если прибавить 1 к int1, как и к uint32_t(они оба занимают по 4 байта), то адрес увеличится на 4(был 0xAAFFAACB, а станет 0xAAFFAACF), тип double занимает 8 байт, то есть если, например, переменная типа double занимала адрес 0x123AB111, то будет занимать 0x123AB119 при увеличении указателя на 1.
    "К указателям могут применяться только две арифметические операции: сложение и вычитание. Для понимания арифметических действий с указателями предположим, что p1 - это указатель на целое, содержащий значение 2000, и будем считать, что целые имеют длину 2 байта. После выражения

    p1 ++;

    содержимое p1 станет 2002, а не 2001! Каждый раз при увеличении p1 указатель будет указывать на следующее целое. Это справедливо и для уменьшения. Например:

    р1 --;

    приведет к тому, что p1 получит значение 1998, если считать, что раньше было 2000

    Естественно, все не ограничивается только уменьшением или увеличением. Можно добавлять или вычитать из указателей целые числа. Выражение

    p1 = p1 + 9;

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

    Помимо добавления или вычитания указателей и целых чисел, единственную операцию, которую можно выполнять с указателями, - это вычитание одного указателя из другого.
    ."100120ea0ab7436d8bd981033bea675e.png
    Ответ написан
    Комментировать
  • Как перевести побитовую операцию сдвига с C++ на Php?

    @dev400
    <?php
    $x = "abc def" ;
    $array = explode(" ", $x);
    var_dump($array);
    /*
        array(2) {
             [0]=> string(3) "abc"
             [1]=> string(3) "def" 
        }
    */
    Ответ написан
    Комментировать
  • Ссылка на лямбду?

    tsarevfs
    @tsarevfs Куратор тега C++
    C++ developer
    Для лямбд, которые не захватывают переменные в своих [], определен оператор преобразования в указатель на функцию(ClosureType::operator ret(*)(params)()). Собственно поэтому происходит неявный каст в вашем 1 примере. Для ссылки компилятор не находит подходящего преобразования.
    Последний пример сначала преобразует лямбду к указателю и разыменовывает его уже просто как указатель.
    Ответ написан
    Комментировать
  • Сможете объяснить формулу момента контура изображения?

    Разве это не (x,y)-координаты i-ой точки контура ?
    Ответ написан
    Комментировать
  • Как создать палитру цветов для bmp изображения?

    alsopub
    @alsopub
    Вот тут кажется много полезной информации с кодом:
    www.enlight.ru/demo/faq/smth.phtml?query=alg_clr_dith
    Ключевые слова: Кластеризация (Quantization), Dithering.
    Можно, даже, взять усредненную (универсальную) палитру, но результат будет не всегда хорошим.

    Ваша палитра вышла не такой плохой на первый взгляд как вы подумали, однако я вижу что изображение, построенное на ее основе, не использует яркие цвета, вероятно есть ошибка в алгоритме.

    Поиск цвета в палитре нужно вести только не только по яркости. Скорее по сумме квадратов отклонений по каждой цветовой компоненте.

    И еще - у вас не сортировка по яркости, у вас один проход с перестановкой, он не дает полную сортировку.
    Скорее всего из-за этого у вас и получилось такое тусклое итоговое изображение. Но яркость - все равно не то, синий и красный цвета будут одинаково яркими, но совсем разными.
    Ответ написан
    3 комментария
  • Как писать приложения 24/7?

    GavriKos
    @GavriKos
    Обычно это связано с криво написанным приложением.
    Во первых - интерфейс отдельно - мониторинг отдельно. Интерфейс можно закрыть - демон/служба мониторинга останется
    Во вторых - куда пишутся данные? В оперативу? Сколько приложение выжрало? Какие структуры данных использовали? Пробовали писать в БД?
    Ответ написан
    3 комментария
  • Последовательное выполнение условий if в С++?

    Не сортировка

    Сортировка. Только на множестве используется отношение порядка, отличное от принятого для действительных чисел.

    #include <vector>
    #include <algorithm>
    #include <iterator>
    #include <iostream>
    
    template <typename T> int sgn(const T val) {
        return (T(0) < val) - (val < T(0));
    }
    
    int main() {
    
    	std::vector<double> v = {0, 2, -1, -100, -3, 4, 1, -90};
    
    
    	std::cout << "Original: ";
    	std::copy(v.begin(), v.end(), std::ostream_iterator<double>(std::cout, " "));
    	std::cout << std::endl;
    
    	std::stable_sort(v.begin(), v.end(),
    		[](const double &a, const double &b) -> bool {
    			const int sa = sgn(a);
    			const int sb = sgn(b);
    			return sa < sb;
    		});
    
    	std::cout << "Sorted: ";
    	std::copy(v.begin(), v.end(), std::ostream_iterator<double>(std::cout, " "));
    	std::cout << std::endl;
    
    	return 0;
    }


    Original: 0 2 -1 -100 -3 4 1 -90 
    Sorted: -1 -100 -3 -90 0 2 4 1
    Ответ написан
    1 комментарий