2016-03-27 19 views
1

Ich versuche, die folgende Zeile mit DISPLAY ausgeben und bekomme das richtige Ergebnis in Micro Focus COBOL in Visual Studio und der COPOL Compiler Tutorial, aber etwas seltsam, wenn Sie es auf einem z/OS ausführen Enterprise-COBOL-Mainframe mit IBM:Verschiedene Ergebnisse mit OCCURS mit verschiedenen Compilern

01 W05-OUTPUT-ROW. 
    05 W05-OFFICE-NAME PIC X(13). 
    05 W05-BENEFIT-ROW OCCURS 5 TIMES. 
     10 PIC X(2) VALUE SPACES. 
     10 W05-B-TOTAL PIC ZZ,ZZ9.99 VALUE ZEROS. 
    05 PIC X(2) VALUE SPACES. 
    05 W05-OFFICE-TOTAL PIC ZZ,ZZ9.99 VALUE ZEROS. 

Es scheint in Enterprise COBOL, dass die Räume werden ignoriert, und fügt eine zusätzliche Null-gefüllte Säule, obwohl die PERFORM VARYING und DISPLAY-Code ist genau das gleiche in beiden Versionen:

PERFORM VARYING W02-O-IDX FROM 1 BY 1 
    UNTIL W02-O-IDX > W12-OFFICE-COUNT 

    MOVE W02-OFFICE-NAME(W02-O-IDX) TO W05-OFFICE-NAME 

    PERFORM 310-CALC-TOTALS VARYING W02-B-IDX FROM 1 BY 1 
     UNTIL W02-B-IDX > W13-BENEFIT-COUNT 

    MOVE W02-O-TOTAL(W02-O-IDX) TO W05-OFFICE-TOTAL 
    DISPLAY W05-OUTPUT-ROW 
END-PERFORM 

W13-BENEFIT-COUNT ist 5 und ändert sich nie im Programm, daher ist die 6. Spalte ein Rätsel für mich.

korrekte Ausgabe:

Correct output

Seltsamer Ausgang:

strange output

Edit: wie gewünscht, hier ist W02-OFFICE-TABLE:

01 W02-OFFICE-TABLE. 
    05 W02-OFFICE-ROW OCCURS 11 TIMES 
    ASCENDING KEY IS W02-OFFICE-NAME 
    INDEXED BY W02-O-IDX. 
     10 W02-OFFICE-CODE PIC X(6). 
     10 W02-OFFICE-NAME PIC X(13). 
     10 W02-BENEFIT-ROW OCCURS 5 TIMES 
     INDEXED BY W02-B-IDX. 
      15 W02-B-CODE PIC 9(1). 
      15 W02-B-TOTAL PIC 9(5)V99 VALUE ZERO. 
     10 W02-O-TOTAL PIC 9(5)V99 VALUE ZERO. 

und W12 -OFFICE-COUNT ist immer 11, ändert sich nie:

01 W12-OFFICE-COUNT PIC 99 VALUE 11. 
+0

Notwendigkeit zu sehen: W02-O-IDX; W02-B-IDX; W12-BÜRO-COUNT. Da einige Leute das Suffix "IDX" und eine Pseudozufallsart verwenden, müssen wir die Definitionen sehen. Nimm die VALUE-Klausel auf W-B-TOTAL ab und die Nullen werden auf magische Weise weggehen (sie werden etwas anderes sein). –

+0

Jetzt, da der Fix in ist, richtet sich die gesamte Ausgabe gleich aus? Schau dir deine Screenshots an. Warum befindet sich die Spalte TOTAL, die vom Problem OCCURS unbeeinflusst ist, an einer anderen Stelle als die Überschriften der beiden Beispiele? –

Antwort

2

würde ich sehr zögerlich über Misch VALUE mit OCCURS und Re-Code, um die WS als

01 W05-OUTPUT-ROW. 
    05 W05-OFFICE-NAME PIC X(13). 
    05 W05-BENEFITS  PIC X(55) VALUE SPACES. 
    05 FILLER REDEFINES W05-BENEFITS. 
    07 W05-BENEFIT-ROW OCCURS 5 TIMES. 
     10 FILLER  PIC X(02). 
     10 W05-B-TOTAL PIC ZZ,ZZ9.99. 
    05 FILLER   PIC X(02) VALUE SPACES. 
    05 W05-OFFICE-TOTAL PIC ZZ,ZZ9.99 VALUE ZEROS. 

Vielleicht hat es etwas mit dem fehlenden Feldnamen zu tun?

Ah! böse INDEXED. Ich würde beide *** - IDX-Variablen einfach 99s machen.

+0

Es gibt kein Problem mit der VALUE-Anweisung, obwohl es nicht besonders nützlich ist. Dies wird für die Ausgabe keinen Unterschied machen. Was fehlt Feldname? –

+0

@BillWoodger: Ich habe keinen Zugriff auf den Mainframe, also kann ich nicht testen. Ich glaube, dass es das Problem tatsächlich beheben wird - OP kann bestimmen. Ich habe nie das Symbol von '10 PIC X (2)' benutzt oder gesehen und würde es immer als '10 FILLER PIC X (2)' kodieren. – Magoo

+0

Ich habe versucht, das FILLER-Schlüsselwort den Leerzeichenwerten hinzuzufügen, keine Änderung. Aber Sie haben Recht, dass das Entfernen der VALUE ZEROS die unerklärten Nullen entfernt. Ich habe auch Ihren Code ausprobiert und das Ergebnis ist das gleiche: Die Leerzeichen werden ignoriert (oder vielleicht bis zum Ende gedrängt?). Es muss etwas damit zu tun haben, eine Tabelle ANZEIGEN zu lassen, die anders auf dem Mainframe arbeitet. –

4

Die Frage ist nicht so sehr "Warum macht Enterprise COBOL das?", Weil es dokumentiert ist, wie "warum generieren diese anderen zwei Compiler Programme, die tun, was ich will?", Was wahrscheinlich auch dokumentiert ist.

Hier ist ein Zitat aus dem Entwurf des späteren 2014 COBOL Standard (die tatsächliche Standard-Geld kostet):

C.3.4.1 Subskribierung indexNamen

Um diese zu erleichtern Operationen wie Tabellensuche und Manipulation bestimmter Elemente, ist eine Technik namens Indizierung verfügbar. Um diese Technik zu verwenden, weist der Programmierer einem Element, dessen Datenbeschreibungseintrag eine OCCURS-Klausel enthält, einen oder mehrere Indexnamen zu. Ein Index, der einem Indexnamen zugeordnet ist, fungiert als Index, und sein Wert entspricht einer Häufigkeitsnummer für das Element, dem der Indexname zugeordnet ist.

Die INDEXED BY-Angabe, mit der der Indexname identifiziert wird, und , die seiner Tabelle zugeordnet ist, ist ein optionaler Teil der OCCURS-Klausel. Es gibt keinen separaten Eintrag zur Beschreibung des Indexes, der index-name zugeordnet ist, da seine Definition vollständig hardwareorientiert ist.Bei Laufzeit entspricht der Inhalt des Index einer Vorkommenummer für die spezifische Dimension der Tabelle, mit der der Index zugeordnet ist; die Art der Übereinstimmung wird jedoch durch den Implementierer bestimmt. Der Anfangswert eines Index zur Laufzeit ist nicht definiert, und der Index soll vor der Verwendung initialisiert werden. Der Anfangswert eines -Index wird mit der PERFORM-Anweisung mit der VARYING-Angabe, der SEARCH-Anweisung mit der ALL-Anweisung oder der SET-Anweisung zugewiesen.

[...]

Ein Index-Name kann nur die Tabelle, auf die sie über die indizierte BY Phrase zugeordnet ist Referenz verwendet werden.

Aus dem zweiten Absatz wird klar, dass die Implementierung eines Indexes auf den Implementierer des Compilers zurückzuführen ist. Was bedeutet, dass das, was ein Index tatsächlich enthält und wie er intern manipuliert wird, von Compiler zu Compiler variieren kann, solange die Ergebnisse gleich sind.

Der letzte zitierte Absatz gibt an, dass ein bestimmter Index vom Standard nur für die Tabelle verwendet werden kann, die diesen spezifischen Index definiert.

Sie haben einen entsprechenden Code in 310-CALC-TOTALS: Nehmen Sie ein Quelldatenelement mit dem Index aus seiner Tabelle, und verwenden Sie diesen Index aus der "falschen" Tabelle, um einen abgeleiteten Wert in einer anderen Tabelle zu speichern.

Dies unterbricht die "Ein Index-Name kann verwendet werden, um nur die Tabelle zu referenzieren, mit der er über den INDEXED BY-Ausdruck verknüpft ist."

Sie haben also Ihren Code in 310-CALC-TOTALS geändert in: nehmen Sie ein Quelldatenelement mit dem Index aus seiner Tabelle und verwenden Sie einen in der Zieltabelle definierten Datennamen oder Index, um einen davon abgeleiteten Wert zu speichern in einer anderen Tabelle.

So funktioniert nun Ihr Code, und Sie erhalten das gleiche Ergebnis mit jedem Compiler.

Warum kompiliert der Enterprise COBOL-Code, wenn der Standard (und dies war der gleiche für frühere Standards) verbietet diese Verwendung?

IBM hat eine Spracherweiterung. In der Tat zwei Erweiterungen, die zu Ihrem Fall anwendbar sind (aus der Unternehmen COBOL-Sprachreferenz zitiert in Anhang A):

Indexing und Subskribierung ... eine Tabelle mit einem Index-Namen referenzieren definiert nicht für einen anderen Tisch

und

OCCURS ... Verweis auf eine Tabelle, durch Indizieren, wenn indizierte BY Phrase

angegeben

So haben Sie keine Kompilierung-Fehler erhalten, als einen Index aus einer anderen Tabelle und unter Verwendung eines Index, wenn kein Index für die Tabelle sind beide OK definiert ist.

Also, was macht es, wenn Sie einen anderen Index verwenden?Wieder von der Sprachreferenz, Subskribierung diesmal auf Indexnamen (Indexierung)

Ein Index-Name jeder Tabelle verweisen verwendet werden kann. Jedoch sollte das Element Länge der Tabelle, auf die verwiesen wird, und der Tabelle, die der Indexname zugeordnet ist, übereinstimmen. Andernfalls wird der Verweis nicht auf das gleiche Tabellenelement in jeder Tabelle verweisen, und Sie erhalten möglicherweise Laufzeitfehler.

Welches ist genau das, was dir passiert ist. Der Unterschied in den Längen der Elemente in den OCCURS liegt an den "Einfüge-Bearbeitungs" -Symbolen in Ihrem PICture für die Tabelle, von der Sie ANZEIGEN. Wenn die Elemente in den beiden Tabellen die gleiche Länge hätten, hätten Sie kein Problem bemerkt.

Sie gaben eine VALUE-Klausel für Ihre Tabellenelemente (unnötig, da Sie immer etwas in sie vor der Ausgabe geben würden) und dies verließ Ihre "sechste" Spalte, die fünf vorherigen Spalten wurden als kürzere Elemente geschrieben. Beachten Sie die Verwirrung, die entsteht, wenn die Bearbeitung auf eine Länge erfolgt und das Speichern mit einer anderen impliziten Länge erfolgt, Sie überschreiben sogar die zweite Dezimalstelle.

IBMs Implementierung von INDEXED BY bedeutet, dass die Länge der indizierten Elemente intrinsisch ist. Daher die unerwarteten Ergebnisse, wenn die referenzierten Felder tatsächlich unterschiedliche Längen haben.

Was ist mit den anderen beiden Compilern? Sie müssen ihre Dokumentation treffen, um sicher zu sein, was passiert ist (etwas so Einfaches wie der Index durch eine Eintragsnummer dargestellt wird (also Ebene 1, 2, 3, usw.) und das Erlauben eines Index, sich auf einen anderen zu beziehen Tisch wäre genug). Es sollte zwei Erweiterungen geben: um zu ermöglichen, dass ein Index für eine Tabelle verwendet wird, die diesen Index nicht definiert hat; um zu ermöglichen, dass ein Index für eine Tabelle verwendet wird, für die kein Index definiert ist. Die beiden kommen logisch als ein Paar, und beide müssen nur spezifisch sein (das erste würde anders tun), weil sie spezifisch gegen den Standard sind.

Micro Focus verfügt über eine Sprachenerweiterung, wobei ein Index aus einer Tabelle verwendet werden kann, um Daten aus einer anderen Tabelle zu referenzieren. Es ist nicht explizit, dass dies eine Referenzierung einer Tabelle ohne definierte Indizes beinhaltet, aber dies ist offensichtlich so.

Tutorialsoft verwendet OpenCOBOL 1.1. OpenCOBOL ist jetzt GnuCOBOL. GnuCOBOL 1.1 ist die aktuelle Version, die anders und aktueller als OpenCOBOL 1.1 ist. GnuCOBOL 2.0 kommt bald. Ich trage den Diskussionsbereich für GnuCOBOL bei SourceForge.Net bei und habe das Thema dort angesprochen. Simon Sobisch vom GnuCOBOL-Projekt hat sich bereits an Ideaone und Tuturialspoint über die Verwendung des veralteten OpenCOBOL 1.1 gewandt. Ideaone hat positives Feedback gegeben, Tutorialpoint, mit dem Simon sich heute noch nicht in Verbindung gesetzt hat, noch nichts.

Als Nebenproblem sieht es so aus, als ob Sie SEARCH ALL verwenden, um eine Binärsuche Ihrer Tabelle durchzuführen. Für "kleine" Tabellen ist es wahrscheinlich, dass der Overhead der Mechanismen der verallgemeinerten Binärsuche, die von SUCHEN ALL bereitgestellt wird, die erwarteten Einsparungen bei den Maschinenressourcen überwiegt. Wenn Sie große Datenmengen verarbeiten, ist eine einfache SUCHE wahrscheinlich effizienter als die SUCHE ALL.

Wie klein "klein" ist, hängt von Ihren Daten ab. Fünf ist wahrscheinlich zu fast 100% klein.

Bessere Leistung als die Funktionen SEARCH und SEARCH ALL können durch Kodieren erreicht werden, aber denken Sie daran, dass SEARCH und SUCHE ALLE keine Fehler machen.

Aber vor allem mit SEARCH ALL sind Fehler durch den Programmierer einfach.Wenn die Daten nicht in der richtigen Reihenfolge sind, funktioniert SEARCH ALL nicht korrekt. Das Definieren von mehr Daten als das Auffüllen von Daten führt dazu, dass eine Tabelle schnell aus der Reihenfolge kommt. Wenn Sie SEARCH ALL mit einer variablen Anzahl von Elementen verwenden, sollten Sie die Verwendung von OCCURS DEPENDING ON für die Tabelle oder "Auffüllen" von nicht verwendeten nachgestellten Einträgen mit einem Wert über dem maximal möglichen Schlüsselwert in Betracht ziehen.

+0

Danke für die Erklärung. Ich habe einfach angenommen, dass ein Index ein einfacher For-Loop-Zähler ist und vollständig wiederverwendbar ist. Ich hätte nie gedacht, dass es an die Größe des Tisches gebunden war, aber das macht jetzt vollkommen Sinn. Außerdem gab Microfocus diese Warnung, die ich ignorierte, weil ich die richtigen Ergebnisse erhielt, bevor ich zu z/OS wechselte: '" Warnung COBCH1118: Indexname gehört zu anderen Tabelle - unerwartetes Verhalten kann auftreten " Es hätte Es war schön, wenn der Mainframe-Compiler auch eine Warnung abwarf. –

+0

@ JeremyRobson Es ist gültig für Enterprise COBOL, also warum sollte es eine Warnung geben? Die Art, wie es reibungslos funktioniert, ist "jeder weiß, dass man das nicht kann", COBOL 101, sozusagen. Also macht es keiner. Obwohl du kannst. Nehmen Sie Warnungen immer ernst. Finde immer genau heraus, was sie (oder andere Nachrichten) bedeuten. –

Verwandte Themen