LINUX.ORG.RU

Pascal системы исчисления

 


1

1

Подскажите, как реализовать в данной процедуре возможность выбора разных систем исчисления, в которой она также сможет делать посимвольный ввод?

procedure ReadLongint (var success : boolean; var result : longin);
var
   c   : char;
   res : longint;
   pos :  integer;
begin
   res := 0;
   pos := 0;
   repeat
      read(c);
      pos := pos + 1
   until (c <> ' ') and (c <> #10);
   while (c <> ' ') and (c <> #10) do
   begin
      if (c < '0') or (c > '9') then
      begin
	 writeln('Unexpected ''', c, ''''' in pos: ', pos);
	 readln;
	 success := false;
	 exit
      end;
      res := res*10 + ord(c) - ord('0');
      read(c);
      pos := pos + 1
   end;
   result := res;
   success := true
  end;


Последнее исправление: maxcom (всего исправлений: 2)

Возьмите в руки бумажку, запишите алгоритм работы желаемой программы в виде блок-схемы, разбейте его на подпункты если какой-то пункт не понятен / слишком общими словами написан. Для грязной реализации того что хотите, достаточно инструкций read, if и прочих с приведённого вами куска кода, не более. Так что вперёд, а вот по ходу дела уже можете спрашивать, что конкретно не получается и какие усилия вы предприняли чтобы самостоятельно решить вашу задачу. Ну или в job, там сделают в лучшем виде.

mydibyje ★★★
()
Последнее исправление: mydibyje (всего исправлений: 1)

В этом коде, очевидно, есть константа, ответственная за основание системы счисления. Она используется в двух местах - при проверке диапазона очередной введённой цифры и при сдвиге результата на один разряд для добавления очередной цифры. Найди, пожалуйста, эти места. Сделай так чтобы в обоих значение участвовало явно. Затем вынеси его а аргумент.

slovazap ★★★★★
()

Лучше так:

function ReadLongint(var Res: Longint): Boolean;
var
  pos: Integer;
begin
  ReadLongint := False;
  res := 0;
  pos := 0;
  repeat
    Read(c);
    Inc(Pos);
  until c <= ' ';


Но на случай 16-ричного ввода, имейте в виду, что ReadLn уже умеет читать не только десятичные, но и 16-ричные значения, только вводить их нужно с префиксом '$'.

bormant ★★★★★
()
Ответ на: комментарий от Virtuos86

Ты до ерунды прикопался. Куча языков регистронезависимы, есть даже таблица в вики Чувствительность к регистру символов Это не хорошо и не плохо, есть свои преимущества и недостатки у обоих подходов. Но в пределах одной программы все же хорошим тоном, в том числе и в Паскале, является сохранение стиля. То есть, если назвал переменную pos, ее желательно так везде и именовать.

praseodim ★★★★★
()
Ответ на: комментарий от praseodim

Ты до ерунды прикопался. Куча языков регистронезависимы, есть даже таблица в вики Чувствительность к регистру символов Это не хорошо и не плохо, есть свои преимущества и недостатки у обоих подходов.

Правда? И какие же есть плюсы? А также в каком серьезном языке программирования (то есть не для фанбоев) есть такая «фича»?

Но в пределах одной программы все же хорошим тоном, в том числе и в Паскале, является сохранение стиля. То есть, если назвал переменную pos, ее желательно так везде и именовать.

Любопытно, но мне кажется, что ты «переобуваешься» в пределах одного комментария.

Virtuos86 ★★★★★
()
Ответ на: комментарий от Virtuos86

Объективно там нечего не осиливать.

Совершенно верно. И при том постоянно находится кто-нибудь, кто вылезет и обгадится на ровном месте; и вот так вот последние 50 лет, задолбало.

Это и удивляет. Ребус-кроксворд. (q) Место проклятое (q)

bormant ★★★★★
()
Последнее исправление: bormant (всего исправлений: 1)
Ответ на: комментарий от Virtuos86

Это Вы сейчас SQL с ассемблером устаревшими назвали?

Подавляющее большинство актуальных языков программирования созданы в период c 1969-го года по 2000-й год. И даже наиболее актуальный некомпилируемый язык программирования - Python - появился в 1991-м году, 31 год назад.

saahriktu ★★★★★
()
Ответ на: комментарий от saahriktu

Это Вы сейчас SQL с ассемблером устаревшими назвали?

Сиквел это вещь в себе, а асм это не ЯП по нынешним меркам - в том плане, что на нем не то что не пишут, на нем нечего писать сейчас ручками живым кодерам.

Virtuos86 ★★★★★
()
Ответ на: комментарий от pihter
procedure ReadLongint (var success : boolean; var result : longint; var notation : char);
var
   c   : char;
   res : longint;
   pos :  integer;
begin
   res := 0;
   pos := 0;
   repeat
      read(c);
      pos := pos + 1
   until (c <> ' ') and (c <> #10);
   while (c <> ' ') and (c <> #10) do
   begin
          
       if (notation > #48) and (notation < #58) then
       begin
	 res := res*10 + ord(c) - ord('0');
       end;
       if (notation > #64) and (notation < #91) then
       begin
	  res := res*10 + ord(c) - ord('0');?????
       end;
      read(c);
      pos := pos + 1;
   end;
   result := res;
   success := true
   end;

Подскажите, допустим система исчисления определяется параметром. В случае от 2 до 10 один и тот же принцип прочтения. А как посимвольно прочесть, дальше? от A до Z? Поставил знаки вопроса.

ilyaGor
() автор топика
Ответ на: комментарий от ilyaGor

А как посимвольно прочесть, дальше? от A до Z? Поставил знаки вопроса.

Ты же считываешь символ.

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

Ты лгоритм работы этой функции понимаешь? Можешь мне объяснить зачем каждая строчка?

pihter ★★★★★
()
Ответ на: комментарий от pihter

Каждая строчка:

procedure ReadLongint (var success : boolean; var result : longint; var notation : char);   //Принимаю указанные параметры
var
   c   : char;         // чар через который будем вводить символ
   res : longint;      // численное значение будущей записи        
   pos :  integer;     // номер вводимого символа
begin                  
   res := 0;           // обнуляем
   pos := 0;           // обнуляем
   repeat
      read(c);         // читаем символ
      pos := pos + 1   
   until (c <> ' ') and (c <> #10);  //условие не таб и не пробел
   while (c <> ' ') and (c <> #10) do
   begin
          
       if (notation > #48) and (notation < #58) then
       begin
	 res := res*10 + ord(c) - ord('0');  // вот здесь эта константа 10 так понимаю?
       end;
       if (notation > #64) and (notation < #91) then
       begin
	  res := res*10 + ord(c) - ord('0');?????
       end;
      read(c);
      pos := pos + 1;
   end;
   result := res;
   success := true
   end;
ilyaGor
() автор топика
Ответ на: комментарий от ilyaGor

Если res*10+нечто, то нечто 0..9 ;)
А для res:=res*base+нечто, нечто 0..base-1
Как кодировать то, что выше 9, зависит от принятых соглашений, обычно a..z регистронезависимо - 0..35; A..Z, a..z регистрозависимо - 0..61, ну и до 63 обычно бывает нужно (см. BASE64).
Регистронезависимый вариант соответственно:
res:=res*base+Ord(UpCase(c))-Ord('A')+10;
Регистрозависимый целиком:

case c of
'0'..'9': res:=res*base+Ord(c)-Ord('0');
'A'..'Z': res:=res*base+Ord(c)-Ord('A')+10;
'a'..'z': res:=res*base+Ord(c)-Ord('a')+36;
end;


PS. В BASE64 MIME «циферки» другие: A-0,a-26,0-52, +-62, /-63.

bormant ★★★★★
()
Последнее исправление: bormant (всего исправлений: 3)
Ответ на: комментарий от bormant

Спасибо за ваше решение. Я дико извиняюсь, вопрос может быть глупый, но я прям очень начинающий пока. base объявлять integer? В случае от 0 до 9 она должна быть 10, это понятно, а во втором и третьем случае какой делать?

ilyaGor
() автор топика
Ответ на: комментарий от Virtuos86

То-то я смотрю, плюсы никак не могут сделать модульность на уровне, хотя бы приближающемся к «устаревшему говну мамонта», только-только начали в C++20 внедрять, и оно толком не работает.

hobbit ★★★★★
()
Ответ на: комментарий от ilyaGor

во втором и третьем случае какой делать?

А оно не во втором и третьем ;) оно заранее должно быть понятно, что там в потоке ожидается, потому как
10(2) = 2
10(10) = 10
10(16) = 16
...

Поэтому нужно заранее определиться с входящим потоком. Например, стандартный Read/ReadLn паскалевый, читая из потока число, полагает, что если оно начинается с цифры 0..9 — десятичное, с $ — 16-ричное, т.е. определение по необязательному префиксу. В псевдокоде:

repeat Read(c) until c>' ';
Base:=10;
if c='$' then begin
  Base:=16; Read(c);
end;

Соответственно, необходимо добавить контроль на допустимые цифры, '0'..'9' для 10-го числа, '0'..'9','A'..'F' — для 16-го.

Если есть желание, можно усложнять в ту или иную сторону, добавить префиксов по вкусу; соответственно придется контролировать и варианты ввода. Если префиксов ожидается больше одного, есть смысл цифру считать отдельно — проще контролировать:
d:={...}; // в зависимости от режима 10, 16, еще какой-то
if d<Base then
  Res:=Res*Base+d
else {ошибка}

В вариантах выше база числа известна до вычитывания его цифр...

Вероятно, на стандартную процедуру ввода возлагать лишнего не совсем правильно — если программисту нужно больше обычного, пусть читает строку и сам разбирает под любые нестандартные хотелки.

bormant ★★★★★
()
Последнее исправление: bormant (всего исправлений: 1)
Ответ на: комментарий от bormant

Спасибо вам за такое подробное объяснение. Переписал с учётом того, что вы подсказали, насколько я вижу оно почти работает. Там снизу добавил основное тело программы, чтобы видеть, что числа выдаются. Если ввожу двузначное значение в параметр, который отвечает за систему исчисления, он передаёт второй символ сразу в следующий параметр. Подскажите как реализовать у этого параметра ввод двузначных?

procedure ReadLongint (var success : boolean; var base: integer; var result : longint; var notation : char);
var
   c	: char;
   res	: longint;
   pos	: integer;
begin
   res := 0;
   pos := 0;
   repeat
      read(c);
      pos := pos + 1
   until (c <> ' ') and (c <> #10);
   while (c <> ' ') and (c <> #10) do
   begin    
      case c of
        '0'..'9': res:=res*base+ord(c)-ord('0');
        'A'..'Z': res:=res*base+ord(c)-ord('A')+10;
        'a'..'z': res:=res*base+ord(c)-ord('a')+36;
       end;
   read(c);
   pos := pos + 1    
  
   end;
   result := res;
   success := true
end;

var
   x, y	: longint;
   n	: char;
   ok	: boolean;
   base	: integer;
begin
    repeat
       write('Please type scale of notation: ');
       read(n)
    until (n >' ');
    base:=10;
    if n='$' then begin
    base:=16;
    read(n);
    end;
    repeat
       write('Please type the first number: ');
       ReadLongint(ok, base, x, n)
    until ok;
    repeat
       write('Please type the second number: ');
       ReadLongint(ok, base,  y, n)
    until ok;
 writeln(x, ' times ', y, ' is ', x*y)
end.
ilyaGor
() автор топика
Последнее исправление: ilyaGor (всего исправлений: 1)
Ответ на: комментарий от Virtuos86

Я плюсовик, если иметь в виду, что c++ — мой основной инструмент для зарабатывания денег в течение уже многих лет (ну понятно, основные инструменты это мозг и глаза, но я про внешние). И я так не говорю.

hobbit ★★★★★
()
Ответ на: комментарий от pihter

Да и вообще java машина написана на плюсах. Компиляторы всех этих высокоуровневых языков на плюсах, все драйвера и все операционки. Это не выглядит как исчезающе малый процент.

ilyaGor
() автор топика
Ответ на: комментарий от ilyaGor

Первое впечатление: непрактично и сильно странно.

Вообще хорошо бы придерживаться правила: сперва ТЗ, потом код.

Допустим, нужно читать 10-е или 16-е (префикс '$') числа.
Вот ее и реализуем:

function ReadLong(var N: Longint): Boolean;
var
  Res: Longint;
  Base: Integer;
  c: Char;
begin
  ReadLong:=False;
  repeat Read(c)
  until c>' ';
  Base:=10; Res:=0;
  if c='$' then begin
    Base:=16; Read(c);
  end;
  while c>' ' do begin
    c:=UpCase(c);
    case c of
    '0'..'9':
      Res:=Res*Base+Ord(c)-Ord('0');
    'A'..'F':
      if base=16 then
        Res:=Res*Base+Ord(c)-Ord('A')+10
      else
        Exit;
    else
      Exit;
    end;
    Read(c);
  end;
  N:=Res;
  ReadLong:=True;
end;

var x, y: Longint;
begin
  WriteLn('Use prefix "$" for hexadecimal numbers.');
  repeat Write('x: ');
  until ReadLong(x);
  repeat Write('y: ');
  until ReadLong(y);
  WriteLn(x,' times ',y,' is ',x*y);
end.

Нужно что-то добавить: меняем ТЗ (обязательно до непротиворечивого состояния!), меняем код.

Но в целом, вот эта конкретная задача реализуется куда как проще:
var x, y: Longint;
begin
  WriteLn('Use prefix "$" for hexadecimal numbers.');
  repeat Write('x: '); Read(x);
  until IOResult=0;
  repeat Write('y: '); Read(y);
  until IOResult=0;
  WriteLn(x,' times ',y,' is ',x*y);
end.

bormant ★★★★★
()
Последнее исправление: bormant (всего исправлений: 2)
28 июня 2023 г.
Ответ на: комментарий от interrupted

В LORCODE тег в квадратных скобках [code=pascal], подробнее там:
www.linux.org.ru/help/lorcode.md

В markdown тег ```pascal, подробнее там:
www.linux.org.ru/help/markdown.md

bormant ★★★★★
()
Последнее исправление: bormant (всего исправлений: 1)