4

如何循环浏览一个集合?

我正在使用 Fujitsu/Alchemy 编译器的试用版,并且从供应商那里获得了缓慢而糟糕的支持。

我基本上想将一个列表从 C# 传递给 COBOL,然后让 COBOL 使用它并可能更新它。

在 C# 中,遍历集合的常规方法是使用“foreach”构造。

但是,C#“foreach”构造是以下内容的快捷方式:

private static void test1()
{
    List<IDMSMapField> list1 = new List<IDMSMapField>();
    int listSize = list1.Count;
    // was just checking exact variablename and case here to copy into COBOL code.
    int itemNumber = 0;

    System.Collections.Generic.List<IDMSMapField>.Enumerator enumerator1 = list1.GetEnumerator();

    while (enumerator1.MoveNext())
    {
        Console.Write("Okay" + enumerator1.Current);
    }
}

如果你能帮我弄清楚如何声明这个类,我可以用 COBOL 写这个:

System.Collections.Generic.List<IDMSMapField>.Enumerator

“枚举器”结构记录在 Microsoft 的 MSDN 站点上

它告诉“枚举器”是一个结构,而不是一个类!

从我在手册“CreatingCOBOLfromDotnetFrameworkDox.pdf”中可以看出,结构被定义为 COBOL 存储库中的类。

手册中的示例:

Define specifiers for structure in REPOSITORY, and any struct members:
CLASS STRUCT-name AS "struct-namespace"
PROPERTY PROP-struct-member AS "external-property-name"
Handle structures like classes. E.g. object to store a struct instance:
01 struct-object OBJECT REFERENCE STRUCT-name.

下面,我将重复我尝试过的一些变体,但由于“无法解决”错误,这些变体都无法编译。如果你能告诉我如何正确声明这一点,我认为我们可以继续前进。

1.

    REPOSITORY.
           CLASS  CLASS-LIST         AS "System.Collections.Generic.List<>"
           CLASS  STRUCT-Enumerator  AS "System.Collections.Generic.List<>.Enumerator"
           .

第二行错误:

错误 JMN1795I-S:无法解析命名引用“System.Collections.Generic.List<>.Enumerator”。

  1. 完全相同的错误:

        REPOSITORY.
               CLASS  CLASS-LIST         AS "System.Collections.Generic.List<>"
               CLASS  STRUCT-Enumerator  AS "System.Collections.Generic.List<T>.Enumerator"
               .
    

错误 JMN1795I-S:无法解析命名引用“System.Collections.Generic.List.Enumerator”。

  1. 同样的错误:

    存储库。CLASS CLASS-LIST AS "System.Collections.Generic.List<>" CLASS STRUCT-Enumerator as "System.Collections.Generic.List.Enumerator" 。

错误 JMN1795I-S:无法解析命名引用“System.Collections.Generic.List.Enumerator”。

另一种选择是将它视为一个数组,但我也坚持这一点。

REPOSITORY.
    CLASS LIST-IDMSMapField    AS "System.Collections.Generic.List<>[]"
    CLASS CLASS-IDMSMapField   AS "Lightyear.ERCB.IDMSDC.IDMSMapField"
    CLASS CLASS-LIST-IDMSMapField EXPANDS LIST-IDMSMapField USING CLASS-IDMSMapField.

METHOD-ID. TW1DR4000-PF06 AS "TW1DR4000_PF06".
DATA DIVISION.
WORKING-STORAGE SECTION.

01 MapFieldItem USAGE OBJECT REFERENCE CLASS-IDMSMapField.

LINKAGE SECTION.

01 MapFieldList USAGE OBJECT REFERENCE CLASS-LIST-IDMSMapField.

PROCEDURE DIVISION...
...
SET MapFieldItem TO MapFieldList(1).

错误 JMN2671I-S: ':' 必须在引用修饰符中指定。':' 假设。

我认为编译器可能将 (1) 视为子字符串操作。

4

2 回答 2

3

花了一些时间,但这里有一个完整的工作示例。还有一些其他技巧可以获取属性,并使用适当的 USAGE 子句将属性值(例如 Count)移动到 COBOL 变量。“EXPANDS”关键字(在存储库中)是解决方案的另一个关键部分。

在我的实际程序中,我将在 LINKAGE 部分中收到列表,并且我将获得更复杂对象的列表......但示例代码是一个更简单的场景,它独立运行并“按原样”运行。

   IDENTIFICATION DIVISION.
   PROGRAM-ID. MAIN AS "COBOLEnumerationSample.Main".
   ENVIRONMENT DIVISION.
   CONFIGURATION SECTION.
   SPECIAL-NAMES.
   REPOSITORY.
       CLASS List        AS "System.Collections.Generic.List<>"
       CLASS SysString   AS "System.String"
       CLASS SysBoolean  AS "System.Boolean" 
       CLASS ListString EXPANDS List USING SysString
       CLASS Enumerator  AS "System.Collections.Generic.List<>+Enumerator"
       CLASS StringEnumerator EXPANDS Enumerator USING SysString
       PROPERTY PROP-Count   AS "Count"      
       PROPERTY PROP-Current AS "Current"
       .       
   DATA DIVISION.
   WORKING-STORAGE SECTION.
   01 myList              OBJECT REFERENCE ListString.
   01 myEnum              OBJECT REFERENCE StringEnumerator.   
   01 myBooleanEnumResult OBJECT REFERENCE SysBoolean. 
   01 myDotNetString      OBJECT REFERENCE SysString.  
   01 myLoopCounter       PIC 9(4)  value zero. 
   01 myCobolCount        PIC S9(9) COMP-5 VALUE ZERO.
   01 myCobolString       PIC X(30) value spaces. 
   01 YN-END-LOOP         PIC X     value "N". 
   01 WS-ACCEPT-INPUT     PIC X(80) value spaces. 

   PROCEDURE DIVISION.
   1000-START.
       INVOKE ListString "NEW" returning myList.
       INVOKE myList "Add" using "Apples"
       INVOKE myList "Add" using "Bananas"
       INVOKE myList "Add" using "Orange"


       SET myCobolCount to PROP-Count of myList 
       DISPLAY "Size of MyList = " myCobolCount

       INVOKE myList "GetEnumerator" returning myEnum.


       PERFORM UNTIL YN-END-LOOP = "Y" 
             INVOKE myEnum "MoveNext" returning myBooleanEnumResult  
  * How to test for Boolean, True = B'1' and False = B'0' 
             IF myBooleanEnumResult = B'0' 
                MOVE "Y" TO YN-END-LOOP 
             ELSE       
                SET myDotNetString TO PROP-Current of myEnum 
                ADD 1 TO myLoopCounter
                SET myCobolString to myDotNetString 
                DISPLAY myLoopCounter " " myCobolString 
             END-IF    

       END-PERFORM 

       DISPLAY "END OF PROGRAM - PRESS ENTER TO END" 
       ACCEPT WS-ACCEPT-INPUT
       .

   END PROGRAM MAIN.
于 2011-06-08T22:34:38.963 回答
0

使用 Micro Focus 的 .NET 实现,代码可以使用“执行变化通过”扩展来遍历列表。

所以调整后的版本是:

   IDENTIFICATION DIVISION.
   PROGRAM-ID. MAIN AS "COBOLEnumerationSample.Main".
   ENVIRONMENT DIVISION.
   CONFIGURATION SECTION.
   SPECIAL-NAMES.
   REPOSITORY.
       CLASS List        AS "System.Collections.Generic.List"
       CLASS SysString   AS "System.String"
       CLASS SysBoolean  AS "System.Boolean"
       CLASS ListString EXPANDS List USING SysString
       PROPERTY PROP-Count   AS "Count"
       PROPERTY PROP-Current AS "Current"
       .
   DATA DIVISION.
   WORKING-STORAGE SECTION.
   01 myList              OBJECT REFERENCE ListString.
   01 myLoopCounter       PIC 9(4)  value zero.
   01 myCobolCount        PIC S9(9) COMP-5 VALUE ZERO.
   01 myCobolString       PIC X(30) value spaces.
   01 WS-ACCEPT-INPUT     PIC X(80) value spaces.

   PROCEDURE DIVISION.
   1000-START.
       INVOKE ListString "NEW" returning myList.
       INVOKE myList "Add" using "Apples"
       INVOKE myList "Add" using "Bananas"
       INVOKE myList "Add" using "Orange"

       SET myCobolCount to PROP-Count of myList
       DISPLAY "Size of MyList = " myCobolCount

       move 0 to myLoopCounter
       PERFORM varying myCobolString through myList
           DISPLAY myLoopCounter " " myCobolString
           ADD 1 to myLoopCounter
       END-PERFORM

       DISPLAY "END OF PROGRAM - PRESS ENTER TO END"
       ACCEPT WS-ACCEPT-INPUT
       .

   END PROGRAM MAIN.

接下来,您可以使用内联声明,而不是使用存储库语法和扩展,例如:

   IDENTIFICATION DIVISION.
   PROGRAM-ID. MAIN AS "COBOLEnumerationSample.Main".
   WORKING-STORAGE SECTION.
   01 myList         type "System.Collections.Generic.List"[string].
   01 myLoopCounter   PIC 9(4)  value zero.
   01 myCobolCount    PIC S9(9) COMP-5 VALUE ZERO.
   01 myCobolString   PIC X(30) value spaces.
   01 WS-ACCEPT-INPUT PIC X(80) value spaces.

   PROCEDURE DIVISION.
   1000-START.
       INVOKE type "System.Collections.Generic.List"[string]::"NEW"
             returning myList
       INVOKE myList "Add" using "Apples"
       INVOKE myList "Add" using "Bananas"
       INVOKE myList "Add" using "Orange"


       SET myCobolCount TO myList::"Count"
       DISPLAY "Size of MyList = " myCobolCount

       MOVE 0 TO myLoopCounter
       PERFORM varying myCobolString through myList
           DISPLAY myLoopCounter " " myCobolString
           ADD 1 TO myLoopCounter
       END-PERFORM

       DISPLAY "END OF PROGRAM - PRESS ENTER TO END"
       ACCEPT WS-ACCEPT-INPUT
       .

   END PROGRAM MAIN.

无论如何,我只是喜欢我们可以在 COBOL 中做到这一点,无论使用哪种产品......享受......

于 2011-06-10T21:22:09.020 回答