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

Как проблема домашней работы, я работаю над чтением десятичного интервала от 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) распечатает CF3.

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

8
задан Gilles 'SO- stop being evil' 17 September 2012 в 22:36
поделиться

9 ответов

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

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

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

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

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

3
ответ дан 5 December 2019 в 20:16
поделиться

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

.
0
ответ дан 5 December 2019 в 20:16
поделиться

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

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

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

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(). Надеюсь, что Вы узнаете лучшие способы получения ввода позже.

3
ответ дан 5 December 2019 в 20:16
поделиться

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

n = 1020, 3 гекс-цифры, big_base = 16*16

1-й шаг
1020 /(16*16) = 3

2-й шаг
n = 1020- 3*(16*16) = 252
. 252 / (16) = 15, F

3-й шаг
n = 252 - 15*16 = 12, C

1
ответ дан 5 December 2019 в 20:16
поделиться

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

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

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 : это правда, потому что в экземлярном коде используется таблица 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: I didn't read right ^^ Вы не имеете права использовать функции, поэтому о рекурсии не может быть и речи... Вот интерактивный способ, вы можете поместить это в 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);
}

Надеюсь, теперь он решает все !

.
1
ответ дан 5 December 2019 в 20:16
поделиться

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

Следующий код работает (я не много тестировал, видимо, работает). Я уверен, что это не самое оптимальное и лучшее решение, но это единственное, что я смог придумать. Он должен работать с любой базой. К сожалению, он не будет конвертировать 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);
}
0
ответ дан 5 December 2019 в 20:16
поделиться

Исходя из того, что было предложено, способ решения этой проблемы заключался в том, чтобы сохранить последнее число и повторить цикл для каждой цифры. Я отслеживал состояние печати, сохраняя предыдущий коэффициент и распечатывая его каждый раз, когда приходил к нему (затем сбрасывая номер и начиная заново), затем сбрасывая его на предыдущий. Звучит сложно, но изменение кода было простым. Мое условие остановки цикла было, когда у меня было 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;
}    

Спасибо всем, кто встал!

.
0
ответ дан 5 December 2019 в 20:16
поделиться

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

#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;
}
0
ответ дан 5 December 2019 в 20:16
поделиться

Вы можете использовать две петли. Первый продолжает генерировать мощности базы до тех пор, пока не найдет степень, большую, чем входное число. Второй начинается отсюда (или, скорее, на одну степень раньше) и возвращается к основанию ^ 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--;
}
0
ответ дан 5 December 2019 в 20:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: