Сдвиг в си

Циклический сдвиг в младшей тетрады байта на n позиций вправо.

Ребят, подскажите как написать программу. Может кто сталкивался с таким?

Можно, например, так:

#include <iostream>
#include <iomanip>

using namespace std;

void binp(ostream& os, unsigned int n) {
    if (n != 0) {
        binp(os, n >> 1);
        os << (n & 1);
    }
    else {
        os << "0b0";
    }
}

int main() {

    setlocale(LC_ALL, ".1251");

    int num;
    cout << "Введите целое число: ";
    cin >> num;

    cout << "Получено: 0x" << hex << num << "\t";
    binp(cout, num);
    cout << endl;

    int carry;
    for (int i = 0; i < 4; i++) {
        // циклический сдвиг младшей тетрады вправо -- начало
        carry = num & 1;
        num = ((num & 0xf) >> 1) | (num & ~0xf);
        if (carry) {
            num |= 0x8;
        }
        // циклический сдвиг младшей тетрады вправо -- конец
        cout << i+1 << "  0x" << hex << num << "\t";
        binp(cout, num);
        cout << endl;
    }

    return 0;
}

Переменная carry содержит младший бит, который должен быть перенесён в старшую позицию тетрады.

(num & 0xf) — выделена младшая тетрада
(num & 0xf) >> 1 — младшую тетраду сдвинули на один бит вправо
(num & ~0xf) — сбросить биты младшей тетрады в 0
Осталось сложить получившееся вместе и установить старший бит тетрады, если carry не равна 0.

Хорошее число 3276 ;)

На случай если кому то пригодится
Сдвиг на 1 позицию вправо в старшей тетради

#include<stdio.h>
#include<iostream>

using namespace std;

int amount_bits(int a)
{
    int amount_b = 0;
    a = a >> 1;
    for (int i = 0; i < 8; i++)
    {
        printf("%d\n", a);
        system("pause");
        if ((a & 1) == 1)
            amount_b++;
        a = a >> 2;
    }
    return amount_b;
}

int shift(int a)
{
    return((a & 0x87FF) | ((a & 0x800) << 3) | (((a & 0x7800) >> 1) & 0x7800));
}

void bin_output(int a)
{
    for (int i = 0; i <16; i++)
    {
        if ((a & 0x8000) == 0x8000)
            printf("1");
        else
            printf("0");
        a = a << 1;
    }
}

void f_help()
{
    system("cls");
    printf("Согласно меню, Вы можете произвести следующие действия :\n-Ввести целое число\n");
    printf("-Подсчитать количество единичных значений битов, стоящих на четных позициях\n");
    printf("-Выполнить циклический сдвиг вправо в старшей тетраде кода целого числа\n");
    printf("-Завершить работу программы\n\n");
}

int main()
{
    setlocale(LC_ALL, "rus");
    int a = 0, menu, amount_b,flag=0;
    do
    {
        system("cls");
        puts("Перед началом использования программы ознакомьтесь с инструкцией\n\n");
        puts("\tМеню\n");
        puts("1-Ввод целого положительного числа\n");
        puts("2-Подсчет количества единичных значений битов\n");
        puts("3-Циклический сдвиг\n");
        puts("4-Завершение работы\n");
        puts("Выберите пункт меню...\n");
        scanf_s("%d", &menu);
        switch (menu)
        {
        case 1:
        {
            do
            {
                system("cls");
                puts("Введите целое число:");
                fflush(stdin);
                scanf_s("%d", &a);
                flag = 1;
            } while (a < 0);
            break;
        }
        case 2:
        {
            if (flag == 1)
            {
                system("cls");
                printf("Двоичное представление: ");
                bin_output(a);
                flag = 2;
                amount_b = amount_bits(a);
                printf("\nКоличество единичны значений битов на четных позициях\n %d\n", amount_b);
                system("pause");
            }
            else
            {
                system("cls");
                puts("Сначала выполните пункт 1");
                system("pause");
            }
            break;
        }
        case 3:
        {
            if (flag == 2)
            {
                system("cls");
                printf("Целое число: %d", a);
                printf("\nДвоичное представление: ");
                bin_output(a);
                a = shift(a);
                printf("\n\nЦелое число после сдвига: ");
                printf("%d", a);
                printf("\nДвоичное представление: ");
                bin_output(a);
                printf("\n\n");
                system("pause");
            }
            else
            {
                system("cls");
                puts("Сначала выполните пункт 2");
                system("pause");
            }
            break;
        }
        case 4:
        {
            system("cls");
            printf("Всего хорошего!\n");
            system("pause");
            break;
        }
        case 5:
            f_help();
        default:
        {
            puts("Выбран неверный пункт меню!");
            system("pause");
            break;
        }
        }
    } while (menu != 4);
    return 0;
}

Nikita1881, сам-то своей программой пробовал пользоваться? Удобно? Я — так просто охренел от такого пользовательского интерфейса.

Начинаем сначала: запускаем программу. «Перед началом использования программы ознакомьтесь с инструкцией». «О'кей, Гугл! Инструкция к программе...» Т.е. я хотел узнать, а где, собственно, инструкция? Оказывается на пункте меню 5, которого в меню нет. Кстати, здесь пропущен break, поэтому после инструкции программа еще и выдает что «Выбран неверный пункт меню!»:

       case 5:
            f_help();
            break;              // <-- !!!
        default:
        {
            puts("Выбран неверный пункт меню!");
            system("pause");
            break;
        }

После того, как наконец-то, после анализа кода программы, добрались до «инструкции», выясняется, что «2-Подсчет количества единичных значений битов» в действительности означает «Подсчитать количество единичных значений битов, стоящих на четных позициях». Классное уточнение! По пункту 3 — аналогично.

Ладно, с тем, что программа реально должна делать, разобрались.

В меню вводим 3. Подозреваю, что без ввода числа ничего не выйдет, но меню — есть меню, и оно предоставляет свободу выбора. «Сначала выполните пункт 2». Хм... Оказывается надо сначала подсчитать количество единичных битов в четных позициях. Загадочно... В меню вводим 2. Ну вот оно, таки надо сначала ввести число. Слава Богу, что «4-Завершение работы» работает без выполнения пунктов 3, 2 и 1.

Ты скажи, зачем ты такой пользовательский интерфейс наклепал? Тренировался в наборе текста слепым десятипальцевым методом? Здесь совершенно явно просматривается линейное выполнение программы: ввод числа, подсчет битов, сдвиг, завершение. Или, если уж очень хочется, этот линейный кусок завернуть в цикл do-while с запросом на продолжение. В итоге код программы сокращается в 2 раза.

Теперь по остальному тексту программы.

#include<stdio.h>
#include<iostream>

Если ты используешь вызовы из stdio.h, зачем включать iostream? Видимо ради system() и setlocale(). Один удар микроскопом — и гвоздь забит. Изящно )) Но такой код компилятором С (не ++) не скомпилируется. А программа, похоже, написана на чистом С. Если не полениться, и почитать доки, то проблема решается например так:

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

Подобрались к самому интересному: циклический сдвиг вправо в старшей тетраде целого числа. Что такое целое число? Как выяснилось из текста программы, под целым числом ты подразумеваешь 16-битное целое со знаком. А почему не 8-, 32- или 64-битное? Это либо надо как-то оговаривать, либо писать программу так, что бы она корректно работала со старшей тетрадой числа вне зависимости от архитектуры компьютера, разрядности ОС и настроек компилятора.

Я долго медитировал над твоей функцией shift(). Наконец до меня дошло, что под тетрадой ты понимаешь любую непрерывную последовательность из четырёх бит, а не ниббл (полубайт), как это принято. Поэтому, исходя из твоего предположения о тетраде, функция работает правильно, исходя из общепринятого — нет (это еще учитывая предположение, что int — 16-битный!).

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

Ответить

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

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

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

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

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

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