Я работал над этой функцией Happy
, чтобы попрактиковаться в потоке управления. Happy
проверяет, является ли число счастливым. Я также пытался научиться обработке ошибок. Итак, я попытался уловить, является ли пользовательский ввод чем-то другим, кроме целого числа. Особенно, если ввод - это строка. Для этого я попытался включить скалярный тест здесь, но я не смог протестировать его в редакторе, потому что, если я попытаюсь ввести любые буквы без кавычек, я, конечно же, получу VALUE ERROR: Undefined name
.
Также книга Освоение APL предупреждает об использовании Quad для ввода данных.
Как правильно проверить, является ли ввод строкой? Предполагаю, что пользователь будет вводить буквы без кавычек.
(Я использую Dyalog APL 17.0)
(Я взял код о том, как разбить число на цифры из здесь?)
Happy
'Enter a Number'
N←⎕
N2←N
:If N<0
N←|N
'You entered'N2
'Only positive numbers can be happy'
'We will check if'N'is happy'
N2←N
:EndIf
f←10⊥⍣¯1⊢
D←f N
N←+/D×D
⍝:If 0≢⊃0⍴⊂N
⍝:OrIf N≢⌊N
⍝ 'You entered: 'N'Enter an integer'
⍝ →0
⍝:EndIf
:If N=1
'***************'
'Yes'N2'is happy!'
'***************'
:Else
:While N≠1
N←+/D×D
D←f N
N←+/D×D
'N is:'N
:If N=4
'**********************************'
'Sorry!'N2'is not a happy number'
'**********************************'
:Leave
:EndIf
:If N=1
'**********************'
'Yes!'N2'is a happy number'
'**********************'
:EndIf
:EndWhile
:EndIf
Обновленный ответ
Без лишних слов, вот предлагаемое решение:
Happy;ok;N;N2
'Enter a Number'
ok←0
:While ~ok
N2←N←⍞ ⍝ N2=original input
ok←∧/N∊⎕D,'¯.' ⍝ allow high minus for negatives and decimal separator
(~ok)/'Please enter numeric data!'
:EndWhile
N←2⊃⎕VFI N ⍝ result of ⍞ will be text, so make it numeric
N←⍬⍴N ⍝ make it a scalar
:If N<0
N←|N
'You entered'N2
'Only positive numbers can be happy'
'We will check if'N'is happy'
N2←N
:EndIf
f←10⊥⍣¯1⊢
D←f N
N←+/D×D
:If N=1
'***************'
'Yes'N2'is happy!'
'***************'
:Else
:While N≠1
N←+/D×D
D←f N
N←+/D×D
'N is:'N
:If N=4
'**********************************'
'Sorry!'N2'is not a happy number'
'**********************************'
:Leave
:EndIf
:If N=1
'**********************'
'Yes!'N2'is a happy number'
'**********************'
:EndIf
:EndWhile
:EndIf
Замечания
Legrand прав в том, что не использует ⎕
, вместо этого используйте ⍞
. Это дает вам "непереведенную" строку, чтобы вы могли с ней работать. Использование системы для оценки пользовательского ввода (без отлова ошибок) может открыть двери для всех видов атак. (Документация здесь)
Я использовал ⎕VFI
(который, я думаю, является специфической для Dyalog системной функцией), который проверяет ввод. Это предпочтительнее ⍎
, который (опять же) может открывать двери ... (Документация здесь])
Я был сбит с толку, значит, это не тот D, который я использовал в функции как D←fN
, где я вычисляю цифры N?
хорошо, я ответил со своего телефона ... но я вижу дополнительные вещи, о которых следует упомянуть. Обновлю свой теплый сегодня же;)
хорошо спасибо. Я пробовал. Он работает, но также улавливает числа, а остальная часть функции не выполняется.
Спасибо! Я изучаю твой ответ. Итак, я подумал, что Quote Quade принимает только строковый ввод. Но я вижу, что пользователь может вводить числовые значения, но Quote Quade преобразует его в строку: chars ← ⍞ 123 символа 123 + / chars DOMAIN ERROR.
Вы должны использовать ⍞
(Ввод символов; документация), а не ⎕
. ⍞
предоставит вам буквальный текст, введенный пользователем.
input←⍞
Затем вы можете использовать ⎕VFI
(Проверить и исправить ввод; документация) в результате, чтобы проверить числовой ввод. Это даст вам вектор из двух векторов. Первый логический и указывается для каждого «слова» в аргументе. Второй вектор - числовой, содержащий одно число на слово. Недействительные слова становятся нулевыми.
(valid values)←⎕VFI input
Итак, если вы ищете одно число, проверьте вектор действительности, а затем вы можете проверить, является ли он целым числом:
:If valid≢,1
:OrIf values≢⌊values
'You entered: 'N'Enter an integer'
→0
:EndIf
Наконец, вы можете извлечь N
:
N←⊃values
;
.:Else
для остальной части программы вместо →0
, чтобы избежать скачков.:Leave
, изменив :EndWhile
на :Until N=4
.,
), а не скручивайте (совмещая) его.⎕←
, чтобы упростить поиск и повысить четкость.Happy;input;valid;values;N;N2;f;D ⎕←'Enter a Number' input←⍞ (valid values)←⎕VFI input :If valid≡,1 :AndIf values≡⌊values N←⊃values N2←N :If N<0 N←|N ⎕←'You entered',N2 ⎕←'Only positive numbers can be happy' ⎕←'We will check if',N,'is happy' N2←N :EndIf f←10⊥⍣¯1⊢ D←f N N←+/D×D :If N=1 ⎕←'***************' ⎕←'Yes',N2,'is happy!' ⎕←'***************' :Else :While N≠1 N←+/D×D D←f N N←+/D×D ⎕←'N is:',N :If N=4 ⎕←'**********************************' ⎕←'Sorry!',N2,'is not a happy number' ⎕←'**********************************' :EndIf :If N=1 ⎕←'**********************' ⎕←'Yes!',N2,'is a happy number' ⎕←'**********************' :EndIf :Until N=4 :EndIf :Else ⎕←'You entered: ',input,' Enter an integer' :EndIf
Замечательно! Спасибо. Особенно за советы, не относящиеся к делу. Я завтра внимательно прочитаю.
«Цифры». Также есть {Quad} A для "Alphabet"