Хотя у вас уже есть действительный ответ, исправляющий ошибку обновления dec_num
после деления и действительные рекурсивные методы, предоставленные другими, неясно, намереваетесь ли вы разрешить ввод отрицательных 3-значных значений кака также положительные значения.Реализация, которая определяет размер типа и затем сдвигается на единицу по каждому из битов, может обеспечить простое решение, которое будет обрабатывать как положительные, так и отрицательные значения.
Например, часть преобразования кода, сдвигаемая на *Значение 1006 * для каждого бита (индексированное 31 -> 0
) может быть простым:
int main (void) {
int decnum = 0; /* user input number */
unsigned remain = 0; /* remainder after shift */
size_t nbits = sizeof decnum * CHAR_BIT; /* number of bits for type */
/* read decnum here */
printf ("decimal: %d\nbinary : ", decnum); /* output value */
while (nbits--) { /* write bits 31->0 while 1 bits remain */
if ((remain = decnum >> nbits)) /* shift saving shifted value */
putchar ((remain & 1) ? '1' : '0'); /* bit 0/1 output '0'/'1' */
}
putchar ('\n'); /* tidy up with newline */
}
(примечание: простой оператор ternary
используется для определения, выводить ли '1'
или '0'
)
Большая часть вашей проблемы - ваша неспособность проверить возврат из scanf
.Это открытое приглашение для Неопределенное поведение .Независимо от того, какую функцию вы используете для пользовательского ввода , вы должны проверить, что ввод был успешным, прежде чем продолжить.В противном случае вы будете вызывать неопределенное поведение при попытке получить доступ к неопределенному значению.
При использовании scanf
для запроса допустимого ввода вы должны обрабатывать три случая каждый раз (1) сделалпользователь отменяет ввод, нажимая Ctrl + d , генерируя руководство EOF
?( Ctrl + z в окнах), (2) произошел сбой , соответствующий или , ?и (3) хороший случай ввода.Затем, как и в вашем случае, вы должны дополнительно проверить , что вход был в правильном диапазоне значений (3-значное число в вашем случае).Кроме того, для требуется допустимый ввод, вы должны обработать любой символ, который остается непрочитанным во входном буфере (как в случае сбоя , соответствующего , или еслипользователь подсунул и набрал дополнительные символы после целочисленного значения.
Теперь вполне нормально просто проверить ввод и return
на недопустимом вводе независимо от того, что вызвало сбой, но для требуется действительный ввод, вы должны обработать все три случая, проверить, что вход был в допустимом диапазоне (и даже затем удалить завершающий '\n'
, оставленный scanf
, подготавливая буфер ввода для любого дополнительного ввода, который может быть взятпозже в вашем коде.
Во многих случаях это потребует больше кода, чем требует ваш фактический расчет, но это очень важно. Например, в вашем случае, если вы хотите, чтобы требовал , пользователь должен ввестидопустимый ввод, вы можете заменить /* read decnum here */
на что-то похожее на:
for (;;) { /* loop continually until valid input or canceled */
int rtn; /* variable to hold scanf return */
fputs ("enter 3 digit integer: ", stdout); /* prompt */
rtn = scanf ("%d", &decnum); /* read value, saving return */
if (rtn == EOF) { /* handle manual EOF cancelation */
fputs ("(user canceled input)\n", stderr);
return 1;
}
if (rtn == 0) { /* handle input failure */
empty_stdin(); /* always empty input buffer */
fputs (" error: invalid integer input.\n", stderr);
} /* validate 3 digit poisitive (or negative) number */
else if (decnum < -999 || (decnum > -100 && decnum < 100)
|| decnum > 999) {
empty_stdin();
fputs (" error: not a 3 digit number.\n", stderr);
}
else { /* handle good input case (break loop) */
empty_stdin();
break;
}
}
примечание: вспомогательная функция empty_stdin()
.Это может быть реализовано с помощью getchar()
для чтения и отбрасывания любых символов, вызывающих проблемы, например,
void empty_stdin (void) /* helper function to empty stdin after bad input */
{ /* (as well as the trailing '\n' after good input) */
int c = getchar();
while (c != '\n' && c != EOF)
c = getchar();
}
В целом, вы можете сделать что-то вроде следующего:
#include <stdio.h>
#include <limits.h> /* for CHAR_BIT */
void empty_stdin (void) /* helper function to empty stdin after bad input */
{ /* (as well as the trailing '\n' after good input) */
int c = getchar();
while (c != '\n' && c != EOF)
c = getchar();
}
int main (void) {
int decnum = 0; /* user input number */
unsigned remain = 0; /* remainder after shift */
size_t nbits = sizeof decnum * CHAR_BIT; /* number of bits for type */
for (;;) { /* loop continually until valid input or canceled */
int rtn; /* variable to hold scanf return */
fputs ("enter 3 digit integer: ", stdout); /* prompt */
rtn = scanf ("%d", &decnum); /* read value, saving return */
if (rtn == EOF) { /* handle manual EOF cancelation */
fputs ("(user canceled input)\n", stderr);
return 1;
}
if (rtn == 0) { /* handle input failure */
empty_stdin(); /* always empty input buffer */
fputs (" error: invalid integer input.\n", stderr);
} /* validate 3 digit poisitive (or negative) number */
else if (decnum < -999 || (decnum > -100 && decnum < 100)
|| decnum > 999) {
empty_stdin();
fputs (" error: not a 3 digit number.\n", stderr);
}
else { /* handle good input case (break loop) */
empty_stdin();
break;
}
}
printf ("decimal: %d\nbinary : ", decnum); /* output value */
while (nbits--) { /* write bits 31->0 while 1 bits remain */
if ((remain = decnum >> nbits)) /* shift saving shifted value */
putchar ((remain & 1) ? '1' : '0'); /* bit 0/1 output '0'/'1' */
}
putchar ('\n'); /* tidy up with newline */
}
Пример использования / Вывод
$ ./bin/prnbin3digit
enter 3 digit integer: why?
error: invalid integer input.
enter 3 digit integer: -75
error: not a 3 digit number.
enter 3 digit integer: 1024
error: not a 3 digit number.
enter 3 digit integer: 127 and more junk
decimal: 127
binary : 1111111
Или случай с отрицательным значением:
$ ./bin/prnbin3digit
enter 3 digit integer: -127
decimal: -127
binary : 11111111111111111111111110000001
Или случай, когда пользователь отменяет ввод:
$ ./bin/prnbin3digit
enter 3 digit integer: (user canceled input)
Несмотря на то, что это оказалось дольше, чем могла бы быть простая right-shift
реализация преобразования, сейчас стоит выстроить хорошие привычки пользовательского ввода, чтобы потом избежать неисчислимых проблем.Посмотрите вещи и дайте мне знать, если у вас есть дополнительные вопросы.