1

Тема: Read/ReadLn

Реализация Read/ReadLn в System выглядит следующим образом:

function _ReadChar(var t: TTextRec): Char;
function _ReadLong(var t: TTextRec): Longint;
procedure _ReadString(var t: TTextRec; s: PShortString; maxLen: Longint);
procedure _ReadCString(var t: TTextRec; s: PChar; maxLen: Longint);
procedure _ReadLString(var t: TTextRec; var s: AnsiString);
procedure _ReadWString(var t: TTextRec; var s: WideString);
procedure _ReadWCString(var t: TTextRec; s: PWideChar; maxBytes: Longint);
function _ReadWChar(var t: TTextRec): WideChar;
function _ReadExt(var t: TTextRec): Extended;
procedure _ReadLn(var t: TTextRec);

Процедура ReadLn здесь одна. Если вспомнить, как работает стандартный ввод в Паскале, это видится логичным:

var
  A, B, C: Integer;
begin
  Read(A, B); // числа через пробел
  ReadLn(C);  // число на той же строке через пробел, затем перевод строки
end;

Если уж говорить про совместимость, должно быть реализовано именно так. Похоже, ввод придется делать через GetCh консоли. Я за это не берусь.

2 (изменено: Freeman, 05.12.2020 в 18:37)

Re: Read/ReadLn

Freeman пишет:

Процедура ReadLn здесь одна. Если вспомнить, как работает стандартный ввод в Паскале, это видится логичным:

Получается, что реальный ввод происходит после ReadLn.

Например, такой код

program test;

{$APPTYPE CONSOLE}

var
  A, B, C: Integer;
begin
  Read(A, B); // числа через пробел
  Write(A, ' ', B);
  ReadLn(C);  // число на той же строке через пробел, затем перевод строки
  Write(' ', C);
  ReadLn;
end.

Полный ввод произойдёт после ввода конца строки

misc.php?action=pun_attachment&item=41&download=0

Freeman пишет:

Похоже, ввод придется делать через GetCh консоли.

Когда я делал модуль InOut для XDS Modula-2/Oberon-2 compiler, то там я реализовал всё через GetS, даже если вводится только Char.

Вот модуль InOut
EXTERN LoadLibrary    ; in DLL.asm
EXTERN GetProcAddress ; in DLL.asm
EXTERN X2C_HALT       ; in X2C.asm

GLOBAL InOut_BEGIN
GLOBAL InOut_Write
GLOBAL InOut_WriteLn
GLOBAL InOut_WriteInt
GLOBAL InOut_WriteCard
GLOBAL InOut_WriteString
GLOBAL InOut_Read
GLOBAL InOut_ReadCard
GLOBAL InOut_ReadString

READ_BUFFER_SIZE equ 80

SECTION .text
; ---------------------------------------------------------------------------- ;
InOut_BEGIN:
        push   ebx
        push   esi
        push   edi

        push   dword sz_console
        call   LoadLibrary
        mov    ecx, eax
        mov    ebx, GetProcAddress

        push   ecx
        push   dword sz_con_init
        call   ebx
        mov    [con_init], eax

        push   ecx
        push   dword sz_con_printf
        call   ebx
        mov    [con_printf], eax

        push   ecx
        push   dword sz_con_gets
        call   ebx
        mov    [con_gets], eax

        push   dword [32]
        push   -1
        push   -1
        push   -1
        push   -1
        call   [con_init]

        pop    edi
        pop    esi
        pop    ebx

        ret
; ---------------------------------------------------------------------------- ;
; PROCEDURE WriteString(v: ARRAY OF CHAR);
InOut_WriteString:
        push   ebx
        push   esi
        push   edi

        push   dword 0
        push   dword [esp + 4 + 4*4]
        call   [con_printf]
        add    esp, 8

        pop    edi
        pop    esi
        pop    ebx

        ret    8
; ---------------------------------------------------------------------------- ;
; PROCEDURE WriteInt(v: INTEGER;  w: CARDINAL);
InOut_WriteInt:
        push   ebx
        push   esi
        push   edi

        push   dword [esp + 4 + 3*4]
        push   dword [esp + 8 + 4*4]
        push   dword sz_format_int
        call   [con_printf]
        add    esp, 12

        pop    edi
        pop    esi
        pop    ebx

        ret    8
; ---------------------------------------------------------------------------- ;
; PROCEDURE WriteLn;
InOut_WriteLn:
        push   dword 0
        push   dword sz_end_of_line
        call   InOut_WriteString
        ret
; ---------------------------------------------------------------------------- ;
; PROCEDURE Write(v: CHAR);
InOut_Write:
        push   ebx
        push   esi
        push   edi

        push   dword [esp + 4 + 3*4]
        push   dword sz_format_char
        call   [con_printf]
        add    esp, 8

        pop    edi
        pop    esi
        pop    ebx

        ret    4
; ---------------------------------------------------------------------------- ;
; PROCEDURE WriteCard(v: CARDINAL; w: CARDINAL);
InOut_WriteCard:
        push   ebx
        push   esi
        push   edi

        push   dword [esp + 4 + 3*4]
        push   dword [esp + 8 + 4*4]
        push   dword sz_format_card
        call   [con_printf]
        add    esp, 12

        pop    edi
        pop    esi
        pop    ebx

        ret    8
; ---------------------------------------------------------------------------- ;
; PROCEDURE Read(VAR v: CHAR);
InOut_Read:
        push   ebx
        push   esi
        push   edi

        mov    esi, [PtrInReadBuffer]
        lodsb
        test   al, al
        jnz    .read_buffer_not_empty

        mov    [PtrInReadBuffer], dword ReadBuffer

        push   dword READ_BUFFER_SIZE
        push   dword ReadBuffer
        call   [con_gets]
        test   eax, eax
        jz     X2C_HALT

        mov    esi, ReadBuffer
        lodsb

.read_buffer_not_empty:
        mov    edi, [esp + 4 + 3*4]
        stosb

        inc    dword [PtrInReadBuffer]

        pop    edi
        pop    esi
        pop    ebx

        ret    4
; ---------------------------------------------------------------------------- ;
; PROCEDURE ReadCard(VAR v: CARDINAL);
InOut_ReadCard:
        push   ebx
        push   esi
        push   edi

        mov    ebx, [esp + 4 + 3*4]

        push   ebp
        mov    ebp, esp
        sub    esp, 16

        lea     edi, [esp]
        mov     ecx, 16
        xor     al, al
        rep stosb

        push    dword 16
        lea     esi, [esp - 1*4]
        push    esi
        call    InOut_ReadString

        xor     ecx, ecx
        xor     eax, eax
.next:
        lodsb
        sub    al, 48
        cmp    al, 9
        jnbe   .done
        lea    ecx, [ecx + ecx * 4]
        lea    ecx, [eax + ecx * 2]
        jmp    .next
.done:

        mov    [ebx], ecx

        mov    esp, ebp
        pop    ebp

        pop    edi
        pop    esi
        pop    ebx

        ret    4
; ---------------------------------------------------------------------------- ;
; PROCEDURE ReadString(VAR v: ARRAY OF CHAR);
InOut_ReadString:
        push   ebx
        push   esi
        push   edi

        mov    esi, [PtrInReadBuffer]
        lodsb
        test   al, al
        jnz    .read_buffer_not_empty

        mov    [PtrInReadBuffer], dword ReadBuffer

        push   dword READ_BUFFER_SIZE
        push   dword ReadBuffer
        call   [con_gets]
        test   eax, eax
        jz     X2C_HALT

        mov    esi, ReadBuffer
        lodsb

.read_buffer_not_empty:
        mov    edi, [esp + 4 + 3*4]
        mov    ecx, [esp + 8 + 3*4]
.skip:
        inc    dword [PtrInReadBuffer]
        jcxz   .done
        test   al, al
        jz     .done
        cmp    al, " "
        jnbe   .next
        dec    ecx
        lodsb
        jmp    .skip
.next:
        jcxz   .done
        stosb
        cmp    al, " "
        jbe    .done
        dec    ecx
        lodsb
        inc    dword [PtrInReadBuffer]
        jmp    .next
.done:
        mov    [edi], byte 0

        pop    edi
        pop    esi
        pop    ebx

        ret    8


SECTION .data
; ---------------------------------------------------------------------------- ;
sz_end_of_line      db 10,0
sz_format_int       db "%*ld",0
sz_format_char      db "%c",0
sz_format_card      db "%*u",0
; ---------------------------------------------------------------------------- ;
sz_con_init         db "con_init",0
sz_con_printf       db "con_printf",0
sz_con_gets         db "con_gets",0
sz_console          db "/sys/lib/console.obj",0
; ---------------------------------------------------------------------------- ;
con_init            dd 0
con_printf          dd 0
con_gets            dd 0
; ---------------------------------------------------------------------------- ;
PtrInReadBuffer     dd ReadBuffer
ReadBuffer:       resb READ_BUFFER_SIZE

В этом модуле существует внутренний буфер ReadBuffer размером READ_BUFFER_SIZE.
В этот буфер происходит чтение с помощью функции GetS, а затем уже мы обрабатываем(например, конвертируем строку в число) то, что было введено в этот буфер.
Аналогичным образом предлагаю сделать и здесь.

Freeman пишет:

While console I/O procedures still non-standard

Как минимум функцию Write уже можно перенести в System и сделать стандартной.
По поводу WriteExt\ReadExt — в библиотеке Console в KolibriOS не поддерживается ввод\вывод чисел с плавающей точкой посредством встроенных функций, нужно самим делать дополнительно код конвертации(хотя лучше бы он был в системной библиотеке).
ReadLString — для длинных строк ещё нужен менеджер памяти.

Post's attachments

1.PNG, 1.73 Кб, 238 x 97
1.PNG 1.73 Кб, 73 скачиваний с 2020-06-24