Уроки по С++, Урок 6. Чтение ввода с клавиатуры
В этой книге ваши программы использовали выходной поток cout для отображения вывода на экран. Из данного урока вы узнаете, что C++ обеспечивает входной поток с именем cin, из которого программы могут читать информацию, введенную пользователем с клавиатуры. При использовании cin для чтения ввода с клавиатуры вы указываете одну или несколько переменных, которым cin будет присваивать входные значения. К тому времени, когда вы закончите этот урок, вы освоите следующие основные концепции:
- Вы можете использовать входной поток cin для присваивания определенным переменным символов и чисел, введенных с клавиатуры.
- При применении cin для чтения и присваивания переменной значения, введенного с клавиатуры, можно использовать содержимое переменной так, как если бы ваша программа использовала оператор присваивания для сохранения значения в переменной.
- Когда ваша программа
использует
Как вы уже знаете, если ваши программы используют выходной поток cout, они помещают данные в поток с помощью оператора вставки (<<). Подобным образом, если ваши программы применяют cin для чтения ввода с клавиатуры, они будут использовать оператор извлечения (>>).
ПЕРВОЕ ЗНАКОМСТВО С cin
Точно так же как выходной поток cout позволяет вашим программам записать вывод на экран, входной поток cin позволяет программам читать ввод с клавиатуры. Когда программы используют cin для чтения ввода с клавиатуры, они должны указать переменную, в которую cin поместит данные. Следующая программа FIRSTCIN.CPP использует cin для чтения числа, введенного с клавиатуры. Программа присваивает введенное число переменной с именем number, а затем выводит значение переменной, используя выходной поток cout:
#include <iostream.h>
void main(void)
{
int number; II Число, читаемое с клавиатуры
cout << «Введите ваше любимое число и нажмите Enter: «;
cin >> number;
cout << «Ваше любимое число равно » << number << endl;
}
Когда вы откомпилируете и запустите эту программу, на вашем экране появится сообщение, предлагающее вам ввести ваше любимое число. Если вы введете число и нажмете ENTER, программа присвоит ввод переменной number. Затем, используя cout, программа выведет сообщение, отображающее ваше любимое число.
Следующая программа TWONBRS.CPP запрашивает у вас два числа. Программа присваивает числа переменным
#include <iostream.h>
void main(void)
{
int first, second; // Числа, введенные с клавиатуры
cout << «Введите два числа и нажмите Enter: «;
cin >> first >> second;
cout << «Были введены числа » << first << » и » << second << endl;
}
Обратите внимание на использование с cin двух операторов извлечения:
cin >> first >> second;
В этом случае cin присвоит первое введенное значение переменной first, a второе переменной second. Если для вашей программы требуется третье значение, вы можете использовать третий оператор извлечения, как показано ниже:
cin >> first >> second >> third;
Если вы применяете cin для чтения чисел с клавиатуры, cin использует левый пустой символ (пробел, табуляцию, возврат каретки), чтобы определить, где начинается одно значение, а где второе. Экспериментируйте с программой TWONBRS, разделяя числа табуляцией, пробелом и возвратом каретки.
Чтение ввода с клавиатуры с помощью cin
Для чтения ввода с клавиатуры программы могут использовать входной поток cin. При использовании cin вы должны указать переменную, в которую cin помещает данные. Затем используйте оператор извлечения (>>) для направления данных, как показано ниже:
cin >> some_variable;
Оператор извлечения называется так, потому что он извлекает (удаляет) данные из входного потока, присваивая значение указанной переменной.
Следите за ошибками переполнения
Если ваши программы выполняют ввод с использованием cin, остерегайтесь возможных ошибок, возникающих при вводе пользователем неверного числа. Например, запустите программу FIRSTCIN, которую вы только что создали. Когда программа запросит вас ввести ваше любимое число, введите число 1000000 и нажмите ENTER. При этом программа не сможет отобразить число 1000000 в качестве введенного значения. Вместо этого возникнет ошибка переполнения, так как 1000000 превышает наибольшее значение, которое может хранить тип int.
Если вы внимательно рассмотрите программу FIRSTCIN. CPP, то обратите внимание, что cin присваивает введенное число переменной типа int. Как вы узнали из урока 4, переменные типа int могут хранить значения только в диапазоне от -32768 до 32767. Поскольку переменная типа int не может вместить значение 1000000, возникает ошибка. Запустите программу еще несколько раз, вводя отрицательные и положительные числа. Обратите внимание на ошибки, которые возникают, если вы выходите за допустимые пределы значений для той переменной, в которую cin помещает ввод.
Следите за ошибками несовпадения типов
Как уже обсуждалось, программа FIRSTCIN.CPP предполагает, что пользователь вводит значение в диапазоне от -32768 до 32767. Если вместо ввода числа вне этого диапазона, пользователь вводит буквы или другие символы, то возникает другая ошибка — ошибка несовпадения типов. Другими словами, программа ожидала значение одного типа (int), а пользователь ввел значение другого типа (char). Для примера запустите программу второй раз. Когда программа запросит число, введите буквы АВС. Как и раньше, возникнет ошибка, поскольку программа ожидает целое число, а не буквы.
Выполните подобные эксперименты с программой TWONBRS, вводя бессмысленные значения или числа с плавающей точкой. Вы обнаружите, что программа наталкивается на те же ошибки. В последующих уроках вы научитесь выполнять операции ввода таким образом, чтобы уменьшить возможность подобных ошибок. А сейчас просто помните, что такие ошибки могут возникать.
Чтение символьных данных
Обе предыдущие программы использовали cin для чтения целых чисел в переменные типа int. Следующая программа CIN_CHAR.CPP использует входной поток cin для чтения символов с клавиатуры. Как видите, программа читает символ в переменную типа char.
#include <iostream.h>
void main(void)
{
}
char letter;
cout << «Введите любой символ и нажмите Enter: «;
cin >> letter;
cout << «Был введен символ » << letter << endl;
Откомпилируйте и поэкспериментируйте с данной программой, вводя более одного символа и наблюдая за реакцией программы. Вы обнаружите, что программа каждый раз работает только с одним символом.
Чтение слов с клавиатуры
Во второй части данной книги вы научитесь сохранять слова или даже строки текста в одной переменной. Там же вы узнаете, как использовать входной поток cin для чтения слов и целых строк. А сейчас можете создать свою собственную простую программу, которая читает значения типа float или long. Например, следующая программа CIN_LONG.CPP использует cin для чтения значения типа long:
#include <iostream.h>
void main(void)
{
long value;
cout << «Введите большое число и нажмите Enter: «;
cin >> value;
cout << «Было введено число » << value << endl;}
Как и раньше, поэкспериментируйте с этой программой, вводя очень большие числа (и отрицательные тоже).
Перенаправление В/В и входной поток cin
Как вы уже знаете из урока 3, если ваши программы используют выходной поток cout, пользователь может перенаправить вывод программы с экрана дисплея в файл или на принтер. Как уже обсуждалось, выходной поток cout соответствует стандартному выводу операционной системы. Подобным образом входной поток cin соответствует стандартному вводу операционной системы. В результате, если ваша программа использует cin для выполнения операций ввода, пользователь может перенаправить ввод программы с клавиатуры на файл. В последующих уроках вы научитесь писать программы, которые читают и обрабатывают перенаправленный ввод.
ЧТО ВАМ НЕОБХОДИМО ЗНАТЬ
В этом уроке вы научились использовать входной поток cin для выполнения ввода с клавиатуры. Как вы уже знаете, если ваши программы используют cin для чтения ввода с клавиатуры, вам следует указать переменные, которым cin присваивает вводимые значения. В уроке 7 вы научитесь использовать оператор C++ if, чтобы позволить программам принимать собственные решения. Однако перед тем, как приступить к уроку 7, убедитесь, что вы освоили следующие основные концепции:
- C++ предоставляет входной поток cin, который ваши программы могут использовать для чтения ввода с клавиатуры.
- Если программы для чтения ввода используют cin, они должны указать одну или несколько переменных, в которые cin будет помещать данные.
- Чтобы направить ввод в переменную, вам следует использовать cin с оператором извлечения (>>).
- При применении
- Если пользователь вводит неверные данные, могут возникать ошибки переполнения или несоответствия типов, а значения, присвоенные входным потоком cin переменным вашей программы, будут неверны.
www.programmersclub.ru
Учебный курс. Часть 23. Ввод чисел с консоли
В прошлой части мы научились преобразовывать числа в строку и выводить на консоль. А в этой займёмся обратной задачей — вводом чисел с консоли и преобразованием строки в число. Поскольку ввод в двоичном и восьмеричном виде используется редко, я рассмотрю только примеры ввода чисел в десятичном виде (со знаком и без знака) и в шестнадцатеричном.
Вводить числа сложнее, чем выводить, так как помимо преобразования необходимо проверять корректность введённой пользователем строки. Хорошая программа должна устойчиво работать при любых входных данных (в том числе специально введённых так, чтобы нарушить её работу).
Ввод строки с консоли
Для ввода строки можно использовать функцию MS-DOS 0Ah. Функция позволяет ввести строку длиной от 1 до 254 символов. При вызове в DX передаётся адрес буфера, первый байт которого должен содержать максимально допустимую длину строки. Длина считается вместе с символом конца строки CR (0dh). В результате работы функции во второй байт буфера записывается фактическая длина введённой строки (не считая символа CR). Начиная с третьего байта в буфер записываются символы строки. Подробнее о работе функции можно узнать в раритетном справочнике по DOS 🙂
Чтобы удобнее было использовать эту функцию, можно написать небольшую процедуру. Например, такую:
;Процедура ввода строки c консоли ; вход: AL - максимальная длина (с символом CR) (1-254) ; выход: AL - длина введённой строки (не считая символа CR) ; DX - адрес строки, заканчивающейся символом CR(0Dh) input_str: push cx ;Сохранение СX mov cx,ax ;Сохранение AX в CX mov ah,0Ah ;Функция DOS 0Ah - ввод строки в буфер mov [buffer],al ;Запись максимальной длины в первый байт буфера mov byte[buffer+1],0 ;Обнуление второго байта (фактической длины) mov dx,buffer ;DX = aдрес буфера int 21h ;Обращение к функции DOS mov al,[buffer+1] ;AL = длина введённой строки add dx,2 ;DX = адрес строки mov ah,ch ;Восстановление AH pop cx ;Восстановление CX ret ... buffer rb 256 |
;Процедура ввода строки c консоли ; вход: AL — максимальная длина (с символом CR) (1-254) ; выход: AL — длина введённой строки (не считая символа CR) ; DX — адрес строки, заканчивающейся символом CR(0Dh) input_str: push cx ;Сохранение СX mov cx,ax ;Сохранение AX в CX mov ah,0Ah ;Функция DOS 0Ah — ввод строки в буфер mov [buffer],al ;Запись максимальной длины в первый байт буфера mov byte[buffer+1],0 ;Обнуление второго байта (фактической длины) mov dx,buffer ;DX = aдрес буфера int 21h ;Обращение к функции DOS mov al,[buffer+1] ;AL = длина введённой строки add dx,2 ;DX = адрес строки mov ah,ch ;Восстановление AH pop cx ;Восстановление CX ret … buffer rb 256
Процедура использует отдельно объявленный буфер. В качестве единственного параметра ей передаётся максимальная длина строки в регистре AL. После возврата из процедуры в этот регистр записывается фактическая длина строки, а в регистр DX — адрес начала строки. Старшая часть AX сохраняется.
Ввод десятичных чисел без знака
Для преобразования числа в строку используется так называемая схема Горнера. Любое число в десятичной системе можно представить в следующем виде:
34710 = 3·102 + 4·101 + 7·100 = (3·10 + 4)·10 + 7
Это очень удобно запрограммировать в цикле: результат сначала умножается на 10, а потом к нему прибавляется очередная цифра и так далее для всех цифр. Кстати, это верно не только для десятичной системы счисления, но и для других, разница только в множителе, который должен быть равен основанию системы счисления.
Следующая процедура преобразует строку в слово в регистре AX. Адрес строки передаётся в DX, длина строки передаётся в AL. Если строка не корректна, процедура возвращает 0 и устанавливает флаг CF. Ошибка возвращается в следующих случаях:
- строка имеет нулевую длину, то есть пустая строка;
- строка содержит любые символы кроме десятичных цифр;
- число находится вне границ диапазона представления чисел (для слова без знака 0…65535).
;Процедура преобразования десятичной строки в слово без знака ; вход: AL - длина строки ; DX - адрес строки, заканчивающейся символом CR(0Dh) ; выход: AX - слово (в случае ошибки AX = 0) ; CF = 1 - ошибка str_to_udec_word: push cx ;Сохранение всех используемых регистров push dx push bx push si push di mov si,dx ;SI = адрес строки mov di,10 ;DI = множитель 10 (основание системы счисления) movzx cx,al ;CX = счётчик цикла = длина строки jcxz studw_error ;Если длина = 0, возвращаем ошибку xor ax,ax ;AX = 0 xor bx,bx ;BX = 0 studw_lp: mov bl,[si] ;Загрузка в BL очередного символа строки inc si ;Инкремент адреса cmp bl,'0' ;Если код символа меньше кода '0' jl studw_error ; возвращаем ошибку cmp bl,'9' ;Если код символа больше кода '9' jg studw_error ; возвращаем ошибку sub bl,'0' ;Преобразование символа-цифры в число mul di ;AX = AX * 10 jc studw_error ;Если результат больше 16 бит - ошибка add ax,bx ;Прибавляем цифру jc studw_error ;Если переполнение - ошибка loop studw_lp ;Команда цикла jmp studw_exit ;Успешное завершение (здесь всегда CF = 0) studw_error: xor ax,ax ;AX = 0 stc ;CF = 1 (Возвращаем ошибку) studw_exit: pop di ;Восстановление регистров pop si pop bx pop dx pop cx ret |
;Процедура преобразования десятичной строки в слово без знака ; вход: AL — длина строки ; DX — адрес строки, заканчивающейся символом CR(0Dh) ; выход: AX — слово (в случае ошибки AX = 0) ; CF = 1 — ошибка str_to_udec_word: push cx ;Сохранение всех используемых регистров push dx push bx push si push di mov si,dx ;SI = адрес строки mov di,10 ;DI = множитель 10 (основание системы счисления) movzx cx,al ;CX = счётчик цикла = длина строки jcxz studw_error ;Если длина = 0, возвращаем ошибку xor ax,ax ;AX = 0 xor bx,bx ;BX = 0 studw_lp: mov bl,[si] ;Загрузка в BL очередного символа строки inc si ;Инкремент адреса cmp bl,’0′ ;Если код символа меньше кода ‘0’ jl studw_error ; возвращаем ошибку cmp bl,’9′ ;Если код символа больше кода ‘9’ jg studw_error ; возвращаем ошибку sub bl,’0′ ;Преобразование символа-цифры в число mul di ;AX = AX * 10 jc studw_error ;Если результат больше 16 бит — ошибка add ax,bx ;Прибавляем цифру jc studw_error ;Если переполнение — ошибка loop studw_lp ;Команда цикла jmp studw_exit ;Успешное завершение (здесь всегда CF = 0) studw_error: xor ax,ax ;AX = 0 stc ;CF = 1 (Возвращаем ошибку) studw_exit: pop di ;Восстановление регистров pop si pop bx pop dx pop cx ret
Для установки флага CF используется команда STC. Сбросить флаг CF можно командой CLC. В коде данной процедуры она не используется, так как в случае успешного завершения цикла флаг CF всегда будет равен 0.
На основе этой процедуры несложно написать ещё одну для ввода чисел размером 1 байт. Сначала строка преобразуется в слово без знака, а затем выполняется проверка старшей части на равенство нулю. Обратите внимание, что команда TEST всегда сбрасывает флаг CF.
;Процедура преобразования десятичной строки в байт без знака ; вход: AL - длина строки ; DX - адрес строки, заканчивающейся символом CR(0Dh) ; выход: AL - байт (в случае ошибки AL = 0) ; CF = 1 - ошибка str_to_udec_byte: push dx ;Сохранение регистров push ax call str_to_udec_word ;Преобразование строки в слово (без знака) jc studb_exit ;Если ошибка, то возвращаем ошибку test ah,ah ;Проверка старшего байта AX jz studb_exit ;Если 0, то выход из процедуры (здесь всегда CF = 0) xor al,al ;AL = 0 stc ;CF = 1 (Возвращаем ошибку) studb_exit: pop dx mov ah,dh ;Восстановление только старшей части AX pop dx ret |
;Процедура преобразования десятичной строки в байт без знака ; вход: AL — длина строки ; DX — адрес строки, заканчивающейся символом CR(0Dh) ; выход: AL — байт (в случае ошибки AL = 0) ; CF = 1 — ошибка str_to_udec_byte: push dx ;Сохранение регистров push ax call str_to_udec_word ;Преобразование строки в слово (без знака) jc studb_exit ;Если ошибка, то возвращаем ошибку test ah,ah ;Проверка старшего байта AX jz studb_exit ;Если 0, то выход из процедуры (здесь всегда CF = 0) xor al,al ;AL = 0 stc ;CF = 1 (Возвращаем ошибку) studb_exit: pop dx mov ah,dh ;Восстановление только старшей части AX pop dx ret
Следующие две процедуры совмещают ввод строки с преобразованием строки в число. Для слова нужно ввести максимум 5 символов, а для байта — максимум 3.
;Процедура ввода слова с консоли в десятичном виде (без знака) ; выход: AX - слово (в случае ошибки AX = 0) ; CF = 1 - ошибка input_udec_word: push dx ;Сохранение DX mov al,6 ;Ввод максимум 5 символов (65535) + конец строки call input_str ;Вызов процедуры ввода строки call str_to_udec_word ;Преобразование строки в слово (без знака) pop dx ;Восстановление DX ret |
;Процедура ввода слова с консоли в десятичном виде (без знака) ; выход: AX — слово (в случае ошибки AX = 0) ; CF = 1 — ошибка input_udec_word: push dx ;Сохранение DX mov al,6 ;Ввод максимум 5 символов (65535) + конец строки call input_str ;Вызов процедуры ввода строки call str_to_udec_word ;Преобразование строки в слово (без знака) pop dx ;Восстановление DX ret
;Процедура ввода байта с консоли в десятичном виде (без знака) ; выход: AL - байт (в случае ошибки AL = 0) ; CF = 1 - ошибка input_udec_byte: push dx ;Сохранение DX mov al,4 ;Ввод максимум 3 символов (255) + конец строки call input_str ;Вызов процедуры ввода строки call str_to_udec_byte ;Преобразование строки в байт (без знака) pop dx ;Восстановление DX ret |
;Процедура ввода байта с консоли в десятичном виде (без знака) ; выход: AL — байт (в случае ошибки AL = 0) ; CF = 1 — ошибка input_udec_byte: push dx ;Сохранение DX mov al,4 ;Ввод максимум 3 символов (255) + конец строки call input_str ;Вызов процедуры ввода строки call str_to_udec_byte ;Преобразование строки в байт (без знака) pop dx ;Восстановление DX ret
Ввод десятичных чисел со знаком
Ввод чисел со знаком немного труднее. Необходимо проверить первый символ строки: если это символ ‘-‘, то число отрицательное. Кроме того, нужно внимательно проверить диапазон представления (для слова со знаком -32768…32767). Строку без символа ‘-‘ можно преобразовать процедурой для беззнакового числа.
;Процедура преобразования десятичной строки в слово со знаком ; вход: AL - длина строки ; DX - адрес строки, заканчивающейся символом CR(0Dh) ; выход: AX - слово (в случае ошибки AX = 0) ; CF = 1 - ошибка str_to_sdec_word: push bx ;Сохранение регистров push dx test al,al ;Проверка длины строки jz stsdw_error ;Если равно 0, возвращаем ошибку mov bx,dx ;BX = адрес строки mov bl,[bx] ;BL = первый символ строки cmp bl,'-' ;Сравнение первого символа с '-' jne stsdw_no_sign ;Если не равно, то преобразуем как число без знака inc dx ;Инкремент адреса строки dec al ;Декремент длины строки stsdw_no_sign: call str_to_udec_word ;Преобразуем строку в слово без знака jc stsdw_exit ;Если ошибка, то возвращаем ошибку cmp bl,'-' ;Снова проверяем знак jne stsdw_plus ;Если первый символ не '-', то число положительное cmp ax,32768 ;Модуль отрицательного числа должен быть не больше 32768 ja stsdw_error ;Если больше (без знака), возвращаем ошибку neg ax ;Инвертируем число jmp stsdw_ok ;Переход к нормальному завершению процедуры stsdw_plus: cmp ax,32767 ;Положительное число должно быть не больше 32767 ja stsdw_error ;Если больше (без знака), возвращаем ошибку stsdw_ok: clc ;CF = 0 jmp stsdw_exit ;Переход к выходу из процедуры stsdw_error: xor ax,ax ;AX = 0 stc ;CF = 1 (Возвращаем ошибку stsdw_exit: pop dx ;Восстановление регистров pop bx ret |
;Процедура преобразования десятичной строки в слово со знаком ; вход: AL — длина строки ; DX — адрес строки, заканчивающейся символом CR(0Dh) ; выход: AX — слово (в случае ошибки AX = 0) ; CF = 1 — ошибка str_to_sdec_word: push bx ;Сохранение регистров push dx test al,al ;Проверка длины строки jz stsdw_error ;Если равно 0, возвращаем ошибку mov bx,dx ;BX = адрес строки mov bl,[bx] ;BL = первый символ строки cmp bl,’-‘ ;Сравнение первого символа с ‘-‘ jne stsdw_no_sign ;Если не равно, то преобразуем как число без знака inc dx ;Инкремент адреса строки dec al ;Декремент длины строки stsdw_no_sign: call str_to_udec_word ;Преобразуем строку в слово без знака jc stsdw_exit ;Если ошибка, то возвращаем ошибку cmp bl,’-‘ ;Снова проверяем знак jne stsdw_plus ;Если первый символ не ‘-‘, то число положительное cmp ax,32768 ;Модуль отрицательного числа должен быть не больше 32768 ja stsdw_error ;Если больше (без знака), возвращаем ошибку neg ax ;Инвертируем число jmp stsdw_ok ;Переход к нормальному завершению процедуры stsdw_plus: cmp ax,32767 ;Положительное число должно быть не больше 32767 ja stsdw_error ;Если больше (без знака), возвращаем ошибку stsdw_ok: clc ;CF = 0 jmp stsdw_exit ;Переход к выходу из процедуры stsdw_error: xor ax,ax ;AX = 0 stc ;CF = 1 (Возвращаем ошибку stsdw_exit: pop dx ;Восстановление регистров pop bx ret
Обратите внимание, что для перехода после проверки диапазона используется команда JA (как для сравнения чисел без знака). Ввод байта со знаком реализуется с помощью той же процедуры и дополнительной проверки диапазона значения.
;Процедура преобразования десятичной строки в байт со знаком ; вход: AL - длина строки ; DX - адрес строки, заканчивающейся символом CR(0Dh) ; выход: AL - байт (в случае ошибки AL = 0) ; CF = 1 - ошибка str_to_sdec_byte: push dx ;Сохранение регистров push ax call str_to_sdec_word ;Преобразование строки в слово (со знаком) jc stsdb_exit ;Если ошибка, то возвращаем ошибку cmp ax,127 ;Сравнение результата с 127 jg stsdb_error ;Если больше - ошибка cmp ax,-128 ;Сравнение результата с -128 jl stsdb_error ;Если меньше - ошибка clc ;CF = 0 jmp studb_exit ;Переход к выходу из процедуры stsdb_error: xor al,al ;AL = 0 stc ;CF = 1 (Возвращаем ошибку) stsdb_exit: pop dx mov ah,dh ;Восстановление только старшей части AX pop dx ret |
;Процедура преобразования десятичной строки в байт со знаком ; вход: AL — длина строки ; DX — адрес строки, заканчивающейся символом CR(0Dh) ; выход: AL — байт (в случае ошибки AL = 0) ; CF = 1 — ошибка str_to_sdec_byte: push dx ;Сохранение регистров push ax call str_to_sdec_word ;Преобразование строки в слово (со знаком) jc stsdb_exit ;Если ошибка, то возвращаем ошибку cmp ax,127 ;Сравнение результата с 127 jg stsdb_error ;Если больше — ошибка cmp ax,-128 ;Сравнение результата с -128 jl stsdb_error ;Если меньше — ошибка clc ;CF = 0 jmp studb_exit ;Переход к выходу из процедуры stsdb_error: xor al,al ;AL = 0 stc ;CF = 1 (Возвращаем ошибку) stsdb_exit: pop dx mov ah,dh ;Восстановление только старшей части AX pop dx ret
Наконец, ещё две процедуры совмещают ввод строки с преобразованием её в слово и байт со знаком.
;Процедура ввода слова с консоли в десятичном виде (со знаком) ; выход: AX - слово (в случае ошибки AX = 0) ; CF = 1 - ошибка input_sdec_word: push dx ;Сохранение DX mov al,7 ;Ввод максимум 7 символов (-32768) + конец строки call input_str ;Вызов процедуры ввода строки call str_to_sdec_word ;Преобразование строки в слово (со знаком) pop dx ;Восстановление DX ret |
;Процедура ввода слова с консоли в десятичном виде (со знаком) ; выход: AX — слово (в случае ошибки AX = 0) ; CF = 1 — ошибка input_sdec_word: push dx ;Сохранение DX mov al,7 ;Ввод максимум 7 символов (-32768) + конец строки call input_str ;Вызов процедуры ввода строки call str_to_sdec_word ;Преобразование строки в слово (со знаком) pop dx ;Восстановление DX ret
;Процедура ввода байта с консоли в десятичном виде (со знаком) ; выход: AL - байт (в случае ошибки AL = 0) ; CF = 1 - ошибка input_sdec_byte: push dx ;Сохранение DX mov al,5 ;Ввод максимум 3 символов (-128) + конец строки call input_str ;Вызов процедуры ввода строки call str_to_sdec_byte ;Преобразование строки в байт (со знаком) pop dx ;Восстановление DX ret |
;Процедура ввода байта с консоли в десятичном виде (со знаком) ; выход: AL — байт (в случае ошибки AL = 0) ; CF = 1 — ошибка input_sdec_byte: push dx ;Сохранение DX mov al,5 ;Ввод максимум 3 символов (-128) + конец строки call input_str ;Вызов процедуры ввода строки call str_to_sdec_byte ;Преобразование строки в байт (со знаком) pop dx ;Восстановление DX ret
Полный исходный код примера вы можете скачать отсюда: inputdec.asm. В случае некорректной строки программа выводит сообщение об ошибке и повторяет запрос ввода числа:
Ввод шестнадцатеричных чисел
Преобразование шестнадцатеричной строки в число несколько проще. Удобно реализовать в виде отдельной процедуры преобразование одной цифры. Процедура воспринимает символы ‘A’-‘F’ независимо от регистра. Так как перед вычитанием выполняются проверки, флаг CF всегда будет равен нулю после успешного преобразования.
;Процедура преобразования шестнадцатеричной цифры в число ; вход: DL - символ-цифра ; выход: DL - значение цифры (0-15, в случае ошибки DL = 0) ; CF = 1 - ошибка convert_hex_digit: cmp dl,'0' ;Сравнение с символом '0' jl chd_error ;Если меньше, возвращаем ошибку cmp dl,'9' ;Сравнение с символом '9' jg chd_a_f ;Если больше, то возможно это буква a-f или A-F sub dl,'0' ;Преобразование цифры в число ret ;Возврат из процедуры (здесь всегда CF = 0) chd_a_f: and dl,11011111b ;Преобразование буквы в верхний регистр cmp dl,'A' ;Сравнение с символом 'A' jl chd_error ;Если меньше, возвращаем ошибку cmp dl,'F' ;Сравнение с символом 'F' jg chd_error ;Если больше, возвращаем ошибку sub dl,'A'-10 ;Преобразуем букву в число ret ;Возврат из процедуры (здесь тоже всегда CF = 0) chd_error: xor dl,dl ;DL = 0 stc ;CF = 1 ret ;Возврат из процедуры |
;Процедура преобразования шестнадцатеричной цифры в число ; вход: DL — символ-цифра ; выход: DL — значение цифры (0-15, в случае ошибки DL = 0) ; CF = 1 — ошибка convert_hex_digit: cmp dl,’0′ ;Сравнение с символом ‘0’ jl chd_error ;Если меньше, возвращаем ошибку cmp dl,’9′ ;Сравнение с символом ‘9’ jg chd_a_f ;Если больше, то возможно это буква a-f или A-F sub dl,’0′ ;Преобразование цифры в число ret ;Возврат из процедуры (здесь всегда CF = 0) chd_a_f: and dl,11011111b ;Преобразование буквы в верхний регистр cmp dl,’A’ ;Сравнение с символом ‘A’ jl chd_error ;Если меньше, возвращаем ошибку cmp dl,’F’ ;Сравнение с символом ‘F’ jg chd_error ;Если больше, возвращаем ошибку sub dl,’A’-10 ;Преобразуем букву в число ret ;Возврат из процедуры (здесь тоже всегда CF = 0) chd_error: xor dl,dl ;DL = 0 stc ;CF = 1 ret ;Возврат из процедуры
Теперь легко можно написать преобразование шестнадцатеричной строки в слово. Вместо умножения на 16 в процедуре используется сдвиг на 4 бита влево, а вместо сложения — операция ИЛИ. Проверки диапазона значения не нужны, достаточно проверить длину строки и преобразовать цифры.
;Процедура преобразования шестнадцатеричной строки в слово ; вход: AL - длина строки ; DX - адрес строки, заканчивающейся символом CR(0Dh) ; выход: AX - слово (в случае ошибки AX = 0) ; CF = 1 - ошибка str_to_hex_word: push cx ;Сохранение регистров push dx push si movzx cx,al ;CX = счётчик цикла = длина строки jcxz sthw_error ;Если длина строки = 0, возвращаем ошибку cmp cx,4 jg sthw_error ;Если длина строки больше 4, возвращаем ошибку xor ax,ax ;AX = 0 mov si,dx ;SI = адрес строки sthw_lp: mov dl,[si] ;Загрузка в DL очередного символа строки inc si ;Инкремент адреса строки call convert_hex_digit ;Преобразование шестнадцатеричной цифры в число jc sthw_error ;Если ошибка, то возвращаем ошибку shl ax,4 ;Сдвиг AX на 4 бита влево or al,dl ;Добавление преобразованной цифры loop sthw_lp ;Команда цикла jmp sthw_exit ;CF = 0 sthw_error: xor ax,ax ;AX = 0 stc ;CF = 1 sthw_exit: pop si ;Восстановление регистров pop dx pop cx ret |
;Процедура преобразования шестнадцатеричной строки в слово ; вход: AL — длина строки ; DX — адрес строки, заканчивающейся символом CR(0Dh) ; выход: AX — слово (в случае ошибки AX = 0) ; CF = 1 — ошибка str_to_hex_word: push cx ;Сохранение регистров push dx push si movzx cx,al ;CX = счётчик цикла = длина строки jcxz sthw_error ;Если длина строки = 0, возвращаем ошибку cmp cx,4 jg sthw_error ;Если длина строки больше 4, возвращаем ошибку xor ax,ax ;AX = 0 mov si,dx ;SI = адрес строки sthw_lp: mov dl,[si] ;Загрузка в DL очередного символа строки inc si ;Инкремент адреса строки call convert_hex_digit ;Преобразование шестнадцатеричной цифры в число jc sthw_error ;Если ошибка, то возвращаем ошибку shl ax,4 ;Сдвиг AX на 4 бита влево or al,dl ;Добавление преобразованной цифры loop sthw_lp ;Команда цикла jmp sthw_exit ;CF = 0 sthw_error: xor ax,ax ;AX = 0 stc ;CF = 1 sthw_exit: pop si ;Восстановление регистров pop dx pop cx ret
Для ввода байта используется та же процедура, но дополнительно проверяется длина строки — она должна быть не больше 2.
;Процедура преобразования шестнадцатеричной строки в байт ; вход: AL - длина строки ; DX - адрес строки, заканчивающейся символом CR(0Dh) ; выход: AL - байт (в случае ошибки AL = 0) ; CF = 1 - ошибка str_to_hex_byte: push cx ;Сохранение CX mov cx,ax ;Сохранение AX в CX cmp al,2 ;Проверка длины строки jg sthb_error ;Если больше 2, возвращаем ошибку call str_to_hex_word ;Преобразование строки в слово jnc sthb_exit ;Если нет ошибки, то переход к выходу из процедуры sthb_error: stc ;CF = 1 sthb_exit: mov ah,ch ;Восстановление AH pop cx ;Восстановление CX ret |
;Процедура преобразования шестнадцатеричной строки в байт ; вход: AL — длина строки ; DX — адрес строки, заканчивающейся символом CR(0Dh) ; выход: AL — байт (в случае ошибки AL = 0) ; CF = 1 — ошибка str_to_hex_byte: push cx ;Сохранение CX mov cx,ax ;Сохранение AX в CX cmp al,2 ;Проверка длины строки jg sthb_error ;Если больше 2, возвращаем ошибку call str_to_hex_word ;Преобразование строки в слово jnc sthb_exit ;Если нет ошибки, то переход к выходу из процедуры sthb_error: stc ;CF = 1 sthb_exit: mov ah,ch ;Восстановление AH pop cx ;Восстановление CX ret
Ещё две процедуры для ввода и преобразования строки, также как для десятичного ввода:
;Процедура ввода слова с консоли в шестнадцатеричном виде ; выход: AX - слово (в случае ошибки AX = 0) ; CF = 1 - ошибка input_hex_word: push dx ;Сохранение DX mov al,5 ;Ввод максимум 4 символов (FFFF) + конец строки call input_str ;Вызов процедуры ввода строки call str_to_hex_word ;Преобразование строки в слово pop dx ;Восстановление DX ret |
;Процедура ввода слова с консоли в шестнадцатеричном виде ; выход: AX — слово (в случае ошибки AX = 0) ; CF = 1 — ошибка input_hex_word: push dx ;Сохранение DX mov al,5 ;Ввод максимум 4 символов (FFFF) + конец строки call input_str ;Вызов процедуры ввода строки call str_to_hex_word ;Преобразование строки в слово pop dx ;Восстановление DX ret
;Процедура ввода байта с консоли в шестнадцатеричном виде ; выход: AL - байт (в случае ошибки AL = 0) ; CF = 1 - ошибка input_hex_byte: push dx ;Сохранение DX mov al,3 ;Ввод максимум 2 символов (FF) + конец строки call input_str ;Вызов процедуры ввода строки call str_to_hex_byte ;Преобразование строки в байт pop dx ;Восстановление DX ret |
;Процедура ввода байта с консоли в шестнадцатеричном виде ; выход: AL — байт (в случае ошибки AL = 0) ; CF = 1 — ошибка input_hex_byte: push dx ;Сохранение DX mov al,3 ;Ввод максимум 2 символов (FF) + конец строки call input_str ;Вызов процедуры ввода строки call str_to_hex_byte ;Преобразование строки в байт pop dx ;Восстановление DX ret
Полный исходный код примера: inputhex.asm. Как и в примере с десятичными числами, программа повторяет запрос ввода, пока не будут введены корректные данные:
Упражнение
Напишите программу для ввода байта с консоли в двоичном виде. Желательно с проверкой корректности ввода 🙂 Результаты можете писать в комментариях или на форуме.
Ещё раз ссылки на примеры:
- inputdec.asm — ввод десятичных чисел с консоли (со знаком и без)
- inputhex.asm — ввод шестнадцатеричных чисел с консоли
Следующая часть »
asmworld.ru
Ввод чисел в консольных приложениях на С++
Для решения задач на C++ в приложениях с консольным интерфейсом возникает необходимость корректного ввода чисел с возможностью исправления. Числовые значения могут быть целочисленными и вещественными (иметь десятичную дробь), положительными и отрицательными.В данной статье рассматриваются две функций, одна из которых служит для ввода только целых положительных чисел, а другая функция позволяет ввести число с плавающей точкой и знаком «минус». Обе функции позволяют корректировать вводимые числа.Максимально-допустимые значения чисел, которые можно ввести с помощью этих функций, ограничены в одном случае максимальным значением 32-разрядного целого числа без знака, а в другом случае — длиной строки.Реализация этих функций в Visual C++ 2005 выглядит так:
#include "stdafx.h" #include <conio.h> #include <limits.h> unsigned InputInteger() { const int _key_back (0x08); const int _key_enter (0x0D); _TCHAR text[16] = _T(""), limit[16]; size_t max_len = _stprintf_s(limit, _T("%u"), UINT_MAX); // int pos = 0; bool _exit = false; while (!_kbhit() && !_exit) { int ch = _gettch(); if (pos == max_len && ch != _key_back && ch != _key_enter) continue; // switch (ch) { case _key_enter : // Enter _exit = true; break; case _key_back : // Back if (pos > 0) { text[--pos] = '\0'; _tprintf(_T("\b \b")); } break; default : // Any key if (_istdigit(ch) > 0) { text[pos++] = ch, text[pos] = '\0'; if ((pos == max_len) && (_tcscmp(text, limit) > 0)) { text[--pos] = '\0'; } else { _tprintf(_T("%c"), ch); } } break; } } // unsigned result = 0; _stscanf_s(text, _T("%u"), &result); return result; } double InputDouble() { const int _key_back (0x08); const int _key_enter (0x0D); int p = 0; bool end_line = false; TCHAR _str[32] = _T(""); int max_len = sizeof(_str)/sizeof(TCHAR)-1; // while (!end_line) { int ch = _gettch(); if (p == max_len && ch != _key_enter && ch != _key_back) continue; if (ch == '.' && _tcschr(_str, '.') != NULL) continue; if (ch == '-' && _str[0] != '\0') continue; switch (ch) { case _key_enter : end_line = true; break; case _key_back : if (p > 0) { _str[--p] = '\0'; _tprintf(_T("\b \b")); } break; default: if (_istdigit(ch) > 0 || ch == '.' || ch == '-') { _str[p++] = ch; _str[p] = '\0'; if (p == max_len) { _str[--p] = '\0'; } else { _tprintf(_T("%c"), ch); } } break; } } // return _tstof(_str); } int _tmain(int argc, _TCHAR* argv[]) { _cputts(_T("Ввод целого числа: ")); unsigned val = InputInteger(); _cputts(_T("\r\n")); _tcprintf(_T("Число = %d\r\n"), val); // _cputts(_T("Ввод дробного числа: ")); double num = InputDouble(); _cputts(_T("\r\n")); _tcprintf(_T("Число = %f\r\n"), num); // _gettch(); return 0; }
winmain.org
Ввод числа с начальными нулями
Ввод числа с начальными нулями ContentsСуществуют различные способы ввода целых чисел, начинающихся с нуля.
Введите числа в виде текста. Самый простой способ — поставить перед числом апостроф (например, ‘0987). Апостроф не отображается в ячейке, а число будет отформатировано как текст. Но из-за текстового формата с этим числом нельзя выполнять вычисления.
Отформатируйте ячейку с использованием числового формата, например, \0000. Этот формат может быть назначен в поле Код формата на вкладке Формат — Ячейки — Числа. Он определяет отображение ячейки по правилу: «сначала всегда ставится нуль, а затем значащие цифры, которым отводится не менее трёх мест, а если значащих цифр меньше трёх, вместо недостающих цифр слева ставятся нули».
Если нужно применить числовой формат к столбцу чисел, отформатированных текстовым форматом (например, преобразовать текст «000123» в число «123»), выполните следующие действия.
Выберите столбец с числами в текстовом формате. Измените формат ячеек в том столбце на формат «Число».
Выберите команду Правка — Найти и заменить
In the Find box, enter ^[0-9]
In the Replace box, enter &
Установите флажок Регулярные выражения
Выберите Только текущий выбор
Нажмите кнопку Заменить все
Impressum (Legal Info) | Privacy Policy | Statutes (non-binding English translation) — Satzung (binding German version) | Copyright information: Unless otherwise specified, all text and images on this website are licensed under the Mozilla Public License v2.0. “LibreOffice” and “The Document Foundation” are registered trademarks of their corresponding registered owners or are in actual use as trademarks in one or more countries. Their respective logos and icons are also subject to international copyright laws. Use thereof is explained in our trademark policy. LibreOffice was based on OpenOffice.org.
help.libreoffice.org
Ввод чисел | htmlbook.ru
Для ввода чисел предназначено специальное поле, которое допускает ограничения по нижней и верхней границе, а также устанавливает шаг приращения. Само поле для ввода чисел похоже на обычное текстовое поле, но со стрелками, которые позволяют увеличивать и уменьшать значение (рис. 1).
Рис. 1. Вид поля для ввода чисел
Синтаксис создания поля следующий:
<input type="number" атрибуты>
Допустимые атрибуты перечислены в табл. 1.
Атрибут | Описание |
---|---|
min | Минимальное значение. |
max | Максимальное значение. |
size | Ширина поля. |
step | Шаг приращения числа. Может быть как целым (2), так и дробным (0.2). |
name | Имя поля, предназначено для того, чтобы обработчик формы мог его идентифицировать. |
value | Начальное число, которое выводится в поле. |
Для ограничения введённого числа предназначены атрибуты min и max, они могут принимать отрицательное и положительное значение. При достижении верхнего или нижнего порога стрелки в поле в зависимости от браузера блокируются или не дают никакого эффекта (пример 1). Несмотря на такие запреты, в любом случае в поле самостоятельно можно вводить любые значения, включая текст. Атрибуты min и max работают только при использовании стрелок в поле.
Пример 1. Ограничение ввода чисел
HTML5IECrOpSaFx
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Ввод числа</title>
</head>
<body>
<form action="handler.php">
<p>Введите число от 1 до 10:</p>
<p><input type="number" size="3" name="num" min="1" max="10" value="1"></p>
</form>
</body>
</html>
Если значение min превышает max, то атрибут min игнорируется.
Атрибут step задаёт шаг приращения и по умолчанию равен 1. В то же время значение может быть и дробным числом, как показано в примере 2.
Пример 2. Шаг приращения
HTML5IECrOpSaFx
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Ввод числа</title>
</head>
<body>
<form action="handler.php">
<p>Укажите нормальную среднюю температуру человека:</p>
<p><input type="number" name="t" value="35" min="35" max="40" step="0.2"></p>
</form>
</body>
</html>
Результат примера продемонстрирован на рис. 2.
Рис. 2. Ввод дробных чисел в поле
Браузеры плохо поддерживают это поле, пока лишь это делает Chrome и Opera. В остальных браузерах поле для ввода числа приобретает вид обычного текстового поля.
htmlbook.ru
Ввод числа с начальными нулями
Ввод числа с начальными нулями СодержаниеСуществуют различные способы ввода целых чисел, начинающихся с нуля.
Введите числа в виде текста. Самый простой способ — поставить перед числом апостроф (например, ‘0987). Апостроф не отображается в ячейке, а число будет отформатировано как текст. Но из-за текстового формата с этим числом нельзя выполнять вычисления.
Отформатируйте ячейку с использованием числового формата, например, \0000. Этот формат может быть назначен в поле Код формата на вкладке Формат — Ячейки — Числа. Он определяет отображение ячейки по правилу: «сначала всегда ставится нуль, а затем значащие цифры, которым отводится не менее трёх мест, а если значащих цифр меньше трёх, вместо недостающих цифр слева ставятся нули».
Если нужно применить числовой формат к столбцу чисел, отформатированных текстовым форматом (например, преобразовать текст «000123» в число «123»), выполните следующие действия.
Выберите столбец с числами в текстовом формате. Измените формат ячеек в том столбце на формат «Число».
Выберите команду Правка — Найти и заменить
In the Find box, enter ^[0-9]
In the Replace box, enter &
Установите флажок Регулярные выражения
Выберите Только текущий выбор
Нажмите кнопку Заменить все
Impressum (Legal Info) | Privacy Policy | Statutes (non-binding English translation) — Satzung (binding German version) | Copyright information: Unless otherwise specified, all text and images on this website are licensed under the Mozilla Public License v2.0. “LibreOffice” and “The Document Foundation” are registered trademarks of their corresponding registered owners or are in actual use as trademarks in one or more countries. Their respective logos and icons are also subject to international copyright laws. Use thereof is explained in our trademark policy. LibreOffice was based on OpenOffice.org.
help.libreoffice.org
Ввод числа с начальными нулями
Ввод числа с начальными нулямиLibreOffice 5.4 Help
Язык ▼English (USA)አማርኛالعربيةAsturianuБългарскиবাংলাবাংলাབོད་ཡིག / Bod skadBosanskiCatalàCatalà-ValenciaČeskyDanskDeutsch ཇོང་ཁΕλληνικάEnglish (GB)English (ZA)EsperantoEspañolEestiEuskaraSuomiFrançaisGalegoગુજરાતીעבריתहिन्दीHrvatskiMagyarBahasa IndonesiaÍslenskaItaliano日本語ქართულიភាសាខ្មែរ한국어ລາວLietuviųLatviešuМакедонскиNorsk (bokmål / riksmål)नेपालीNederlandsNorsk (nynorsk)OromooPolskiPortuguêsPortuguês do BrasilRomânăРусскийසිංහලSidámo ‘AfóSlovenčinaSlovenščinaShqipSvenskaதமிழ்ТоҷикӣTürkçeئۇيغۇرچەУкраїнськаTiếng Việt中文 (简体字)中文 (正體字) Индекс / УказательCALC
CHART
WRITER
DRAW
IMPRESS
MATH
BASE
BASIC
GLOBAL
Существуют различные способы ввода целых чисел, начинающихся с нуля.
Введите числа в виде текста. Самый простой способ — поставить перед числом апостроф (например, ‘0987). Апостроф не отображается в ячейке, а число будет отформатировано как текст. Но из-за текстового формата с этим числом нельзя выполнять вычисления.
Отформатируйте ячейку с использованием числового формата, например, \0000. Этот формат может быть назначен в поле Код формата на вкладке Формат — Ячейки — Числа. Он определяет отображение ячейки по правилу: «сначала всегда ставится нуль, а затем значащие цифры, которым отводится не менее трёх мест, а если значащих цифр меньше трёх, вместо недостающих цифр слева ставятся нули».
Если нужно применить числовой формат к столбцу чисел, отформатированных текстовым форматом (например, преобразовать текст «000123» в число «123»), выполните следующие действия.
Выберите столбец с числами в текстовом формате. Измените формат ячеек в том столбце на формат «Число».
Выберите команду Правка — Найти и заменить
In the Find box, enter ^[0-9]
In the Replace box, enter &
Установите флажок Регулярные выражения
Выберите Только текущий выбор
Нажмите кнопку Заменить все
Impressum (Legal Info) | Privacy Policy | Statutes (non-binding English translation) — Satzung (binding German version) | Copyright information: Unless otherwise specified, all text and images on this website are licensed under the Mozilla Public License v2.0. “LibreOffice” and “The Document Foundation” are registered trademarks of their corresponding registered owners or are in actual use as trademarks in one or more countries. Their respective logos and icons are also subject to international copyright laws. Use thereof is explained in our trademark policy. LibreOffice was based on OpenOffice.org.
help.libreoffice.org