LINUX.ORG.RU

[Pascal] Как нормально реализовать аргументы в паскале?

 


0

1

Приходится потихоньку изучать паскаль. Недавно начал осваивать аргументы для программ. Нагуглил, нашел что-то по функциям paramcount и paramstr. Но как я не бьюсь не могу организовать аргументы. case видимо такое нечто как '--help': не понимает, ему цифры подавай. Это значит программе, надо цифрами аргументы давать?
Подскажите, как прикрутить к ней аргументы, вроде "--help", "-h" и подобных

★★★★

>Это значит программе, надо цифрами аргументы давать?

Это значит, что не надо использовать строки в case

slackwarrior ★★★★★
()
If (paramstr(1)='--help') or (paramstr(1)='-h') Then
Begin
 (* Вывод справки *)
End;
If (paramstr(1)='--write') or (paramstr(1)='-w') Then
Begin
 WriteValue := StrToInt(ParamStr(2));
 (* Записать какую-нибудь фигню на n значений *)
End;
AlexCones ★★★
()

Создай перечислимый тип, да пользуйся. Зачем там строки-то?

Axel
()
Ответ на: комментарий от baverman

Не писал. До того момента не писал. Это написал здесь и сейчас, что заметно по отсутствие кое-где CamelCase. Ибо мне без него плохеет.

AlexCones ★★★
()

И да, если хотите, чтобы параметры можно было указывать в разном порядке, нужно немного усложнить код:

Const
 MaxNumbersOfParameters = ...;

Var
 MoveAlong : LongBool = TRUE;
 N : Integer;

Begin
 For N := 1 To MaxNumberOfParameters Do
  Begin
   If (ParamStr(N)='--help') or (ParamStr(N)='-h') Then 
    Begin
     (* Вывод справки *)
    End;
   If (ParamStr(N)='--write') or (ParamStr(N)='-w') Then 
    Begin
     WriteValue := StrToInt(ParamStr(N+1));
      (* Записать какую-нибудь фигню на n значений *)
    End;
  End;

Ну и проверок там налепить типа если ParamStr(N+1) <> " etc.

AlexCones ★★★
()
Ответ на: комментарий от AlexCones
(* MoveAlong собственно задумывался как флаг выхода, забыл написать про него. *)
AlexCones ★★★
()
Ответ на: комментарий от nexfwall

Case может обслужить только перечислимые типы и char (который по сути есть byte). Можете городить костыль с написанием собственного case в виде функции, которая вернет Integer-число, получив AnsiString-команду.

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

>Да, забыл убрать дефисы

ЕМНИП, с дефисами оно и не заработает - перечислимые значения кажись имеют те же правила, что и именование переменных.

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

Тоесть, паскаль - не торт? Пора значит его закапывать. Я в своем любимом баше все решал на раз, с помощью case и shift. А тут получается, что нормально организовать аргументы нельзя..

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

>Тоесть, паскаль - не торт? Пора значит его закапывать.

А зачем вы его откопали?

А тут получается, что нормально организовать аргументы нельзя..


Можно, но через if-ы или костыль с ord и преобразованием.

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

А зачем вы его откопали?

Информатика в Колледже заставила его откопать. Думал нормальный язык, а оказывается

Можно, но через if-ы или костыль с ord и преобразованием.

Вот это вот и плохо

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

Не, не совсем затупил. Есть еще val. Срезаем дефисы со строки, преобразуем в перечислимый и используем case.

Axel
()
Ответ на: комментарий от nexfwall

Да, можно еще вот так изголяться:

Command := ParamStr(1);
C := Command[2];
Case C Of
 'w': (* Это '-w' *)
 'h': (* Это '-h' *)
 '-' : (* Здесь делаем еще одно такое же вложение для --help --write. *)

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

Все равно, вот как я сделал:

for	num := 1 to paramcount
		do	begin
			  if	(paramstr(num)='--help') or (paramstr(num)='-h')
			  then	begin
				  {help(); не реализовано еще}
				  halt(0);
				end;
			  if	(paramstr(num)='--calc-count') or (paramstr(num)='-c')
			  then	begin
				  mode:=1;
				  N:=paramstr(num+1);
				  continue
				end;
			  if	(paramstr(num)='--calc-num') or (paramstr(num)='-n')
			  then	begin
				  mode:=2;
				  N:=paramstr(num+1);
				  continue
				end;
			end;
Мне кажется что все правильно. Но компилятор арет:
calc_fibonacci.pas(73,10) Error: Incompatible types: got "ShortString" expected "SmallInt"
calc_fibonacci.pas(79,10) Error: Incompatible types: got "ShortString" expected "SmallInt"
Ну да, N имеет тип integer, так что плохая это была идея. Буду лучше откапывать перл или питон

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

>Тоесть, паскаль - не торт?

не слушай его. Он не шарит.

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

Ну, как-то так. Тока сперва я бы проверил тип.

И, да,

uses sysutils;

Axel
()
Ответ на: комментарий от nexfwall

>Не, не получается. Лучше уж оно останется закопанным

для bash все получается.

Или ты про паскаль? На нем тоже все получается.

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

Я паскаль имею ввиду. Слишком много с ним проблем.
Теперь оно говорит что не знает что есть getoptionvalue. Ты же не указал что оно юзает.

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

Да я вообще не кодер. :) Я так, погулять вышел.

Axel
()

В принципе, если очень чешется, можно использовать кейс, если параметров мало (и порядок фиксированный ;)). Если много - можно цикл по енуму.

//{$define USECASE}
uses
  SysUtils;
type
  TArgsTags = ( atHelp = 1,
                atCommand = 2 );
  TArgsValues = array[TArgsTags] of string;
  TArgsNames = array[1..2] of string;
  TArgs = array [TArgsTags] of TArgsNames;
  var
   CmdValues: TArgsValues;
  const
   CmdNames: TArgs = (('--help', '-h'),('--command','-c'));
   
  function GetTagByName(name: string): TArgsTags;
  var tag: TArgsTags;
  begin
   tag := atHelp;
   for tag := Low(TArgsTags) to High(TargsTags) do
    if (name = CmdNames[tag][1]) or (name = CmdNames[tag][2]) then
    begin
      Result := tag;
      break;
    end;
   Result := tag;
  end;

  procedure ShowHelp;
  begin
    WriteLn('RTFM!');
  end;

  function ArgsCheck: boolean;
  var i: integer;
      tag: TArgsTags;
      procedure FillParam(tag: TArgsTags; value: string);
      begin
          CmdValues[tag] := value;
          WriteLn(Format('arg %s is %s', [CmdNames[tag][1],CmdValues[tag]]));
      end;
  begin
    Result := False;
    WriteLn(Format('Arguments total: %d', [ParamCount]));
    for i:= 1 to ParamCount do
    begin
{$ifdef USECASE}
      tag := GetTagByName(ParamStr(i));
      case (tag) of
       atHelp: begin
                Result := True;
                ShowHelp();
                exit;
               end;
       atCommand:
        begin
          if (i+1 <= ParamCount) then
          begin
            FillParam(tag, ParamStr(i+1));
            Result := True;
          end
         else
         begin
            Result := False;
            ShowHelp();
            exit;
         end;
        end;
       end;  
{$else} //USE CYCLE
    for tag := Low(TArgsTags) to High(TargsTags) do
      if (ParamStr(i) = CmdNames[tag][1]) or (ParamStr(i) = CmdNames[tag][2]) then
      begin
        if (i+1 <= ParamCount) then
        begin
          FillParam(tag, ParamStr(i+1));
          Result := True;
        end
        else
        begin
          Result := False;
          ShowHelp();
          exit;
        end;
      end;
{$endif}
    end;
  end;

begin
  if not ArgsCheck then exit;
  WriteLn('You are parsed');
  ReadLn;
end.

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

А здесь ничего сложного. Суть заключается в функции, о которой я говорил - перевод строкового параметра в индекс, который затем прогоняется через case.

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

Эт для иллюстрации. Вообще, ИМХО, эта функция костыль (тут она ради кейса) - в смысле, можно обойтись без нее и без кейса... И короче выйдет. Просто тот же цикл из функции поместить внутрь цикла по параметрам.

slackwarrior ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.