Существует несколько проблем с использованием scanf
со спецификатором преобразования %d
для этого:
Если входная строка начинается с допустимого целого числа (например, «12abc»)), тогда «12» будет считано из входного потока и преобразовано и присвоено num
, а scanf
вернет 1, так что вы укажете успех, когда вы (вероятно) не должны;
Если входная строка не начинается с цифры, то scanf
не будет читать любые символов из входного потока, num
будетне будет изменено, и возвращаемое значение будет 0;
Вы не указываете, нужно ли обрабатывать недесятичные форматы, но это не будет работать, если вам придется обрабатыватьцелочисленные значения в восьмеричном или шестнадцатеричном формате (0x1a).Спецификатор преобразования %i
обрабатывает десятичный, восьмеричный и шестнадцатеричный форматы, но у вас все еще есть первые две проблемы.
Прежде всего, вам нужно прочитать входные данные как строку (предпочтительно используя fgets
).Если вам не разрешено использовать atoi
, возможно, вам также не разрешено использовать strtol
.Так что вам нужно изучить каждый символ в строке.Безопасный способ проверить значения цифр - использовать библиотечную функцию isdigit
(есть также функции isodigit
и isxdigit
для проверки восьмеричных и шестнадцатеричных цифр соответственно), например
while (*input && isdigit(*input))
input++;
(если вам даже не разрешено использовать isdigit
, isodigit
или isxdigit
, тогда шлепните своего учителя / профессора за выполнение задания сложнее, чем это на самом деле должно быть).
Если вам нужно иметь возможность обрабатывать восьмеричные или шестнадцатеричные форматы, тогда все становится немного сложнее.Соглашение C для восьмеричных форматов должно иметь ведущую цифру 0
, а для шестнадцатеричных форматов - 0x
.Таким образом, если первый непробельный символ равен 0, вам необходимо проверить следующий символ, прежде чем вы сможете узнать, какой недесятичный формат использовать.
Основной контур:
- Если первый непробельный символ не является '-', '+', '0' или ненулевой десятичной цифрой, то этоне является допустимой целочисленной строкой;
- Если первый непробельный символ - '-', то это отрицательное значение, в противном случае мы принимаем положительное значение;
- Если первый символ'+', то это положительное значение;
- Если первый непробельный и незнаковый символ является ненулевой десятичной цифрой, то ввод будет в десятичном формате, и вы будете использовать
isdigit
для проверки оставшихся символов; - Если первый непробельный и незнаковый символ равен '0', то ввод выполняется в восьмеричном или шестнадцатеричном формате;
- Если первыйнепробельный и незнаковый символ - это «0», а следующий символ - это цифра от «0» до «7», тогда ввод вводится в восьмеричном формате, и вы будете использовать
isodigit
для проверки оставшихся символов; - Если первым непробельным и незнаковым символом был 0, авторым символом является
x
или X
, тогда ввод осуществляется в шестнадцатеричном формате, и вы будете использовать isxdigit
для проверки оставшихся символов; - Если какой-либо из оставшихся символов не удовлетворяет указанной функции проверкивыше, то это не допустимая целочисленная строка.