Comment puis-je me débarrasser des espaces de fin et incorporés dans une chaîne?


Lena

J'écris un programme qui convertit les numéros de compte nationaux et internationaux en numéros IBAN. Pour commencer, je dois former une chaîne: ID de la banque + ID de la succursale + numéro de compte + code de pays ISO sans les espaces de fin qui peuvent être présents dans ces champs. Mais tous les numéros de compte n'ont pas la même longueur, certains numéros de compte ont des identifiants de succursale tandis que d'autres n'en ont pas, donc je me retrouverai toujours avec des espaces à la fin de ces champs.

Mon stockage de travail ressemble à ceci:

      01 Input-IBAN.
          05 BANK-ID                    PIC N(10) VALUE "LOYD".
          05 BRANCH-ID                  PIC N(10) VALUE "     ".
          05 ACCOUNT-NR                 PIC N(28) VALUE "012345678912   ". 
          05 COUNTRY-CODE               PIC N(02) VALUE "GB".
      01 Output-IBAN                    PIC N(34).

J'ai mis quelques valeurs là-dedans pour l'exemple; en réalité, cela dépendrait de l'apport. Le code de branche est facultatif, donc je le laisse vide dans l'exemple.

Je veux essentiellement partir de cette entrée enchaînée: "LOYD 012345678912 GB"

pour ça: "LOYD012345678912GB"

Quelqu'un connaît-il un moyen de le faire qui n'entraîne pas de problèmes de performances? J'ai pensé à utiliser le FUNCTION REVERSE, puis à utiliser un INSPECTpour compter les espaces principaux. Mais j'ai entendu dire que c'était une façon lente de le faire. Quelqu'un a-t-il une idée? Et peut-être un exemple sur la façon d'utiliser ladite idée?

EDIT: J'ai été informé que les champs élémentaires peuvent contenir des espaces incorporés.

Bill Woodger

Je vois maintenant que vous avez incorporé des blancs dans les données. Aucune des réponses que vous avez jusqu'à présent ne fonctionne, alors. Gilbert "élimine" les blancs intégrés, le mien perdrait toutes les données après le premier vide dans chaque champ.

Cependant, juste pour souligner, je ne crois pas vraiment que vous puissiez avoir des blancs intégrés si vous générez de quelque façon un "IBAN". Par exemple, https://en.wikipedia.org/wiki/International_Bank_Account_Number#Structure , en particulier:

L'IBAN ne doit pas contenir d'espaces lorsqu'il est transmis par voie électronique. A l'impression, il est exprimé en groupes de quatre caractères séparés par un seul espace, le dernier groupe étant de longueur variable

Si vos données source ont des blancs incorporés, au niveau du champ, vous devez les renvoyer en arrière pour une décision sur ce qu'il faut faire. En supposant que vous recevez la bonne réponse (pas de blancs intégrés au niveau du champ), les deux réponses existantes sont de retour sur la table. Vous modifiez Gilbert's en changeant (logiquement) LENGTH OF en FUNCTION LENGTH et en traitant toute possibilité de débordement de la sortie.

Avec le STRING, vous devez à nouveau faire face à la possibilité de déborder la sortie.

Réponse originale basée sur l'hypothèse de l'absence de blancs intégrés.


Je suppose que vous n'avez pas de blancs incorporés dans les éléments élémentaires qui composent votre structure, car ils proviennent de valeurs standard qui ne contiennent pas de blancs incorporés.

       MOVE SPACE                   TO OUTPUT-IBAN
       STRING                       BANK-ID 
                                    BRANCH-ID 
                                    ACCOUNT-NR 
                                    COUNTRY-CODE 
         DELIMITED                  BY SPACE 
         INTO                       OUTPUT-IBAN 

STRING copie uniquement les valeurs jusqu'à ce qu'il n'y ait plus de données à copier, il est donc nécessaire d'effacer OUTPUT-IBAN avant la STRING.

La copie des données de chaque champ source se terminera lorsque le premier ESPACE sera rencontré dans chaque champ source. Si un champ est entièrement espace, aucune donnée ne sera copiée à partir de celui-ci.

STRING entraînera presque certainement l'exécution d'une routine d'exécution et il y aura une surcharge pour cela. L'exemple de Gilbert LeBlanc peut être légèrement plus rapide, mais avec STRING, le compilateur traite automatiquement toutes les longueurs de tous les champs. Comme vous avez des champs nationaux, assurez-vous d'utiliser la constante figurative ESPACE (ou ESPACES, ils sont identiques) et non une valeur littérale qui, selon vous, contient un espace " ". C'est le cas, mais il ne contient pas d'espace national.

Si le résultat de STRING est supérieur à 34 caractères, les caractères en excès seront tranquillement tronqués. Si vous voulez gérer cela, STRING a une ON OVERFLOWphrase dans laquelle vous spécifiez ce que vous voulez faire dans ce cas. Si vous utilisez ON OVERFLOW, ou en fait, NOT ON OVERFLOWvous devez utiliser le END-STRINGterminateur de portée. Un point / point terminera également l'instruction STRING, mais lorsqu'il est utilisé de cette manière, il ne peut jamais, avec ON / NOT ON, être utilisé dans une instruction conditionnelle de tout type.

N'utilisez pas de points / points pour terminer les étendues.

COBOL n'a pas de "chaînes". Vous ne pouvez pas supprimer les espaces de fin dans les champs de longueur fixe, sauf si les données remplissent le champ. Votre IBAN de sortie contiendra toujours des espaces de fin lorsque les données sont courtes.


Si vous deviez réellement avoir des blancs incorporés au niveau du champ:

Premièrement, si vous voulez "extraire" les blancs intégrés pour qu'ils n'apparaissent pas dans la sortie, je ne peux pas penser à un moyen plus simple (en utilisant COBOL) que celui de Gilbert.

Sinon, si vous souhaitez conserver les blancs incorporés, vous n'avez pas d'autre choix raisonnable que de compter les blancs de fin afin de pouvoir calculer la longueur des données réelles dans chaque champ.

Les implémentations COBOL ont des extensions de langage. On ne sait pas quel compilateur COBOL vous utilisez. S'il s'agit d'AcuCOBOL (maintenant de Micro Focus), INSPECT prend en charge TRAILING, et vous pouvez compter les blancs de fin de cette façon. GnuCOBOL prend également en charge TRAILING sur INSPECT et dispose en outre d'une fonction intrinsèque utile, TRIM, que vous pouvez utiliser pour faire exactement ce que vous voulez (rogner les blancs de fin) dans une instruction STRING.

       move space                   to your-output-field
       string function 
               trim 
                ( your-first-national-source 
                  trailing )
              function 
               trim 
                ( your-second-national-source 
                  trailing )
              function 
               trim 
                ( your-third-national-source 
                  trailing )
              ...
         delimited                  by size
         into                       your-output-field

Notez qu'à part le PIC N dans vos définitions, le code est le même que si vous utilisez des champs alphanumériques.

Cependant, pour le code COBOL 85 standard ...

Vous avez mentionné l'utilisation de FUNCTION REVERSE suivi de INSPECT. INSPECT peut compter les espaces de début, mais pas, par Standard, les espaces de fin. Ainsi, vous pouvez inverser les octets dans un champ, puis compter les espaces de début.

Vous disposez de données nationales (PIC N). Une différence avec cela est que ce ne sont pas des octets que vous devez compter, mais des caractères, qui sont composés de deux octets. Puisque le compilateur sait que vous utilisez les champs PIC N, il n'y a qu'une seule chose pour vous déclencher - le registre spécial, LENGTH OF, compte des octets, vous avez besoin de FUNCTION LENGTH pour compter les caractères.

Les données nationales sont UTF-16. Ce qui signifie que les deux octets pour chaque caractère se trouvent être "ASCII", quand l'un des octets représente un caractère affichable. Cela n'a pas d'importance non plus, fonctionnant sur z / OS, une machine EBCDIC, car le compilateur effectuera automatiquement les conversions nécessaires pour les littéraux ou les éléments de données alphanumériques.

       MOVE ZERO                    TO a-count-for-each-field 
       INSPECT FUNCTION 
                REVERSE 
                 ( each-source-field )
         TALLYING                   a-count-for-each-field 
          FOR LEADING               SPACE 

Après en avoir fait un pour chaque champ, vous pouvez utiliser la modification de référence.

Comment utiliser la modification de référence pour cela?

Tout d'abord, vous devez être prudent. Deuxièmement, vous ne le faites pas.

Deuxièmement d'abord:

MOVE SPACE                   TO output-field
STRING field-1 ( 1 : length-1 )
       field-2 ( 1 : length-2 )
  DELIMITED BY               SIZE
  INTO                       output-field

Traitez à nouveau le débordement si possible / nécessaire.

C'est également possible avec des MOVEs simples et une modification de référence, comme dans cette réponse, https://stackoverflow.com/a/31941665/1927206 , dont la question est proche d'un double de votre question.

Pourquoi faut-il faire attention? Encore une fois, d'après la réponse liée précédemment, en théorie, une modification de référence ne peut pas avoir une longueur nulle.

En pratique, cela fonctionnera probablement. Les programmeurs COBOL semblent généralement tellement désireux de modifier les références qu'ils ne se donnent pas la peine de lire complètement à ce sujet, alors ne vous inquiétez pas du fait qu'une longueur zéro ne soit pas Standard, et ne remarquez pas qu'elle n'est pas standard, parce que cela "fonctionne". Pour l'instant. Jusqu'à ce que le compilateur change.

Si vous utilisez Enterprise COBOL V5.2 ou supérieur (éventuellement V5.1 également, je n'ai tout simplement pas vérifié), vous pouvez être sûr, par l'option du compilateur, si vous le souhaitez, qu'une modification de référence de longueur nulle fonctionne comme attendu.

Certains autres moyens d'accomplir votre tâche, si des blancs incorporés peuvent exister et peuvent être importants dans la sortie, sont couverts dans cette réponse. Avec National, veillez toujours à utiliser FUNCTION LENGTH (qui compte les caractères) et non LENGTH OF (qui compte les octets). Habituellement, la LONGUEUR DE et LA LONGUEUR DE FONCTION donnent la même réponse. Pour les caractères multi-octets, ils ne le font pas.

Articles connexes