Ответы пользователя по тегу Программирование
  • Ошибка времени выполнения: Значение было недопустимо малым или недопустимо большим для Int32, как это решить?

    @Mercury13
    Программист на «си с крестами» и не только
    1. У вас неправильная формула корней.
    2. Хотелось бы узнать, чему равны a, b, c.
    3. Зачем вы округляете?
    4. Собственно причина ошибки. Думаю, у вас отрицательное d, sqrt(d) = NaN (не-число), и ваша реализация Паскаля вот так поступает, когда нужно округлить NaN.
    Ответ написан
    Комментировать
  • Как через printf в Си вывести уникальный символ вроде знака цента или знака параграфа?

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

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

    @Mercury13
    Программист на «си с крестами» и не только
    Object* find (const Object& o)
    {
        /* Поиск, если нашли */
       return link;
       /* Если не нашли? */
       return NULL; // Теперь можно
    }
    Ответ написан
    5 комментариев
  • Как в Си выяснить, является ли введённая 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 (видимо, для совместимости с перегрузкой функций).
    Ответ написан
    Комментировать
  • Неправильная работа кода, почему всегда срабатывает "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 комментариев
  • Как исправить цикл "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. Обратная польская запись не имеет скобок, но, тем не менее, чётко указывает, к каким выражениям относится та или иная операция. Насобачившись, человек будет с лёгкостью переводить запись из алгебраической в обратную польскую и даже притрагиваться не будет к современным «умным» калькуляторам, которые со скобками и учитывают приоритет умножения над сложением.
    Ответ написан
    Комментировать
  • В чем суть self-bounded types?

    @Mercury13
    Программист на «си с крестами» и не только
    Не в этом дело. Тут задача — уже при компиляции сказать, что программа некорректна и нельзя сравнивать, например, enum TrLight { RED, YELLOW, GREEN } и enum Pet { CAT, DOG, HEN }.

    Для Java-машины TrLight и Pet — один и тот же класс, проверка шаблонных классов идёт при компиляции!
    Ответ написан
    Комментировать
  • Как в c++ уменьшить память, зарезервированную под вектор?

    @Mercury13
    Программист на «си с крестами» и не только
    c++11 — shrink_to_fit.
    Ответ написан
    Комментировать
  • Можно ли подготовиться к Яндекс ШАД дза год?

    @Mercury13
    Программист на «си с крестами» и не только
    Да более чем! Главная проблема — интегралы. Один средней сложности точно будет.
    Ответ написан
  • Как живётся программисту без дискретной видеокарты?

    @Mercury13
    Программист на «си с крестами» и не только
    Если не пишешь требовательные игры, никаких проблем. Хороший Core i7, один монитор FullHD.
    Только матплату надо накопать такую, чтобы два монитора всё-таки подключились (у меня VGA+DVI, этого явно не хватает).
    Ответ написан
    Комментировать
  • А допустимо ли делать пхп страницу на инклюдах?

    @Mercury13
    Программист на «си с крестами» и не только
    Лучше вместо include использовать require.
    Хорошее дело, если нужно быстро придумать недо-CMS.
    Ответ написан
    Комментировать
  • Как создать калькулятор (аналоги строительных)?

    @Mercury13
    Программист на «си с крестами» и не только
    Самый лучший инструмент для прототипов — Excel. Или любая другая понравившаяся таблица, например, LibreCalc.
    Для Android — Android Development Studio, понятное дело.
    Настольную программу можно написать даже на JavaScript. Если же нужен EXE — что угодно, на чём умеешь программировать. Я бы взял визуальную систему наподобие Delphi, Qt или WinForms.
    Ответ написан
    Комментировать
  • Как реализовать обратную совместимость пользовательских данных в программе?

    @Mercury13
    Программист на «си с крестами» и не только
    Проще всего это сделать в XML. Тогда мы легко можем добавлять новые теги и игнорировать то, что в XML не входит.

    Двоичный файл надо делать на манер XML — в виде иерархической конструкции из коротеньких потоков. Самое сложное — чтобы по этому двоичному файлу не надо было бегать туда-сюда, как по гоночному треку. Для этого на каждом из уровней иерархии бывает одно из двух.
    1. Запросить некую последовательность кодов, а затем спрашивать: есть этот код? А есть этот? Что-то типа (для простоты пишу как на C++)…
    BlockReader blk;
    int order1[] = { opHeader, opSettings, dirData };
    BlockOrder order(blk, order1);
    
    order.require(opHeader);
    // считать заголовок
    author = blk.readString();
    
    if (order.get(opSettings) {
      // считать настройки
    }
    
    order.require(dirData);
    blk.enterDir();
      // считать данные таким же образом — там может быть свой BlockOrder
    blk.leaveDir();


    Да, для чего мы запрашиваем порядок блоков дважды?
    Первый раз — вот для чего. Представим себе устаревший файл, в котором нет блока настроек. Мы считываем заголовок, видим вместо блока настроек каталог с данными, и сразу вопрос: тут что-то пропущено или что-то лишнее?
    Второй раз — для наглядности (код комментирует сам себя) и защиты от ошибок, когда заявленный в начале порядок не совпадает с реальным.

    2. Просто считываем блоки по одному и интерпретируем. Обычно это бывает во всяких коллекциях.
    while (blk.getBlock()) {
      switch (blk.opcode) {
      case dirTiledLevel:
         // считать плиточный уровень
      case dirGraphicLevel:
         // считать уровень с фоном — цельной картинкой
      }
    }

    Запрещается смешивать упорядоченное с коллекциями.

    Можно также в заголовке каждого блока сделать бит: Essential. Старая версия, наткнувшись на такой блок и не считав ни байта (или наткнувшись на каталог и не войдя), выводит ошибку: версия явно новее, считать невозможно. Это бывает важно, когда в файле есть перекрёстные ссылки.

    Для записи подобных файлов приходится накапливать блок в памяти, а затем сваливать его в один присест (ведь надо записать длину блока). Впрочем, есть и версия для структур, которые заранее знают свою длину — тогда накапливать в памяти излишне.

    Далее. В заголовке можно сохранить поля «SavedWithVersion», «MinRequiredVersion», «MinFullySupportingVersion».
    Добавляем новый блок (или новое поле в имеющийся блок) — поднимаем MinFullySupportingVersion до текущей. Изменяем структуру так, что ломаем совместимость — поднимаем MinRequiredVersion.

    То, что версия слегка устарела, можно ловить и по косвенным признакам — какой-то блок считан не полностью, в какой-то каталог не вошли. У блока/каталога может быть флаг Compatibility — их проверять не надо. И наоборот — если важный блок отмечен как Compatibility, тоже версия устарела. Ясное дело, флаги Essential и Compatibility не могут попадаться вместе.

    Как это делать, если формат сохранения — база данных (например, SQLite), я не в курсе.

    А вот сохранение в устаревший формат, когда структуры данных ушли далеко вперёд, придётся налаживать руками. Можно ли в принципе, как преобразовать в старый формат, и т.д.
    Ответ написан
    Комментировать
  • Почему программисты не любят возврат константных ссылок в C++?

    @Mercury13
    Программист на «си с крестами» и не только
    Я думаю, причина единственная — не надо смотреть на время жизни объекта.
    Если же нужно сэкономить, в возвращаемый результат встраивают умный указатель. Так работают, например, QString и QDatabase.

    А вот в каких-нибудь низкоуровневых векторах — вполне себе константные ссылки.
    const T &QVector::at(int i) const
    Ответ написан
    Комментировать
  • Почему в Python при целочисленном делении (-1 // 2) получается ответ (-1)?

    @Mercury13
    Программист на «си с крестами» и не только
    Соответствующий кусок статьи Википедии «Деление с остатком» во многом мой, расскажу вкратце.

    Когда делитель отрицательный, в моей практике такого не бывало. А когда отрицательное делимое, есть два подхода. Но прежде выясним, что такое неполное частное и что такое остаток.
    q = [a / b], r = a − bq.
    Когда b>0, есть два подхода к округлению.
    1. Неполное частное округляется к нулю, остаток отрицательный.
    2. Неполное частное округляется к −∞, остаток положительный.
    Оба имеют право на жизнь: первый — когда преобразуем сумму в копейках в рубли-копейки, второй — когда огрубляем координаты, чтобы указать, в какой клетке находится точка.
    Можно эти правила расширить и на отрицательный делитель: a mod (−b) = −a mod b. В такой ситуации знак остатка равняется знаку делимого и делителя соответственно.
    В x86 (а значит, в большинстве ЯП) принят первый подход. А в Питоне — второй.
    Ответ написан
    Комментировать
  • Почему в битовых сдвигах остаётся минус?

    @Mercury13
    Программист на «си с крестами» и не только
    1. Двоичное представление −7 будет немного другое: 256−7 = 249 = 1111.1001
    2. В знаковом типе используется т.н. арифметический сдвиг вправо: на освободившееся место приходит не 0, а копия верхнего бита (простой и арифметический сдвиг влево идентичны). Возьми вместо −7 что-нибудь начинающееся на 10 в двоичной системе — например, 0x8000.FFFF — и объясни, что выходит.
    Ответ написан
    Комментировать
  • Что такое асинхронное копирование файлов?

    @Mercury13
    Программист на «си с крестами» и не только
    В WinAPI асинхронное копирование файлов — это использование так называемого «асинхронного ввода-вывода» (Overlapped I/O), механизма, который не поднимает новых потоков (по крайней мере явно), но позволяет параллельно с вводом-выводом делать что-то другое. В данном случае — читать и записывать одновременно.

    Что это даёт?
    1. Уменьшает простои программы и этим ускоряет копирование.
    2. Если копирование в пределах одного механического AHCI-диска (из каталога в каталог, с раздела на раздел)— это позволяет оптимизировать маршруты головки на уровне драйвера или контроллера.
    3. Если копирование между разными накопителями — накопители будут действовать параллельно.
    Ответ написан
    Комментировать
  • Как представляется отрицательное число в дополнительном коде?

    @Mercury13
    Программист на «си с крестами» и не только
    Во-первых, вы ошиблись. В беззнаковом типе 1111.1111 = 255 (а не 256!), в знаковом типе 1111.1111 = −1 (а не −127).
    1000.0000 — соответственно −128 и 128.
    256 не передашь одним байтом — ни в знаковом типе, ни в беззнаковом.

    Ну и ответ на ваш главный вопрос.
    > Как ЭВМ понимает, какое число положительное, а какое отрицательное?
    Если заведомо известно, что в ячейке знаковое число — как сказано выше, по верхнему биту (1 — минус, 0 — ноль или плюс). А различить знаковое и беззнаковое число — работа, вообще-то, не машины, а программиста и компилятора, и если просто дана ячейка неизвестного типа — никак не узнаешь, signed там, unsigned, дробное, указатель или символ.
    • Сложение и вычитание работает одинаково для знаковых и беззнаковых чисел.
    • Проверка переполнений и сравнение. Используются три флага: флаг равенства (zf, zero), флаг знакового переполнения (of, overflow) и флаг беззнакового переполнения (cf, carry). Каждая из арифметических функций заполняет и знаковые, и беззнаковые флаги, и есть отдельные функции ветвления для беззнаковых чисел (above/below — например, ja, jbe = jna…) и для знаковых (greater/less — jg, jle = jng). Jump if above, jump if below or equal, и т.д.
    • Умножение и деление — также разные функции, беззнаковая mul/div и знаковая imul/idiv.

    Кстати, по этой причине компилятор ругается, если нужно сравнивать signed и unsigned. Единственный способ надёжно сделать это, например, для 4-байтовых чисел — расширить до 8-байтового signed, чтобы уместился и тот, и другой.
    Ответ написан
    3 комментария
  • Как программно скачать несколько файлов с сайта?

    @Mercury13
    Программист на «си с крестами» и не только
    1. Заполучить принцип, по которому строятся ссылки. Возможно, для этого придётся разбирать код самого сайта.
    2. Использовать любую библиотеку HTTP: Indy (Delphi), cURL (DLL с большим количеством привязок) или что-нибудь другое. С другими я, к сожалению, не работал. Ну или просто запускать подходящий EXE-загрузчик (wget, curl…).
    3. Обойти анти-DDoS’овские меры. Многие сети раздачи контента проверяют, похож ли клиент на легитимный браузер — наш бот должен все эти меры обойти.

    Знаю, что слабость последних версий Indy — ориентация на .NET и вытекающие оттуда ограничения; также Indy «слишком вумный» и сложные REST-службы не работают, так как строишь тело, вычисляешь имитовставку — а служба говорит, что они друг другу не соответствуют; видимо, Indy что-то подстроил. Кстати, когда я понял, что запросы без тела работают, а с телом — ни в какую, первым тестом стал curl.exe, и только потом подключил libcurl через собственную Delphi-привязку.

    Слабость cURL — тонкости протоколов (скажем, заголовки и кодировки) остаются за прикладными программистом; ориентирован на FILE* и на всех языках, кроме Си, запись в файл слегка затруднена; ориентирован на vararg и если работать без типобезопасной обёртки, надо быть предельно осторожным.
    Ответ написан
    Комментировать