Десятичное в восьмеричное в С - PullRequest
5 голосов
/ 19 марта 2011

Я только начал учить себя Си из программирования Си К.Н Кинга: Современный подход (2ndEdn).

Мне это нравится, но я надеюсь выложить странный вопрос для совета, если это уместно, потому что, к сожалению, у меня нет наставника, и некоторые вопросы поднимают больше вопросов, чем они отвечают!

Я задаю вопрос о введении целого числа и отображении его в восьмеричном виде. Там написано, что есть простой способ сделать это, но об этом позже. Я придумал следующее:

// Convert a number to octal

int n, n2, n3, n4, n5, n6;

printf("Enter a number between 0 and 32767: ");

scanf("%d", &n);

n6 = n % 8;
n5 = (n / 8) % 8;
n4 = ((n / 8) / 8) % 8;
n3 = (((n / 8) / 8) / 8) % 8;
n2 = ((((n / 8) / 8) / 8) / 8) % 8;

printf("%d%d%d%d%d", n2, n3, n4, n5, n6);

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

Если у кого-то еще есть книга, это Q4 с.71.

Спасибо за ваше время. Andrew

P.S. Я заглянул в поисковик, но не смог найти ничего, что делало бы это «медленнее»!

Ответы [ 9 ]

5 голосов
/ 19 марта 2011

Все правы, говоря, что есть встроенный способ сделать это с printf.Но как насчет того, чтобы сделать это самостоятельно?

Первое, что пришло в голову, это то, что одна восьмеричная цифра - это ровно три бита.Поэтому вы можете выполнить преобразование следующим образом:

  • Цикл while n != 0
  • Выделите 3 самых левых бита n в d и напечатайте d
  • Shift n 3 бита влево

Код тривиален, но я не предоставляю его, поэтому вы можете сделать это самостоятельно (вам нужно будет ознакомиться с побитовые и смещения операторы для того, чтобы это сделать).

4 голосов
/ 19 марта 2011

Самый простой способ - использовать спецификатор формата printf() * %o :

scanf("%d", &n);
printf("%o", n);
3 голосов
/ 19 марта 2011

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

void print_oct(int n)
{
    if (n != 0) {
        print_oct(n / 8);
        printf("%d", n % 8);
    }
}

Это работает для n> 0.

1 голос
/ 19 января 2013
/* Converts a positive base_10 into base_b */
int DecimalToBase(int n, int b)
{
    int rslt=0, digitPos=1;
    while (n)
    {
        rslt += (n%b)*digitPos;
        n /= b;
        digitPos *= 10;
    }
    return rslt;
}
1 голос
/ 19 марта 2011

С помощью циклов вы можете свернуть свои пять очень похожих строк следующим образом:

for (int d = 8 * 8 * 8 * 8; d > 0; d /= 8)
    printf("%d", n / d % 8);
printf("\n");

d начнется с 8 * 8 * 8 * 8, который является делителем, который вы используете для n2, а затем пройдете через 8 * 8 * 8, 8 * 8, 8 и, наконец, 1, который является делителем для n6, печатая каждую цифру по пути.

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

Компилятор также позаботится о замене делений на 8 со сдвигами на 3 бита. Оба дают одинаковый результат в двоичном формате, но последний работает быстрее.

0 голосов
/ 27 августа 2015

Преобразование десятичного числа в восьмеричное в C Язык

#include<stdio.h>
#include<conio.h>
void main()
{
    A:
    long int n,n1,m=1,rem,ans=0;
    clrscr();
    printf("\nEnter Your Decimal No :: ");
    scanf("%ld",&n);

    n1=n;
    while(n>0)
    {
        rem=n%8;
        ans=(rem*m)+ans;
        n=n/8;
        m=m*10;
    }

    printf("\nYour Decimal No is :: %ld",n1);
    printf("\nConvert into Octal No is :: %ld",ans);

    printf("\n\nPress 0 to Continue...");
    if(getch()=='0')
        goto A;
    printf("\n\n\n\tThank You");
    getch();
}
0 голосов
/ 21 ноября 2014

Существующие ответы не достаточно чисты, на мой взгляд. Вот мой:

#include <stdio.h>

#define OCTALBASE    8
#define OCTALSIZE    8

int main(int argc, char **argv) {
  int indecimal = 1337;
  char output[OCTALSIZE + 1];
  output[OCTALSIZE] = '\0';

  int outindex = OCTALSIZE;
  int outdigit = 0;
  int outvalue = indecimal;
  while (--outindex >= 0) {
    outdigit = outvalue % OCTALBASE;
    if (outvalue > 0 || outdigit > 0)
      { output[outindex] = '0' + outdigit; }
    else { output[outindex] = ' '; }
    outvalue /= OCTALBASE;
  }

  fprintf(stdout, "{ DEC: %8d, OCT: %s }\n", indecimal, output);
  fflush(stdout);

  return 0;
}

Результат:

{ DEC:     1337, OCT:     2471 }
0 голосов
/ 29 мая 2014

Поскольку введены только основы, вы не хотите (по крайней мере, на данный момент) использовать функции, циклы, побитовые операторы, %o спецификатор формата и все такое.Вот мое основное решение:

int n, d1, d2, d3, d4, d5, o;

printf("Enter a number between 0 and 32767: ");
scanf("%d", &n);

d5 = n % 8;
n /= 8;
d4 = n % 8;
n /= 8;
d3 = n % 8;
n /= 8;
d2 = n % 8;
n /= 8;
d1 = n % 8;

o = 10000 * d1 + 1000 * d2 + 100 * d3 + 10 * d4 + d5;

printf("In octal, your number is: %.5d\n", o);

Обратите внимание, что поскольку n не требуется в выводе, вы можете изменять (делить) его для каждого шага (таким образом сохраняя деления, которые являются вычислительными и относительно дорогими).Вы в безопасности до 32767 (в восьмеричном: 77777), так как 32768 (8 * 8 * 8 * 8 * 8 = 8 ^ 5 = (2 ^ 3) ^ 5 = 2 ^ 15)первое число, для которого требуется шесть цифр в восьмеричном виде: 100000.

Эта переменная o на самом деле не нужна, более того, она не будет работать, если int подписан 16-разрядным (в некоторых древних системах)поэтому с этого момента лучше просто печатать отдельные цифры.

0 голосов
/ 19 марта 2011

Использовать %o спецификатор формата внутри printf

printf("Enter a number between 0 and 32767: ");
scanf("%d", &n);
printf("%o", n);
...