Ввод нецелого числа в целое число без знака с помощью scanf в NASM, вызывающее проблемы в циклах - PullRequest
0 голосов
/ 19 сентября 2018

Всякий раз, когда я пытаюсь ввести букву или символ в моем scanf для целых чисел без знака после предварительного ввода принятого числа ранее в цикле, он непрерывно вводит предыдущее число, вызывая бесконечную работу программы.Как это исправить?Вот пример кода, который я написал:

[bits 32]

global _main

extern _scanf
extern _printf

section .data
    prompt_number db "Please select a number. Enter 0 to escape. ", 0
    display_number db "You entered %u. ", 0
    number_fmt db "%u", 0
    number_input dd 0

section .bss

section .text
_main:
    push ebp
    mov ebp, esp
    and esp, 0xfffffff0

_Label:

    sub   esp, 16
    mov   dword[esp], prompt_number
    call  _printf
    add   esp, 16

    sub esp, 16
    mov dword[esp], number_fmt
    mov dword[esp+4], number_input
    call _scanf
    add esp, 16

    sub esp, 16
    mov dword[esp], display_number
    mov eax, [number_input]
    mov dword[esp+4], eax
    call _printf
    add esp, 16

    cmp dword[number_input], 0
    jne _Label

    mov   esp, ebp
    mov   eax, 1
    pop   ebp
ret 

1 Ответ

0 голосов
/ 19 сентября 2018

Это связано с тем, как scanf работает в этих условиях, и решение состоит в том, чтобы портировать одно из предложенных решений для Хороший способ очистить буфер scanf, когда введена неверная запись из C.

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

Ниже приведена быстрая попытка портировать первое решение (используя getchar для использования буфера).Я не могу ручаться за его качество;в основном это мой первый прогон сборки программ:

[bits 32]

global _main

extern _getchar
extern _scanf
extern _printf

section .data
    prompt_number   db "Please select a number. Enter 0 to escape. ", 0
    display_number  db "You entered %u. ", 0
    scan_error      db "Error scanning input. ", 0
    number_fmt      db "%u", 0
    number_input    dd 0

section .bss

section .text
_main:
    push  ebp
    mov   ebp, esp
    and   esp, 0xfffffff0

_Label:

    sub   esp, 16
    mov   dword[esp], prompt_number
    call  _printf
    add   esp, 16

    sub   esp, 16
    mov   dword[esp], number_fmt
    mov   dword[esp+4], number_input
    call  _scanf
    add   esp, 16

    cmp   eax, 0
    jne    _ScanSuccess

_ScanError:
    sub   esp, 16
    mov   dword[esp], scan_error
    call  _printf
    add   esp, 16

_ScanErrorConsumeInput:
    sub   esp, 16
    call  _getchar
    add   esp, 16

    cmp   eax, -1   ; most common value indicating end-of-file
    je    _Label

    cmp   eax, 10   ; newline in ASCII
    je    _Label

    jmp   _ScanErrorConsumeInput

_ScanSuccess:
    sub   esp, 16
    mov   dword[esp], display_number
    mov   eax, [number_input]
    mov   dword[esp+4], eax
    call  _printf
    add   esp, 16

    cmp   dword[number_input], 0
    jne   _Label

_Return:
    mov   esp, ebp
    mov   eax, 1
    pop   ebp
    ret
...