• Как вывести цифры находящиеся в тексте в файле?

    @Mercury13
    Программист на «си с крестами» и не только
    Вводить по символу, проверяя функцией isdigit, цифра это или нет.
    Ответ написан
    Комментировать
  • Как через printf в Си вывести уникальный символ вроде знака цента или знака параграфа?

    @Mercury13
    Программист на «си с крестами» и не только
    Во-первых, надо убедиться, что консоль, с которой вы работаете, поддерживает такие символы. Вот у нас вопрос на этот счёт (конкретно о Windows; насколько мне известно, в юниксах простой UTF-8).
    Как вывести знак Σ(сигма) в C++(консольное приложение)?
    Чтобы вывести этот символ, надо…
    • либо использовать «широкие» версии функции (wprintf, wcout и т.д.).
    • либо вывести этот символ в кодировке UTF-8.

    Исходный текст…
    • либо держать в UTF-8 и в нём символ открытым текстом;
    • либо задать в нём символ кодировкой UTF-16 для «широких» функций, кодировкой UTF-8 для «узких».
    Ответ написан
    Комментировать
  • Как создать обьект с std::initializer_list?

    @Mercury13
    Программист на «си с крестами» и не только
    Это нельзя, initializer_list — это тонкая прослойка, позволяющая инициализировать вектор из линейного массива. Ни на что большее она не нужна.

    У вас есть какая-то странность — SearchVektor<unsigned int> мы инициализируем из вектора vector<int>. Это вообще ни в какие ворота не пишется. Для данного случая вам нужно…

    1. vector<int> liste превратить в vector<unsigned int>.
    2. Написать конструктор, работающий из временного вектора: SearchVektor(std::vector<T> && t ). Такой конструктор будет очень быстрым, ибо дерёт всю информацию из t, оставляя в нём пустоту.
    3. Объявить liste временным —
    return  SearchVektor< unsigned  int> (std::move(liste));
    Ответ написан
    4 комментария
  • Переопределить operator() для получения доступа к члену класса?

    @Mercury13
    Программист на «си с крестами» и не только
    class Window{
    public:
      Graphics& operator * () const { return *g; }
      Graphics* operator -> () const { return g; }
    private:
      Graphics *g;
    }
    
    ...
    
    window->Clear(Color::White);
    Ответ написан
    2 комментария
  • Как написать функцию которая может не вернуть значение?

    @Mercury13
    Программист на «си с крестами» и не только
    Object* find (const Object& o)
    {
        /* Поиск, если нашли */
       return link;
       /* Если не нашли? */
       return NULL; // Теперь можно
    }
    Ответ написан
    5 комментариев
  • Как использовать "гибкость" двумерного массива, перед одномерным?

    @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 комментариев
  • Правильно ли я понимаю идею скролинга игрового мира?

    @Mercury13
    Программист на «си с крестами» и не только
    1. Проще изменять координаты объекту Camera или Viewport. И уже на ходу, при рендеринге, вычислять someObject.x - viewport.x.
    Ведь отображение объектов — малая часть игровой логики: объектам надо жить своей жизнью, взаимодействовать друг с другом и героем, заранее отсекаться, если они далеко от камеры.
    А если — вдруг — будут несколько окошек, например, для игры вдвоём, можно сделать несколько viewport’ов.

    2. Это лишь простейший алгоритм скроллинга (т.н. «привязанная камера»):
    viewport.x = clamp(player.x - viewport.width / 2, 0, world.width - viewport.width);

    clamp(x, y, z) = max(min(x, z), y); при y>z можно (но не обязательно) наладить своё хитрое поведение, взяв, например, (y+z) / 2.
    Если игра динамичная, а окно обзора невелико, можно усложнить поведение камеры.
    У меня есть на этот счёт прекрасный перевод.
    https://habrahabr.ru/post/272933/
    https://habrahabr.ru/post/273397/

    P.S. Платформеры писал профессионально, правда, не на холсте HTML 5, а на Java ME.
    Ответ написан
    2 комментария
  • Как поймать в GDB исключение, вызванное из basic_string(const charT*)?

    @Mercury13 Автор вопроса
    Программист на «си с крестами» и не только
    Нашёл.
    Подключить статический libc++ (-static-libstdc++), тогда всё будет.
    Ответ написан
    Комментировать
  • Как найти маркер конца текста?

    @Mercury13 Автор вопроса
    Программист на «си с крестами» и не только
    Придумал. Пусть Σ' — это наш алфавит, из которого можно делать маркеры.
    1. Определяем макс. длину маркера — mlen = ceil( log{|Σ'|}(length + 1) ).
    2. Заводим битовую маску длины |Σ'| + |Σ'|² + … + |Σ'|^{mlen−1} + length + 1.
    Каждый возможный маркер обозначим числом:
    A = 0, B = 1, …, Z = 25, AA = 26, AZ = 51, BA = 52…
    3. Очередь пуста.
    4. Если очередной символ из Σ' — смотрим, сколько символов сзади из Σ', и ставим единицы в соотв. позициях маски.
    5. Находим в маске ноль — это и есть нужный нам маркер.
    Ответ написан
    Комментировать
  • Почему this NULL в istream_iterator?

    @Mercury13
    Программист на «си с крестами» и не только
    Операторы перегружены правильно.

    А вот и нет. Ваша ошибка
    std::istream& operator>>(std::istream& s, Pnt& p)   // убрать const!

    Не обязательно, но можно.
    explicit Pnt(int s) {…} // добавить explicit!
    Что получается? Мы пытаемся считать в неизменную p.a. Прямое s >> p.a; не подходит — поле-то неизменное. И тут, как ни странно, находится цепочка: создать временный Pnt и снова вызвать саму себя!

    Добавить explicit: запрещаем вызывать этот конструктор неявно.
    Убрать const: расфиксировать p.a.

    Также у вас ошибка в перегрузке операции «присвоить».
    Pnt& operator=(const int a) {
           this->a = a;
           return *this; // ну забыл!
         }


    Насчёт explicit. Конструкторы с одним параметром вообще стоит делать explicit всегда, когда объект семантически отличен от параметра. Например, VeryLongInt(10) или Complex(10) — это та же десятка, и explicit можно опустить. А Vector(10) — динамический массив из 10 элементов ≠ десятке, тут explicit нужен.
    Ответ написан
    1 комментарий
  • Динамическая структура данных. Что это?

    @Mercury13
    Программист на «си с крестами» и не только
    Инструментом для этого, опять-таки, послужит операция new.

    Это и есть критерий ДСД. Всё, где используется динамическая память,— динамическая структура данных.

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

    Почему только?
    По организации: одиночный объект, массив, разные виды деревьев, связанный список и комбинации всего этого…
    По семантике: одиночный объект, индексный массив, ассоциативный массив, список, стек, очередь, pimpl (указатель на реализацию), динамическая строка…
    Например, ассоциативный массив (семантика) можно реализовать как дерево поиска (двоичное дерево), а можно как хэш-таблицу (расширяемый динамический массив + куча связанных списков).
    Очередь (семантика) может быть кольцевым списком (динамический массив, возможно, расширяемый), может — расширяемым массивом из динамических массивов (так работает std::deque из C++), может — связанным списком.
    Стандартный подход к строке — динамический массив. Но что делать, если мы, например, клеим и клеим к строке что-то в конец? Или пишем текстовый редактор, где можно вписывать текст в середину? Тоже хитрые структуры.
    Задача Яндекса — проверить испытуемого за несколько минут. Сложную задачу вряд ли за это время разгрызёшь. Потому и любят простые структуры данных.
    Ответ написан
    Комментировать
  • Как в Си выяснить, является ли введённая 1) строка 2) символ в верхнем или же нижнем регистре?

    @Mercury13
    Программист на «си с крестами» и не только
    > как с помощью массива сделать ввод данных, то есть не char а полноценный string, чтобы вводилась сразу строка а не символ
    char s[100];
    scanf("%99s", s);


    Ну и заодно как обработать эту строку.
    len = strlen(s);
    for (i = 0; i < len; ++i) {
      name = s[i];
      // обработай как-нибудь наш name…
    }


    Далее буду пинать ваш код.
    > scanf("%s",name);
    Противная фишка Си как учебного языка. Чтобы сделать простейшие вещи, надо знать сложные концепции. Все параметры scanf, соответствующие подстановкам — %d, %s и т.д. — указатели. И тип этого указателя соответствует типу в форматной строке.
    Из-за этого ваш код — явное AV (Access Violation); чтобы ввести один символ, надо scanf("%c", &name);. Чтобы ввести кучу символов — я написал выше.
    Почему для s не нужен знак адреса? А потому, что массив — изначально указатель.

    Вторая и третья противные фишки — принципиальная небезопасность многих функций и сложности с организацией простейшего консольного диалога. Допустим, Си из коробки не позволяет расширять строку по мере ввода, и важно ограничивать длину ввода, иначе введёшь 100 символов — будет в лучшем случае AV. А если мы введём больше 99 символов — считаем 99 и остановимся, и дальнейшие scanf’ы начнут читать «хвост».

    > for (i=1;i<=strlen(name);i++) {
    Явное O(n²) по процессорному времени на пустом месте. strlen ищет заканчивающий '\0', т.е. его сложность O(n). Надо запомнить длину в отдельную переменную.
    Возможен и второй способ — через указатели.
    char* p;
    for (p = s; *p != '\0' ++p) {

    Это более эффективный, но и более продвинутый способ.

    > if (name >= 97 && name <= 122)
    А почему бы не написать так: if (name >= 'a' && name <= 'z')? Константы 'a' и 'z' — в Си это тот же int, в C++ char (видимо, для совместимости с перегрузкой функций).
    Ответ написан
    Комментировать
  • Как в текстовый файл записать имя этого же файла?

    @Mercury13
    Программист на «си с крестами» и не только
    Единственный способ что-то подобное сделать с текстовым файлом — записать во временный файл, затем заменить этим временным старый. Так что будет что-то типа (пишу на псевдо-C++)
    открыть исходный и временный файлы
    if (std::getline(исходный, s)) {
      подкорректировать s
      временный << s << std::endl;
      while (std::getline(исходный, s) {
         временный << s << std::endl;
      }
      закрыть оба файла
      уничтожить исходный
      переименовать временный
    }

    Главная проблема — юникодные имена файлов, которых у вас, надеюсь, нет.
    Ну и, разумеется, не забудьте про метку порядка байтов, если она в файлах есть.
    Ответ написан
    Комментировать
  • Что значит эта ошибка при открытии svg-спрайта иконок в браузере?

    @Mercury13
    Программист на «си с крестами» и не только
    Это означает: в XML есть нестандартное (внутреннее редакторское) пространство имён «sketch:xxx», для которого не определён URL (xmlns:sketch="http://example.com/sketch" или что-то типа того).
    Если вы пользуетесь редактором, который работает с этими полями — SVG запорчен. Если это результат какой-нибудь «компиляции» или «экспорта» — удаляйте эти поля, браузеру они ни к чему!
    Ответ написан
    Комментировать
  • Почему в потоке cout элементы выводятся в другом порядке?

    @Mercury13
    Программист на «си с крестами» и не только
    Дело в том, что между точками следования (это точка с запятой, вызов функции и экономные операции &&, || и ?:) компилятор имеет право переставлять операции как хочет. Вот он и решил вычислять c++ с конца.

    В C++11 нет точек следования, есть «вычисляется прежде», но языка это кардинально не меняет.

    В C++17 это обещают поправить.
    19) In a shift operator expression E1<<E2 and E1>>E2, every value computation and side-effect of E1 is sequenced before every value computation and side effect of E2

    en.cppreference.com/w/cpp/language/eval_order

    ЗЫ. MinGW даже предупреждение выводит, что результат такой строчки явно не определён. И на классе Co тоже (см. флейм с Толстым Лорри).
    Ответ написан
  • Неправильная работа кода, почему всегда срабатывает "else"?

    @Mercury13
    Программист на «си с крестами» и не только
    Return Value
    On success, a non-negative value is returned.
    On error, the function returns EOF and sets the error indicator (ferror).

    Так что норма.

    Надо писать
    if (name_bytes >= 0 && bday_bytes >= 0) {
    Ответ написан
    5 комментариев
  • Как объединить три одномерных массива в один?

    @Mercury13
    Программист на «си с крестами» и не только
    Я бы свалил их один за другим в один массив или вектор
    www.cplusplus.com/reference/algorithm/copy

    а затем дважды вызвал бы функцию
    www.cplusplus.com/reference/algorithm/inplace_merge

    Если массивы длины 10, 15 и 20, то…
    • Первый раз — std::inplace_merge(v.begin(), v.begin() + 10, v.begin() + 10 + 15);
    • Второй раз — std::inplace_merge(v.begin(), v.begin() + 10 + 15, v.begin() + 10 + 15 + 20);
    Ответ написан
    Комментировать
  • Не проходит компиляцию с любым текстом в TrayIcon->Hint();?

    @Mercury13
    Программист на «си с крестами» и не только
    Здесь используется расширение C++, т.н. свойства. Внешне они выглядят как поля, но при чтении-записи вызывают функции.
    Form1->TrayIcon->Hint = L"Bad";

    И ещё — название Form1 не рекомендуется, назови её как-нибудь fmMain.
    Ответ написан
    Комментировать
  • Как исправить цикл "while", чтобы выводилось одно значение игнорируя перенос строки?

    @Mercury13
    Программист на «си с крестами» и не только
    Подкорректируй строчку так…
    printf("\nYou choose incorrect type, %c please repeat...\nEnter r type :", i);

    и посмотри, что там будет на месте %c…
    Сможешь сам объяснить эффект?

    А как считать символ при интерактивной работе? Я бы написал свою функцию, которая считывает символ и всё, что забуферизировалось за ним аж до перевода строки.
    Ответ написан
  • Зачем нужна Обратная Польская Запись?

    @Mercury13
    Программист на «си с крестами» и не только
    1. Обратная польская запись легко вычисляется стековым автоматом. Этот автомат работает крайне просто:
    • видишь операнд — положи на стек.
    • видишь операцию — забери со стека столько элементов, сколько в операции мест, проведи операцию и положи результат обратно на стек.
    • В некоторых автоматах (например, в тех же калькуляторах) есть вспомогательная операция «ввод» (↑), отделяющая один операнд от другого: 2+2 = 2 ↑ 2 +
    На этом принципе работает большинство виртуальных машин — и сопроцессор x87 (если не ошибаюсь, там 8-местный стек).

    2. Обратная польская запись намного компактнее, чем дерево операций.

    3. Обратная польская запись не имеет скобок, но, тем не менее, чётко указывает, к каким выражениям относится та или иная операция. Насобачившись, человек будет с лёгкостью переводить запись из алгебраической в обратную польскую и даже притрагиваться не будет к современным «умным» калькуляторам, которые со скобками и учитывают приоритет умножения над сложением.
    Ответ написан
    Комментировать