Разминка для мозгов: перевод числа из dec в bin

Cranium, последний вариант правильный

Еще есть вариант, не использовать статической переменной. Тогда можно записать аргумент как константную ссылку

void dec_to_bin(int const &num)
{
    if (num / 2 >= 1)
        dec_to_bin(num / 2);
    std::cout << num % 2;
}

selevit, во-первых, инициатор не я, а beginner )))
А во-вторых, тема ещё активна. Оптимальное решение ищется ;)

#include <iostream> 
const char *info = "Input whole number. Range 0 to 2,147,483,647";
int good_int()
{
    int num;
    for (;;)
    {
        std::cout << "\ndec = ";
        (std::cin >> num).get();
        if (!std::cin.good())
        {
            std::cin.sync();
            std::cin.clear();
        }
        else if (num >= 0)return num;
        std::cerr << "Error. " << info;
    }
}
void dec_to_bin(int num)
{
    static int k;
    k = num / 2;
    if (k >= 1)
        dec_to_bin(k);
    std::cout << num % 2;
}
void main()
{
    int num;
    std::cout << "For exit input '0'\n" << info;
    for (;;)
    {
        num = good_int();
        if (num == 0)break;
        std::cout << "bin = ";
        dec_to_bin(num);
    }
}

Мой код лучший

void dec_to_bin(int const&num)
{
    if (num / 2 >= 1)
        dec_to_bin(num / 2);
    std::cout << num % 2;
}

Три строчки в функции. Три! И не нужны никакие массивы.

Илья, если в функции void dec_to_bin(int const&num) (1) выражение num / 2 >= 1 упростить до num > 1, избавившись от лишнего деления, и (2) аргумент передавать не по константной ссылке, а по значению, избавившись от лишней косвенной адресации, то получится практически тот вариант рекурсивной функции, который я опубликовал ранее. Наши решения почти совпали.

Второй момент более проблемный и, поскольку задачу ставил не я, адресовать его нужно beginner'у. В условии задачи было ограничение на использование библиотек, и конкретно STL. В твоей программе подзадача «вывести предупреждение и завершить работу, в случае если <вводимое> число превышает кол-во байтов» решается средствами STL. Ибо потоковый ввод-вывод — это фишка чисто из STL.

В других вариантах решения от «различных производителей» (почти во всех) для ввода-вывода тоже используется STL. Но всё-таки делались попытки (разной степени успешности) определить битовый размер вводимого числа. Ты в своём варианте играешь на том, что при вводе числа, превышающего размер переменной-приёмника, функция потокового ввода (из STL) записывает в переменную-приёмник некое магическое значение с установленным старшим битом, которое интерпретируется как отрицательное число, и тут же попадает под нож проверки на отрицательность.

beginner, твоё мнение по данному вопросу?

Слухи о том, что <stdio.h> умер, сильно преувеличены ))
Просто сейчас почему-то не модно знать стандартную си-шную библиотеку ввода-вывода. Впрочем плюсовую потоковую библиотеку хорошо тоже мало кто знает. Парадокс однако ;)

Вот вариант решения, полностью удовлетворяющий всем условиям задачи. Без ГМО, то есть STL. Только <stdio.h>, только хардкор ))

#include <stdio.h>
#include <locale.h>

// псевдоним для целочисленного типа с которым будем работать
//typedef char itype;
//typedef short int itype;
//typedef int itype;
//typedef long int itype;
typedef long long int itype;

enum GNENUM { GN_OK = 0, GN_NEG, GN_ILL, GN_LONG };

GNENUM get_num(itype *num) {
    *num = 0;
    itype prevnum = 0;
    int ch;
    // анализируем первый символ
    ch = getchar();
    if (ch == EOF)
        return GN_ILL;
    if (ch == '-') {
        // анализируем второй символ для правильной диагностики ситуации
        int ch2 = getchar();
        if (ch2 >= '0' && ch2 <= '9')
            return GN_NEG;
        else
            return GN_ILL;
    }
    if (ch != '+')      // игнорируем символ '+'
        ungetc(ch, stdin);  // возвращаем первый символ обратно в буфер ввода

    while ((ch = getchar()) != EOF) {  // конец ввода по ошибке файла
        if (ch == '\n')                // или по символу конца строки
            break;
        if (ch < '0' || ch > '9')   // найден нецифровой символ
            return GN_ILL;
        *num = *num * 10 + (ch - '0');
        if (*num < prevnum)     // проверка на переполнение
            return GN_LONG;
        prevnum = *num;
    }
    return GN_OK;
}

void toBin(itype n) {
    if (n > 1)
        toBin(n / 2);
    putchar(n % 2 + '0');
}


int main() {

    setlocale(LC_ALL, "Russian");

    itype number;

    printf("Введите целое положительное число длиной не более %u бит: ", (unsigned int)sizeof(itype)* 8);
    GNENUM gn_ret = get_num(&number);
    if (gn_ret != GN_OK) {
        switch (gn_ret)
        {
        case GN_NEG:
            printf("Введено отрицательное число.\n");
            break;
        case GN_ILL:
            printf("Неверный формат числа.\n");
            break;
        case GN_LONG:
            printf("Введено слишком большое число.\n");
            break;
        default:
            printf("Хня какая-то творится...\n");
            break;
        }
        return 1;
    }

    // вывод в максимально длинном целочисленном типе
    printf("Введено\n  10-тичное:\t%lld\n  16-ричное:\t%llX\n  двоичное:\t", (long long int)number, (long long int)number);
    // вывод двоичного представления
    toBin(number);
    printf("\n");

    return 0;
}

На счет вывода в двоичной форме я не стал напрягаться и адаптировал решение от Cranium'а.

Работает с целыми типами размером от 1 до 8 байт. Если процессор/компилятор поддерживает, то можно и длиннее (хе-хе! ;) ). Длина типа задается typedef'ом в начале программы: нужно раскомментировать только интересующий typedef.

Просто сейчас почему-то не модно знать стандартную си-шную библиотеку ввода-вывода.

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

Без ГМО, то есть STL.

Если кодишь на плюсах, нужно использовать STL. Это касается как использования контейнера std::string вместо сишных строк, std::vector вместо динамических массивов, new вместо malloc и т. п.

Это в общем-то не только моя позиция но и Самого.

beginner, твоё мнение по данному вопросу?

Ох, Илья, уморил своей версией онлайн разработки

В последней редакции кода (с поправкой на то, что в функции void dec_to_bin(int const&num) все-таки ))) можно обойтись без статических переменных) произошло слияние всяческих штучек (типа безусловного for), рекурсии, проверки goodbit, с последующей синхронизацией потока, в дополнение, с очисткой failbit (но при всей этой грозной защите происходит вылет одного цикла программы при вводе вещественного числа) и апофеоз — это завершение программы вводом нуля и похвалой себя любимого.

Мой код лучший

СУПЕР!!!

А теперь, по существу :|
Илья, вы задание читали?

selevit, я согласен с тобой (и с Самим), что при программировании на плюсах надо использовать STL и не изобретать велосипед. Но...

Что делать, если библиотека не предоставляет достаточных средств для реализации задачи? IMHO Фтьiкай пошёл правильным путём: придумал свой велосипед на гусеничном ходу.

Далее, использование STL запрещено по условиям задания. Как и использование битовых операций. Меня, кстати, больше удивил второй запрет, поскольку битовые операции всегда входили в базовый набор как C++, так и C.

В C++ стандартную си-шную библиотеку ввода-вывода ни кто не отменял и не запрещал. И знать её необходимо. Кстати, многие вещи из STL являются просто надстройкой над стандартной библиотекой: например, тот же потоковый ввод-вывод, или new/delete.

Кстати, многие вещи из STL являются просто надстройкой над стандартной библиотекой:

Правильнее сказать абстракцией. И это удобно, да. Так-то си — это тоже кроссплатформенная надстройка над машинными командами :)

P.S. Согласен с тобой в том, что нужно знать, как работают более низкоуровневые вещи.
Но воспринимать STL, как какую-то «дополнительную библиотеку» языка не стоит.

Без STL конечно можно кодить на плюсах, как на «C с классами», но это уже для каких-то узких задач.

Вот моя программа, думаю все условие выполнил.

#include <iostream>

using namespace std;

int main()
{   

    __int64 iDec = 0;   char bin[31];
    int i = 0; long long lDec = 0; 
    setlocale(0,"");
    cout << "Введите положительное десятичное число(max - "<< LONG_MAX <<" ): ";
    cin >> iDec;

    if (abs(iDec > LONG_MAX)) {cout <<"Превышен лимит значения."; return 0;};
    if (iDec < 0) {cout << "Введено отрицательное число."; return 0;}


    lDec = iDec;

    while (lDec > 0)
    {
        if (lDec % 2 == 0) bin[i] ='0'; else
            bin[i] = '1';
        lDec /= 2;
        i++;
    }

    cout << iDec << " -> ";
    for (i; i > 0; i--)
    {
        cout << bin[i-1];
    }

    return 0;
}

Snoomru, твоя программа ещё одна вариация на тему, о которой я писал ранее (см. 2-3 абзац). Топикстартер подтвердил, что такое решение не удовлетворяет условию задания.

Пока единственное решение, полностью удовлетворяющее условию задания, представил Фтьiкай.

Пока единственное решение, полностью удовлетворяющее условию задания,
представил Фтьiкай.

Да, мне тоже решение от Фтьiкай очень понравилось. Настоящий HARD CODE.

Ой да, я слоупок :D

Единственное, что это C, а не C++. И описание с точки зрения конечного решения должно быть более лаконичным.

Я оставил второй вариант, а с твоего сделал перенаправление, чтобы существующие ссылки не ломались.

Я очень давно не писал на чистом C, но мне кажется, что enum там нет. По крайней мере, компиляция на ideone.com и http://www.codechef.com в режиме C даёт ошибку на функцию GNENUM get_num(itype *num). Интересно, что строка enum GNENUM { GN_OK = 0, GN_NEG, GN_ILL, GN_LONG }; не вызывает неприязни у компилятора.

Так что это код, видимо, всё-таки на C++.

PS. Искать последний стандарт C лень ((

Внимание! Это довольно старый топик, посты в него не попадут в новые, и их никто не увидит. Пишите пост, если хотите просто дополнить топик, а чтобы задать новый вопрос — начните новый.

Ответить

Вы можете использовать разметку markdown для оформления комментариев и постов. Используйте функцию предпросмотра для проверки корректности разметки.

Пожалуйста, оформляйте исходный код в соответствии с правилами разметки. Для того, чтобы вставить код в комментарий, скопируйте его в текстовое поле ниже, после чего выделите то, что скопировали и нажмите кнопку «код» в панели инструментов. Иначе ваш код может принять нечитаемый вид.

Либо производите оформление кода вручную, следующим образом:

``` #include <iostream> using namespace std; int main() { // ... } ```

Предпросмотр сообщения

Ваше сообщение пусто.