11.9.3 解析参数

如果前面的验证函数都不够用,那么还有 inputParser 类,它可以对函数输入执行极其复杂的检查。

 
p = inputParser ()

创建 inputParser 类的对象 p

该类的设计目的是便于解析函数参数。该类支持四种类型的参数:

  1. 必需参数(另请参阅 addRequired);
  2. 可选参数(另请参阅 addOptional);
  3. 命名参数(另请参阅 addParameter);
  4. 开关参数(另请参阅 addSwitch)。

使用这些方法定义函数 API 后,可以使用 parse 方法解析提供的参数,并通过 Results 访问器获取结果。

inputParser.Parameters

返回已定义的参数名称列表。(只读)

inputParser.Results

返回一个结构体,其字段名为参数名称,对应的值为参数值。(只读)

inputParser.Unmatched

返回一个与 Results 类似的结构体,但用于存放未匹配的参数。(只读)另请参阅 KeepUnmatched 属性。

inputParser.UsingDefaults

返回一个元胞数组,其中包含使用了默认值的参数名称。(只读)

inputParser.FunctionName = name

设置要在错误消息中使用的函数名称;默认为空字符串。

inputParser.CaseSensitive = boolean

设置参数名称匹配是否区分大小写;默认为 false。

inputParser.KeepUnmatched = boolean

设置是否解析与任何 Parameter 不匹配的字符串参数,并将其存储在 Unmatched 属性中;默认为 false。如果为 false,则在遇到第一个无法识别的参数时会产生错误,解析将停止。请注意,由于 SwitchParameter 参数可以混合使用,因此无法获知不匹配参数的类型。Octave 假设所有不匹配的参数均为 Parameter 类型,因此其后必须跟一个值。

inputParser.PartialMatching = boolean

设置是否允许以缩写形式给出 ParameterSwitch 选项的参数名称,只要该名称能够唯一标识一个选项即可;默认为 true。例如,参数 'opt' 可以匹配参数 'opt_color',但如果同时还存在参数 'opt_case',则会匹配失败。

inputParser.StructExpand = boolean

设置是否将传递给函数的结构体展开为参数/值对(参数=字段名);默认为 true。

以下示例展示了如何使用该类:

function check (varargin)
  p = inputParser ();                      # create object
  p.FunctionName = "check";                # set function name
  p.addRequired ("pack", @ischar);         # mandatory argument
  p.addOptional ("path", pwd(), @ischar);  # optional argument

  ## Create anonymous function handle for validators
  valid_vec = @(x) isvector (x) && all (x >= 0) && all (x <= 1);
  p.addOptional ("vec", [0 0], valid_vec);

  ## Create two arguments of type "Parameter"
  vld_type = @(x) any (strcmp (x, {"linear", "quadratic"}));
  p.addParameter ("type", "linear", vld_type);
  vld_tol = @(x) any (strcmp (x, {"low", "medium", "high"}));
  p.addParameter ("tolerance", "low", vld_tol);

  ## Create a switch type of argument
  p.addSwitch ("verbose");

  p.parse (varargin{:});  # Run created parser on inputs

  ## The rest of the function can access inputs by using p.Results.
  ## For example, get the tolerance input with p.Results.tolerance
endfunction
check ("mech");           # valid, use defaults for other arguments
check ();                 # error, one argument is mandatory
check (1);                # error, since ! ischar
check ("mech", "~/dev");  # valid, use defaults for other arguments

check ("mech", "~/dev", [0 1 0 0], "type", "linear");  # valid

## following is also valid.  Note how the Switch argument type can
## be mixed in with or before the Parameter argument type (but it
## must still appear after any Optional arguments).
check ("mech", "~/dev", [0 1 0 0], "verbose", "tolerance", "high");

## following returns an error since an Optional argument, 'path',
## was given after the Parameter argument 'type'.
check ("mech", "type", "linear", "~/dev");

注 1:一个函数可以混合使用全部四种 API 类型,但它们必须按照特定顺序出现。Required 参数必须放在最前面,其后可以跟任意数量的 Optional 参数。只有 ParameterSwitch 参数可以混合在一起,且它们必须出现在前两种类型之后。

注 2:如果函数的 API 中同时混合了 OptionalParameter 参数,那么当一个字符串类型的可选参数验证失败时,该参数将被视为 Optional 参数的结束。剩余的参数将与 ParameterSwitch 参数进行匹配。

另请参阅: narginvalidateattributesvalidatestringvarargin