为什么我在Eiffel中遇到了valid_index前提条件违规?

时间:2017-09-22 23:11:08

标签: eiffel preconditions

我只是简单地测试容器类的push_at特性(基本上由数组构成)。我不知道我的代码的哪一部分会触发此违规行为。

local
        con: CONTAINER

do
          create {CONTAINER}con.make
          con.push_at (1,"A")
          con.push_at (2,"B")

 Result := con.get(1) ~ "A" and con.get(2) ~ "B"
 check Result end
 end

在我的测试员中

processing file: eng_gitbash.Rmd
  |............
  ordinary text without R code

  |......................
label: unnamed-chunk-l
Quitting from lines 4-8 (eng_gitbash.Rmd)
Error in eval(expr, envir, enclos) : attempt to apply non-function  Calls:
         <Anonymous> ... handle -> withCallingHandlers -> withVisible -> eval -> eval

Line 4 Error in eval(expr, envir, enclos) : attempt to apply non-function Calls:
         <Anonymous> ... handle -> withCallingHandlers -> withVisible -> eval -> eval


output file: eng_gitbash. knit.md

Output created: eng_gitbash.html
Warning messages:
1: In get_engi ne(optionsSengi ne) :
  Unknown language engine 'gitbash' (must be registered via knit_engines$set())

2: In get_engi ne(optionsSengi ne) :
  Unknown language engine 'gitbash' (must be registered via knit_engines$set()) 

感谢您的帮助!

2 个答案:

答案 0 :(得分:0)

它是容器[i]。当你创建con时,它将是空的(可能 - 你没有向我们展示你的代码)。 您需要在con []上反映前提条件。这反过来需要反映{ARRAY} .put的前提条件,您必须使用它来实现它。你当前的前提条件不是这样做的(它是相当随意的)。

答案 1 :(得分:0)

用作元素存储的底层结构不会自动为新元素分配内存。一些结构在执行分配器命令container [i] := s时执行此操作。但是在你提到的代码中并非如此。因此,此命令中使用的索引i无效,因此违反前提条件。如果查看异常跟踪或调用堆栈,您将看到前提条件违规不在功能{CONTAINER}.puch_at中,而是在{ARRAY}.put或类似内容中,通过巧合和命名约定 - 使用相同的前提条件标签valid_index

有不同的方法可以解决这个问题:

  1. 使用其他结构进行存储(示例中的属性container),例如它可能是HASH_TABLE [STRING, INTEGER]。然后就可以将元素存储在任意索引中。

  2. 确保预先分配存储空间。如果您知道可能的索引范围,则可以初始化container以从头开始使用它们。它可以使用create container.make_filled ("", 1, N)创建,其中N是最大索引。 (我假设container的类型为ARRAY [STRING]。)

  3. 逐个添加元素。在这种情况下,push_at的前提条件应检查提供的索引是否存在或与先前分配的索引相邻:

    require
          valid_index: i >= 1
          existing_or_adjacent_index:
              container.valid_index (i) or else
              container.valid_index (i - 1)
    

    push_at的代码应该适用于使用将在提供的索引超出分配索引范围时分配新索引的功能:

    container.force (s, i)
    
  4. 化妆品:无需在创建说明create {CONTAINER} con.make中重复类型声明,因为变量con的类型为CONTAINER。因此,使用create con.make就足够了。