Вывод цифр числа в обратном порядке без массивов или функций

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

вот что я получил до сих пор:

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

int main()
{
    int num, base, remainder, quotient;
    printf("please enter a positive number to convert: ");
    scanf("%d", &num);
    printf("please enter the base to convert to: ");
    scanf("%d", &base);

    remainder = quotient = 1;

    // validate input
    if (num < 0 || base < 0) {
        printf("Error - all numbers must be positive integers!n");
        return 1;
    }

    // keep dividing to find remainders
    while (quotient > 0) {
        remainder = num % base;
        quotient = num / base;
        num = quotient;
        if (remainder >= 10) {
            printf("%c", remainder + 55);
        } else {
            printf("%d", remainder);
        }
    }   
    printf("n");
    return 0;
}   

это отлично работает, только алгоритм, который это использует, вычисляет преобразованные числа от наименее значимой до наиболее значимой цифры, тем самым печатая ее в обратном порядке. Так, например, преобразование 1020 в шестнадцатеричное ( 0x3FC ) будет печатать Евро-3.

есть ли трюк, который я мог бы использовать, чтобы отменить эти числа для печати в правильном порядке. Я могу использовать только if-else, в то время как простые математические операторы и printf()/getchar()/scanf() - нет функций, массивов или указателей. спасибо.

9 ответов


(удалена исходная часть поста здесь, так как это не решение)

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

Итак, сначала вы вычисляете все цифры, пока не дойдете до последнего, а затем печатаете его.

затем вы берете исходное значение + base и начинаете делить снова, пока не дойдете до второй цифры "наибольшее значение". Распечатать его.

Это двойной цикл, и вы вычисляете все дважды, но вы не используете дополнительное хранилище.


хорошая попытка, и хорошо сформулированный вопрос. Если бы только у нас было больше людей, задающих вопросы таким ясным образом!

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

в любом случае, вы можете сделать что-то вроде этого:

curr := base
pow := 1
while num / curr >= 1 do:
    curr := curr * base
    pow := pow + 1

while pow >= 1:
    pow := pow - 1
    print floor(num / base ** pow)
    num := mod(num, base ** pow)

в основном, вы вычисляете, сколько цифр вы потребуется в первом цикле, а затем печать цифр в правильном порядке позже.

некоторые конкретные проблемы с вашим кодом. Я понимаю, что это начало класса C, но все же лучше знать о таких проблемах сейчас, чем никогда не осознавать их:

printf("please enter a positive number to convert: ");

вы должны добавить fflush(stdout) после этого убедитесь, что вывод отображается перед scanf() называется. По умолчанию stdout линия буферизована на много систем, поэтому подсказка не может появиться перед вашей программой ждет ввода.

printf("please enter the base to convert to: ");

то же, что и выше.

    if (remainder >= 10) {
        printf("%c", remainder + 55);
    } else {
        printf("%d", remainder);
    }

вы предполагаете набор символов ASCII. Это не обязательно должно быть правдой. Но без массивов или указателей нет простого способа распечатать алфавиты, соответствующие 10.... Кроме того, ваш код может печатать странные символы base > 36.

вы также должны знать, что это очень трудно использовать scanf() безопасно. Надеюсь, вы узнаете лучшие способы получения ввода позже.


в одном цикле вы можете рассчитать количество цифр и big_base.
Во втором цикле вы можете выводить цифры, начиная с наиболее значимых, например:

n = 1020, 3 шестнадцатеричные цифры, big_base = 16 * 16

1st step
1020 / (16*16) = 3

2nd step
n = 1020- 3*(16*16) = 252
252 / (16) = 15, F

3rd step
n = 252 - 15*16 = 12, C


Эй ! Я признаю известное домашнее задание, которое у меня было в первый год моей школы (@Epitech students:не копируйте / вставляйте следующий код, попробуйте придумать свое собственное решение, это для вашего же блага^^)

решение вашей проблемы заключается в рекурсивном выполнении задачи:

void    my_putnbr_base(int num, int base)
{
  int   start;
  int   remainder;

  remainder = num % base;
  start = (num - remainder) / base;
  if (start != 0)
    my_putnbr_base(start, base);
  if (remainder >= 10)
    printf("%c", remainder + 55);
  else
    printf("%d", remainder);
}

указывает ли ваша домашняя работа, что она должна работать только с положительными числами ? Если нет, легко включить обработку отрицательных чисел :

void    my_putnbr_base(int num, int base)
{
  int   start;
  int   remainder;

  if (num < 0)
    {
      putchar('-');
      my_putnbr_base(-num, base);
    }
  else
    {
      remainder = num % base;
      start = (num - remainder) / base;
      if (start != 0)
        my_putnbr_base(start, base);
      if (remainder >= 10)
        printf("%c", remainder + 55);
      else
        printf("%d", remainder);
    }
}

@arno: это правда, потому что код exemple использует таблицу ASCII. Если мы хотим что-то действительно гибкое, нам нужна база в параметре. Например :

>> my_putnbr_base(4242, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ")
39U
>> my_putnbr_base(42, "0123456789ABCDEF")
2A

это реализует пример :

void    my_putnbr_base(int num, char *base)
{
  int   start;
  int   remainder;
  int   len;

  len = strlen(base);
  if (num < 0)
    {
      putchar('-');
      my_putnbr_base(-num, base);
    }
  else
    {
      remainder = num % len;
      start = (num - remainder) / len;
      if (start != 0)
        my_putnbr_base(start, base);
      printf("%c", base[remainder]);
    }
}

Я надеюсь, что это решит вашу проблему !

edit: я не читал правильно ^^ вам не разрешено использовать функции, поэтому о рекурсии не может быть и речи... Вот интерактивный способ, вы можете поместить это в main (). Вы можете улучшить этот код путем добавления обработки отрицательных чисел и гибких баз, как я вам показал:)

int     my_putnbr_base_it(int num, int base)
{
  unsigned int  quotient = 1;
  unsigned int  remainder;

  while ((num / quotient) >= base)
    quotient *= base;
  while (quotient)
    {
      if ((remainder = (num / quotient) % base) < 10)
        printf("%d", remainder);
      else
        printf("%c", 55 + remainder);
      quotient /= base;
    }
  return (0);
}

надеюсь, что это решает все сейчас !


вы можете переписать часть кода, вычисляя каждое число, чтобы вести себя как машина состояния. Он начнется в исходном состоянии и вычислит количество цифр, затем изменит состояние на "печать N-й цифры", чтобы напечатать наиболее значимую цифру, затем изменит состояние, чтобы перейти к менее значимым цифрам и т. д., пока не достигнет конечного состояния. Запустив это внутри цикла, вы выведете все цифры в правильном порядке.


вы можете использовать два цикла. Первый продолжает генерировать мощности базы, пока не найдет мощность больше входного числа. Второй начинается отсюда (или, скорее, на одну мощность раньше) и возвращается к основанию^0 (т. е. 1), Чтобы вычислить выходные цифры, наиболее значимые в первую очередь.

непроверенные псевдо-код:

// Determine highest power, don't actually need "power" it's just there for illustration
power = 0;
baseraisedtopower = 1;
while (baseraisedtopower <= input)
{
    baseraisedtopower *= base;
    power++;
}
// Go back one step, could have saved previous result
baseraisedtopower /= base;
power--;
// Output
while (input > 0)
{
    // Integer division, truncate
    quotient = input / baseraisedtopower;
    printf("%c", quotient + 55);
    input -= quotient * baseraisedtopower;
    baseraisedtopower /= base;
    power--;
}

вы можете попробовать этот подход. Это больше доказательство концепции, вам все равно нужно будет справиться с каким-то особым случаем, но, эй, это ваша домашняя работа :)

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

int main()
{
    int num, base, remainder, quotient;
    int divider;

    printf("please enter a positive number to convert: ");
    scanf("%d", &num);
    printf("please enter the base to convert to: ");
    scanf("%d", &base);

    remainder = quotient = 1;

    // validate input
    if (num < 0 || base < 0) {
        printf("Error - all numbers must be positive integers!\n");
        return 1;
    }

    // First get the highest divider
    divider = base;

    while ( num / divider > base ) {
      divider *= base;
    }

    do {

      // Get the highest digit
      remainder = num / divider;

      // And update num accordingly
      num -= remainder * divider;
      divider /= base;

      if (remainder >= 10) {
        printf("%c", remainder + 55);
      } else {
        printf("%d", remainder);
      }

    } while ( divider );

    printf("\n");
    return 0;
}

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

следующий код работает (я не тестировал много, по-видимому, работает). Я уверен, что это не оптимальное и лучшее решение, но единственное, что я мог придумать. Он должен работать с любой базой. К сожалению, он не будет конвертировать 10->A, 11->B и т. д.:

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

int main(){
        int nr,base,res,tp,tpb,tpbt,r,rnr,lp,lpt,i;
        float baset,rt;

        /** Read number */
        printf("nr=");
        scanf("%d",&nr);

        /** Read base */
        printf("base=");
        scanf("%d",&base);

        /** Returning result */
        res=0;

        /** Test if number is positive
        and base is bigger than 2 */
        if(nr<0||base<2){
                /** Error */
                res=1;
        }
        else{
                /** Determine how many
                digits are necessary */
                lp=0;
                baset=base;
                while(baset>1){
                        lp++;
                        baset/=10;
                }

                /** Determine full power
                of 10 when r has length of lp */
                tpb=1;
                while((lp--)>0){
                        tpb*=10;
                }

                /** Power of ten that will be
                incremented */
                tp=0;

                /** Converted number (will be printed
                as the result) */
                rnr=0;

                /** Algorithm */
                while(nr>0){
                        r=nr%base;
                        nr/=base;
                        rt=r;

                        /** Temporary lp for
                        r */
                        lpt=0;
                        while(rt>1){
                                lpt++;
                                rt/=10;
                        }

                        /** Temporary tpb for
                        lpt */
                        tpbt=tpb;
                        for(i=0;i<lpt;i++){
                                tpbt/=10;
                        }

                        /** Build number */
                        rnr+=r*pow((double)(tpbt),(double)(tp++));
                }
        }

        /** Show number */
        printf("number is: %d \n",rnr);

        return (res);
}

основываясь на том, что было предложено, способ решить эту проблему состоял в том, чтобы сохранить печать последнего числа и повторить цикл для каждой цифры. Я отслеживал условие печати, сохраняя предыдущий фактор и печатая, когда я добирался до него каждый раз (затем сбрасывал номер и начинал заново), а затем сбрасывал его до предыдущего. Звучит сложно, но изменение кода было простым. Мое условие остановки для цикла было, когда у меня было 2 последовательных отпечатка, так как большую часть времени он просто вычислял фактор / остаток и ничего не печатать, и когда 2 цифры печатают подряд, это последние два. Во всяком случае, вот код:

#include <stdio.h>
#include <stdlib.h>
int main()
{
    int num, saved, base, remainder;
    int quotient, prev_q, stop_q, just_printed;

    printf("please enter a positive number to convert: ");
    scanf("%d", &num);
    printf("please enter the base to convert to: ");
    scanf("%d", &base);

    saved = num;
    remainder = quotient = prev_q = just_printed = 1;
    stop_q = 0;

    // validate input
    if (num <= 0 || base <= 0) {
        printf("Error - all numbers must be positive integers!\n");
        return 1;
    }

    // divide
    while (1) {
        remainder = num % base;
        quotient = num / base;
        num = quotient;

        // print if it's the last number and reset num to the next 
        if (quotient == stop_q) {
            if (remainder >= 10) { printf("%c", remainder + 55); } 
            else { printf("%d", remainder); }

            // if 2 consecutive printing occur, this means it's time to end this
            if (just_printed) { break; }

            // next time print when hitting the previous quotient
            stop_q = prev_q;

            // reset the number to the original value
            num = saved;


            just_printed = 1;
        } else {
            just_printed = 0;
        }
        prev_q = quotient;
    }   
    printf("\n");
    return 0;
}    

спасибо всем, кто присоединился!