热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

c调用cobol_从COBOL角度看C

c调用cobol我最初是在1986年为一家印刷杂志写这篇文章的。我23岁,从事COBOL已有四年,最初是在打Kong卡上做的。我开始听有关C的知识并将其

c 调用 cobol

我最初是在1986年为一家印刷杂志写这篇文章的。我23岁,从事COBOL已有四年,最初是在打Kong卡上做的。 我开始听有关C的知识并将其教给自己,然后将一些COBOL重写为C(请注意,C是COBOL的可怕替代品),我将此内容作为其他COBOL程序员入门的入门,以了解C。大约10年前更新了该介绍的博客文章,但在过去的两周中,我最终与六位​​不了解COBOL的人分享了该介绍,只是为了向他们描述COBOL记录结构,感觉很强大,在大多数现代语言中也没有很好的体现。 这将成为我目前正在设计的一种新语言,因此请欣赏过去的爆炸声,并了解您的祖父母在“回到过去”的方式:)。

尽管年轻的程序员很难相信,但仍然有至少65%的世界代码是用COBOL编写的,每年要编写50亿行新代码。 每天,COBOL应用程序处理的数据量是Google的200倍。 他们甚至不再在学校教这本书了,这真是令人遗憾,因为COBOL是一种很棒的商业语言,比Python可能存在的任何事物都要好得多。 这是因为其健壮的记录结构以及干净的字符串变量和条件逻辑。 虽然本文的主要目的是让COBOL程序员理解C,但是您可以轻松地反转示例。 在某些时候,必须重写或维护旧的COBOL代码,原因之一是它仍然存在,并且由于COBOL的稳定性和简洁性,因此几乎不需要手工操作。

请记住,C和COBOL来自完全不同的根,这使得比较变得非常困难。

预处理器

COBOL为我们提供了两个共享先前定义的记录布局和变量声明的选项。 最简单,最直接的是$ INCLUDE'文件名'。 这将获取一个文件,并在编译时将其复制到源文件中。 如果您不担心修改任何语句,则此方法就很好用,类似于Python中的“ import”或C / C ++ / etc中的“ include”。

更加通用的选项是使用COBEDIT并维护COPYLIB。 使用COPY命令从COPYLIB检索成员的优点是可以进行动态文本替换。 因此,如果要两次定义客户主数据集,一次定义数据集,一次定义一个文件,则可以在COPYLIB中设置一个前缀,您可以在编译时使用以下命令来更改该前缀:

COPY textname REPLACING ==pseudo-text-1== BY ==pseudo-text-2==.

因此,无需在COPYLIB中保留两个不同的定义。

尽管C确实有一个“ include”语句,但它没有与COPY语句等效的语句。 但是,通过使用“ #if”,“#ifdef”,“#elif”和“ #ifndef”命令,您可以控制在编译时包含哪些文件。 假设您正在编码某种便携式应用程序,并且已在不同文件中定义了不同的文件I / O功能以适应您的不同平台。 您可以使用以下结构轻松控制它;

#define SYS "Windows"
#if SYS == "Windows"
#include "windows.h"
#elif SYS == "MacOS"
#include "macos.h"
#elif SYS == "Linux"
#include "linux.h"
#endif

这里有几件重要的事情需要学习。 首先,#define命令实际上与COBOL中的$ DEFINE几乎相同。 它们都允许您定义和命名宏,该宏将创建“内联”代码,因此,如果代码稍大,它将产生更高的效率。 但是,COBOL define语句可以根据需要设置,但许多C编译器将您限制为仅包含#define语句的行。 将参数传递给C宏也更加令人困惑,只需确保在括号中放宽即可,以确保优先顺序。

例如,#define也可以像在COBOL中使用88级变量一样工作。

#define FALSE 0
#define TRUE !FALSE

然后我可以说'if FALSE'就像在COBOL中用88一样。这里的好处是,我可以使用!将TRUE定义为'not'FALSE。 (表示不是)在第二个#define语句中。 这实际上在COBOL中没有等效项。

既然我已经对#define语句进行了足够的介绍,可以使我们理解第一个示例,那么为什么不结束对示例的解释呢?

由于我们已将SYS定义为等于字符串HP3000,因此第一个#if语句为true,并且文件hp3kio.h将在编译时复制到程序中。 #elif是一个非常愚蠢的说法,“ else if”,只有汇编神知道他们为什么选择以这种方式缩写它。 因此,如果我们要编译代码以在VAX上运行,则只需更改#define行,然后,如果我们正确完成了初始设置,我们的代码就可以在VAX上运行。

信不信由你,您可以使用COBOL中鲜为人知且很少使用的编译器开关来完成几乎相同的事情。 通过使用以下命令,您可以实现类似的效果。

$SET X0=OFF
$IF X0=OFF
COPY WINDOWS
$IF X0=ON
COPY LINUX
$IF

重要的是要注意,尽管COBOL不区分大小写,但C是区分大小写的。 因此,myvar,Myvar和MYVAR实际上是三种不同的东西。 我看到的一个非正式标准是,所有“常规” C代码都使用小写字母,您定义的所有宏以及有时使用的函数都使用大写字母,以便快速,轻松地区分C和C的组成部分。你的是什么。 这根本不是一个坏主意。

我们在讨论入门时的最后一个注意事项是如何在代码中添加注释。 在COBOL中,请在第7列中输入*,然后键入所需的任何内容,也可以使用每行的最后5个字符输入有意义的内容。 在C语言中,我们的注释必须放在匹配的/ *…* /中,这可以单独出现在带有命令的行上,也可以跨行出现。 这里有一些例子;

/* here is my comment */
/*
here is another comment
that spans multiple lines
*/

a = b; / *这是在命令行上的注释* /

可变声明

下一步最明显的方法是如何在C中定义变量。在某些方面,这是C实际上比COBOL拥有C的地方,因为您可以定义全局AND局部变量。 这相当于在COBOL程序中有一个状态验证段,该段在段的顶部声明了它所需的所有变量,然后在该段返回调用过程时它们消失了。 想象一下,不再声明仅使用一次的全局变量。

C在定义变量的方式上与COBOL显着不同。

COBOL C
---------------------------------------------------------
PIC S9(4 ) COMP short
PIC S9( 9 ) COMP long
PIC 9 char

关于在C中声明简单整数的重要说明,标准声明为'int my_counter'。 现在,my_counter的长度将取决于在其上声明的计算机的本机体系结构。 因此,在16位系统上说“ int”将声明一个16位整数或PIC S9(4)COMP。 问题是,如果将代码移至32位系统,则该声明将突然变为32位或PIC S9(9)COMP。 我们通过声明它们为16位的“短”整数或32位的“长”整数来解决这个问题。

我们的下一个变量类型是字符串或字符数组。 C以截然不同的方式处理字符串。 因为所有内容都是单个字符,所以您必须定义一个字符数组,这也是引用它的方式。 这是一个示例,说明如何在COBOL中执行此操作以及如果它像C一样必须在COBOL中执行操作;

char name[8]; /* a variable called name that is eight characters */
01 NAME PIC X(08).

或者如果像C那样定义的话

01 NAME-ARRAY05 NAME PIC X OCCURS 8 TIMES.

实际上,C语言中的字符数组将始终以空字符结尾,因此,如果需要八个字符数组,则需要将其设置为九个,以解决最后的空字符。

将字符数组初始化为C中空格的唯一方法是将单个字符移动到数组的每个元素。 这是您在两种语言中的选择;

01 NAME PIC X(08) VALUE SPACES.

要么

MOVE SPACES TO NAME.

要么

INITIALIZE NAME.


字符名称[9];
对于&#xff08;i &#61; 1; i <&#61; 9; i &#43;&#43;&#xff09;
name [i] &#61;”“;

很讨厌吧&#xff1f; 我将在C语句中解释所有后来没有意义的事情。 C还可以区分字符和字符串。 由于&#39;char&#39;类型只真正声明一个字符&#xff0c;因此不需要以null结尾的字符&#xff0c;因此这两个声明是不同的&#xff1b;

char switch;
char switch2[1];

实际上&#xff0c;由于字符串上的空终止符&#xff0c;您实际上需要将&#39;switch2&#39;设置为两个字符的数组&#xff0c;以使其按预期的方式运行。 在C中用\ 0定义了一个null&#xff0c;并且所有的字符串操作函数都依赖于null字符的正确位置&#xff0c;以便获得预期的输出。

例如&#xff0c;如果您想将我们的字符变量开关初始化为Y&#xff0c;则可以将其括在单引号字符&#39;&#xff0c;即&#39;Y&#39;中。 单引号表示它是一个字符&#xff0c;而对于switch2&#xff0c;您将使用双引号”将字符串括起来&#xff0c;即“ Y”。 您必须直截了当&#xff0c;这很重要&#xff0c;如果您使用不正确&#xff0c;一些编译器不会抱怨&#xff0c;您可能会得到一些真正无法预测的结果。

既然我们知道如何在C中声明简单变量&#xff0c;我们将如何声明类似于COBOL中01变量声明的记录结构&#xff1f; 尽管实现有些奇怪&#xff0c;但在C语言中有一种用于此确切目的的“结构”。 首先让我们在COBOL中声明一个简单的布局&#xff0c;然后在C中进行相同的操作&#xff1b;

01 CUST-MAST03 CM-NUMBER PIC X( 06 ).03 CM-NAME PIC X( 30 ).03 CM-AMT-OWE PIC S9( 9 ) COMP.03 CM-YTD-BAL PIC S9( 9 ) COMP OCCURS 12.03 CM-PHONE PIC X( 10 ).
struct customer_master {char cm_number[ 7 ];char cm_name[ 31 ];long cm_amt_owe;long cm_ytd_bal[ 12 ];char cm_phone[ 10 ];};
struct customer_master cust_mast;

“ struct”动词声明您所关注的记录类型的模板&#xff0c;一旦声明了模板&#xff0c;您就可以声明一个属于该结构类型的变量。 所以这行&#xff1a;struct customer_master cust_mast声明变量&#39;cust_mast&#39;为&#39;customer_master&#39;类型。 然后&#xff0c;您可以通过指定变量名称点成员&#xff08;即cust_mast.cm_name&#xff09;来引用结构的成员。如果您打算将结构复用用于其他目的&#xff0c;这将特别方便。 这里的缺点是没有一种简便的方法可以在不单独寻址每个成员的情况下初始化结构内部的变量。 COBOL具有非常方便的INITIALIZE动词来执行此操作&#xff0c;但是您可以在C中编写一个通用的初始化函数&#xff0c;该函数可以实现相同的目的。 如果不想重复使用结构&#xff0c;则可以在声明的同时命名结构。 在}之后和之前&#xff1b; 只需输入您希望它具有的任何旧变量名即可。 工作存储部分中使用的最后一个常用动词是REDEFINES。 C版本是“联合”动词。 重定义对于使用字母或数字变量非常方便。 由于字节引用是在COBOL-85中引入的&#xff0c;因此您几乎再也看不到用于获取变量中各个子字符串的REDEFINE语句。 现在让我们看一下如何声明一个REDEFINE和一个“ union”。

01 CUST-MASTER03 CM-DAYS-LATE PIC XXX.03 CM-DL-REDEFINE REDEFINES CM-DAYS-LATE.05 CM-DL-NUM PIC 999.
union redef {char days_late[ 4 ];int dl_num;};
union redef days_late_test;

联合的设置和使用与结构非常相似&#xff0c;您甚至可以将联合放入结构中&#xff0c;无论如何&#xff0c;您通常都希望在该结构中使用联合。 我们将&#39;days_late&#39;的字符数组设置为4&#xff0c;因为我们必须记住要考虑空字符。 如果愿意的话&#xff0c;您可以用工会做各种奇怪的事情&#xff0c;但这实际上是我要讲的。

我想谈谈的另一种类型是枚举类型。 通过使用“ enum”关键字&#xff0c;我们可以创建一个新的“类型”并指定其可能具有的值。 &#xff08;实际上&#xff0c;“枚举”是类型“ int”&#xff0c;因此我们确实为现有类型创建了一个新名称。&#xff09;枚举类型的目的是帮助使程序更具可读性&#xff0c;例如COBOL 88级别。 语法类似于用于结构的语法。

enum ranges {min &#61; 10, max &#61; 100, mid &#61; 55};
enum ranges tester;
tester &#61; mid;
if (tester > min)

if语句将是正确的&#xff0c;因为tester的值为55。我建议&#xff0c;如果您想使用枚举类型&#xff0c;则在它们上面读取的内容要比我在这里所涉及的要多得多。

关于变量声明&#xff0c;我要说的最后一点是&#xff0c;与COBOL相比&#xff0c;C几乎没有应用编辑掩码的功能。 这使得它成为编写报告的一种不太方便的语言&#xff0c;并且在其中广泛使用日期和美元编辑掩码的情况下。

操作员

首先让我们看一下C中&#61;和&#61;&#61;之间的区别。在COBOL中&#xff0c;有几种方法可以将数据获取到变量中。 一种常见的方式是MOVE动词&#xff0c;C中的等价词&#61;。 这是令人困惑的&#xff0c;因为如果您设置逻辑测试并使用&#61;&#xff0c;则它将始终评估为true&#xff0c;因为等号右侧的值将分配给左侧的变量。 如果要比较值&#xff0c;则需要使用&#61;&#61;。 这是一个简单的错误&#xff0c;可能导致各种问题。 如果在CI中要说

if(my_int &#61; 5)

将会发生的是&#xff0c;将为变量“ my_int”分配值5&#xff0c;并且由于分配成功进行&#xff0c;因此它将返回一个非零值&#xff0c;该值表示true。 这将使&#39;if&#39;语句评估为true。 因此&#xff0c;这个“如果”陈述将永远是正确的。 简单的错误&#xff0c;重大的影响以及编译器不会抱怨它&#xff0c;因为它是有效的语句。 确保您尽早了解&#61;和&#61;&#61;之间的区别&#xff0c;并且永远不要忘记它。

我们的下一个布尔运算符是“ AND”。 COBOL使在IF语句中比较多个值变得非常容易。

IF (VAR1 &#61; VAL1) AND (VAR2 &#61; VAL2 OR VAL3) THEN

“ AND”的C表示形式为“ &&”&#xff0c;“ OR”为“ ||”&#xff0c;“ NOT EQUAL”由“&#xff01;&#61;”标识。

这些都不是特别难于学习的&#xff0c;但是当他们第一次学习该语言时&#xff0c;它们都不如直观。

发挥创造力&#xff0c;您可以利用#define来使操作员随心所欲。

#define AND &&
#define OR ||
#define NOT !&#61;
#define EQUALS &#61;&#61;

现在&#xff0c;这可能会打扰其他C程序员&#xff0c;但是如果它可以帮助您提高代码的可读性和易维护性&#xff0c;谁会说这是错误的&#xff1f;

转让经营者

由于我已经讨论过C中的&#61;符号等效于COBOL MOVE动词&#xff0c;因此不再赘述。 但是&#xff0c;在C中使用&#61;符号的另一种选择是使用字符串函数&#39;strcpy&#39;。 这会执行“字符串复制”到变量中。 这是初始化字符数组并确保正确放置null的好方法&#xff08;strcpy将null附加到复制的字符串的末尾&#xff09;&#xff0c;特别是如果您以后要向字符串附加数据。 C中用于附加字符串的动词是“字符串连接”的“ strcat”。 在COBOL中&#xff0c;我们有“ STRING”动词&#xff0c;它使您可以更好地控制变量的连接方式。 &#39;strcat&#39;所做的所有工作就是将一个字符复制到另一个字符数组中&#xff0c;直到它从一个终止的null开始到另一个字符数组为止。 现在您可以看到为什么在正确的位置放置null如此重要。

我绝对喜欢C中的几个非常酷的增量运算符快捷方式。 例如&#xff0c;在COBOL中&#xff0c;如果您想在循环中递增变量&#xff0c;则可以通过两种方法来实现&#xff1a;

ADD 1 TO KOUNT
COMPUTE KOUNT &#61; KOUNT &#43; 1
ADD 1 TO KOUNT GIVING KOUNT
PERFORM VARYING KOUNT FROM 1 BY 1 UNTIL KOUNT >&#61; MAX

在C语言中&#xff0c;您可以说以下内容&#xff1b;

kount &#61; kount &#43; 1
kount &#43;&#61; 1
kount &#43;&#43;
for (kount &#61; 1; kount >&#61; max; kount&#43;&#43;)

第一个示例应该是显而易见的&#xff0c;在第二个示例中&#43; &#61;是第一个示例的快捷方式&#xff0c;这意味着在右侧的计算中将&#61;号左侧的变量包括在内。 第三个示例意味着将值增加1。我们的前两个示例在加法中可以具有任何值&#xff0c;但是第三个示例仅增加1。 最后一个示例与最后一个COBOL示例相同。 有趣的是最后一个参数“ kount &#43;&#43;”&#xff0c;通过将&#43;&#43;放在变量的右边&#xff0c;我们说在测试变量是否大于或等于“ max”后增加变量。 如果将&#43;&#43;放在左侧&#xff08;如“ &#43;&#43; kount”中一样&#xff09;&#xff0c;则意味着在进行测试之前先递增。 这与PERFORM指令“先测试后”或“后测试”相同。 -符号可用于以完全相同的方式递减&#xff0c;即&#61;或–。

逻辑结构

希望这里的每个人都熟悉COBOL PERFORM语句。 它具有比我想了解的更多的变化&#xff0c;但这是它唯一的循环构造&#xff0c;除非您使用GO TO计数。 C提供了几种不同的循环控件。

while
do..while
for

现在&#xff0c;COBOL将“ while”和“ for”循环的功能很好地整合到了PERFORM中。 但是&#xff0c;“ do..while”循环并不完全相同&#xff0c;您可以通过正确控制变量来模拟它。 从本质上讲&#xff0c;“ while”和“ do..while”之间的区别是在“ do..while”循环中&#xff0c;它将至少“执行”一次循环&#xff0c;因为测试直到循环结束后才进行执行一次。 在“ while”循环中&#xff0c;您的测试在第一次执行时可能无效&#xff0c;因此您可能永远不会真正通过循环。

int i &#61;21 ;
while (i&#43;&#43; <20 ) {printf ("% d \ n ", i );
}
/* the above line will display nothing since i is already greater than 20 */
do
{printf ("% d \ n ", i );
} while ( i &#43;&#43; <20 );
/* the above line will display 21 */

让我们谈谈&#39;if&#39;语句&#xff0c;这是一个字符串比较操作如何令人困惑的示例。 在COBOL中&#xff0c;以下语句非常简单

IF STRING1 IS EQUAL TO STRING2 or IF STRING1 &#61; STRING2

您无法在C中以这种方式比较字符串。在&#39;string.h&#39;头文件中有一个函数可以比较两个字符串&#xff0c;但是&#xff0c;要获得相同的结果&#xff0c;必须使用以下措辞&#xff1b;

if (!strncmp(string1,string2)) {

让我解释一下&#xff0c;首先是“ strncmp”是一个字符串比较函数&#xff0c;如果string1小于string2&#xff0c;那么将返回一个小于零的值&#xff08;类似于在COBOL中使用条件代码&#xff09;。 如果string1等于string2&#xff0c;则返回零值。 如果string1大于string2&#xff0c;则返回大于零的值。 问题是&#xff0c;如果在IF语句中使用strncmp且字符串相等&#xff0c;则返回零&#xff0c;零表示IF语句为假&#xff0c;这就是我们在&#39;strncmp&#39;前面加&#39;&#xff01;&#39;的原因。 这意味着不是。 如果string1和string2相等&#xff0c;则最终结果是返回非零值&#xff08;对于IF语句为TRUE&#xff09;。 这也进一步说明了如何将逻辑表达式嵌入“ if”语句中。

输入/输出

C语言完全没有任何I / O设施&#xff0c;这是很幸运的。 那么&#xff0c;您如何执行任何类型的终端或文件I / O&#xff1f; 幸运的是&#xff0c;在C语言编程的黑暗年代&#xff0c;有人写了Standard I / O标头文件。 因此&#xff0c;如果要执行任何I / O&#xff0c;则必须包含。 我将讨论stdio中包含的一些更基本的功能。

stdio中最常用的功能是“ printf”和“ scanf”。 “ printf”用于向STDLIST显示信息&#xff0c;“ scanf”用于从STDIN读取信息。 这两个功能在其用法中都具有广泛的格式化功能。 COBOL很不错&#xff0c;因为您可以使用DISPLAY和ACCEPT来读取或写入几乎任何所需的内容。 但是&#xff0c;您不能在语句本身中进行类型转换或变量格式化&#xff0c;因此必须首先在工作存储中声明一个格式化变量。 尽管C几乎没有声明格式化变量的功能&#xff0c;但是它确实为您提供了对格式化输出的广泛控制。 一个简单的示例将显示一个具有两个小数点的整数。

01 EDIT-INT PIC ZZ9.99
01 MY-INT PIC S9(3)V99.
MOVE MY-INT TO EDIT-INT.
DISLAY EDIT-INT.

浮动my_int;
printf&#xff08;“&#xff05;3.2f \ n”&#xff0c;my_int&#xff09;;

如您所见&#xff0c;如果使用C语言进行格式化&#xff0c;则较不直观。 “ printf”的工作方式是在第一个参数&#xff08;即引号内的部分&#xff09;中使用文字和/或格式字符串。 然后将变量替换作为第二个参数。 然后\ n表示在这一点上换行。 这是嵌入文本的示例&#xff1b;

printf("I have %d apples and %d oranges",count_apple, count_orange);

这会将“ count_apple”替换为第一个参数&#xff0c;并将“ count_orange”替换为第二个参数。 “ printf”中几乎有十二种不同的格式化程序。

“ printf”的另一个有趣的功能是它具有类型转换的能力&#xff0c;在这个例子中&#xff0c;您需要知道&#xff05;d表示打印一个整数&#xff0c;&#xff05;c表示打印一个字符。

printf("%c %d\n", &#39;A&#39;, &#39;A&#39;);

您认为这将产生什么结果&#xff1f; 您可能错了&#xff0c;您会看到“ A 65”&#xff0c;因为通过为字母字符“ A”指定&#xff05;d会将其格式化为“ A”的十进制ASCII码&#xff08;即65&#xff09;。

与“ printf&#xff08;&#xff09;”类似&#xff0c;“ scanf&#xff08;&#xff09;”使用控制字符串&#xff0c;后跟参数列表。 主要区别在于参数列表。 Printf&#xff08;&#xff09;使用变量名称&#xff0c;常量和表达式。 Scanf&#xff08;&#xff09;使用指向变量的指针。 幸运的是&#xff0c;使用该函数我们无需了解任何有关指针的知识。 只要记住以下两个规则&#xff1a;

1.如果要读取基本变量类型的值&#xff0c;请在变量名称前加上&#xff06;。
2.如果要读取字符串变量&#xff0c;请不要使用&#xff06;。

这是显示输出并提示输入的简短示例&#xff1a;

main()
{
int age;
float assets;
char pet[30];
printf("enter your age, assets, and favorite pet.\n");
scanf("%d %f", &age, &assets);
scanf("%s", pet); /* no & for char array */
printf("%d $%.0f %s\n ", age, assets, pet);
}

如果要运行它将看起来像这样。

输入您的年龄&#xff0c;资产和喜爱的宠物。
32
10507.32
戊quin
32 $ 10507企鹅

有趣的一点是&#xff0c;scanf&#xff08;&#xff09;一次可以读取多个变量&#xff0c;这与COBOL ACCEPT动词不同。 关于printf&#xff08;&#xff09;的最后一点&#xff0c;以下2条语句工作相同&#xff1a;

printf("Enter your option ");
DISPLAY "Enter your option " NO ADVANCING.

正如我前面提到的&#xff0c;C是针对单个字符而不是字符串的。 因此&#xff0c;stdio中有一整套的功能&#xff0c;旨在读取和写入单个字符。 由于COBOL很少关心您要使用的数组大小&#xff0c;因此我不打算赘述&#xff0c;只记得这四个函数的名称即可。

getchar
putchar
getc
putc

在开始展示一些小程序外壳程序之前&#xff0c;我将仅介绍另外两个COBOL动词比较。 我最喜欢的两个动词是STRING和UNSTRING&#xff0c;它们用于连接变量和文字&#xff0c;并根据用户定义的标记解析字符串。 通常&#xff0c;它们非常易于使用&#xff0c;而C语言却不是。 我将只运行COBOL示例&#xff0c;然后在C中显示完全相同的代码。

01 FULL-NAME.03 FN-FILE PIC X( 08 ) VALUE "MYFILE" .03 FN-GROUP PIC X( 08 ) VALUE "MYGROUP" .03 FN-ACCOUNT PIC X( 08 ) VALUE "MYACCT" .
01 WS-FULL-NAME PIC X( 26 ) VALUE SPACES.
PROCEDURE DIVISION.A1000-START. DISPLAY FULL-NAME.
* displays "MYFILE MYGROUP MYACCT" STRING FN-FILE DELIMITED BY SPACES "." DELIMITED BY SIZE FN-GROUP DELIMITED BY SPACES "." DELIMITED BY SIZE FN-ACCT DELIMITED BY SPACES INTO WS-FULL-NAME. DISPLAY WS-FULL-NAME.
* displays "MYFILE.MYGROUP.MYACCT"
MOVE SPACES TO FULL-NAME.
UNSTRING WS-FULL-NAME DELIMITED BY "." INTO FN-FILE FN-GROUP FN-ACCT.
DISPLAY FULL-NAME.
* displays "MYFILE MYGROUP MYACCT"
#include
#include
main()
{
char ws_full_name[ 27 ];
struct full_file_name { char file[ 9 ]; char group[ 9 ]; char acct[ 9 ];
} fn;
strcpy(fn.file, "MYFILE" );
strcpy(fn.group, "MYGROUP" );
strcpy(fn.acct, "MYACCT" );
strcpy(ws_full_name,fn_file);
strcat(ws_full_name, "." );
strcat(ws_full_name,fn_group);
strcat(ws_full_name, "." );
strcat(ws_full_name,fn_acct);
printf( "%s\n" ,ws_full_name);
/* displays "MYFILE.MYGROUP.MYACCT" */

您知道&#xff0c;我不打算展示与UNSTRING相当的东西&#xff0c;如果您刚开始使用C的话&#xff0c;那就太令人困惑了。该函数称为“ strtok”&#xff0c;它要求您使用指向字符串的指针&#xff0c;并且因为我根本没有真正了解指针&#xff0c;所以我不想混淆这个问题。 但是请记住&#xff0c;您必须了解C中的指针是如何工作的&#xff0c;否则您将永远无法有效地使用该语言。 只是对指针的完整讨论超出了本文的范围。

无论如何&#xff0c;在我们的C示例中&#xff0c;我们使用了&#39;strcpy&#39;命令将字符串复制到变量中。 该函数还添加了空终止符&#xff0c;并从本质上初始化了字符数组。 使用“ strcat”函数&#xff0c;将第二个参数中的字符串连接到第一个参数中命名的变量。 它寻找空终止符&#xff0c;然后开始将字符串写入其中。

如您所见&#xff0c;用C处理字符串比使用COBOL更加困难和and回。 现在不要误解&#xff0c;我认为C在某些方面很有用&#xff0c;只是如果您在编码标准业务类型应用程序&#xff0c;则不需要很多。

代码骨架

好的&#xff0c;那么您要做什么用C编写程序&#xff1f; 如您所知&#xff0c;COBOL必须使用四个分区。

IDENTIFICATION DIVISION
ENVIRONMENT DIVISION
DATA DIVISION
PROCEDURE DIVISION

每个方面都有其自己的目的&#xff0c;即所描述的内容。 在C语言中&#xff0c;一切都基于函数。 如您在前面的示例中所见&#xff0c;我在程序顶部有“ main&#xff08;&#xff09;”。 您可以将main&#xff08;&#xff09;视为PROCEDURE DIVISION。 就像C程序中的其他所有功能一样&#xff0c;它是一个函数&#xff0c;通常它是您必须拥有的唯一函数。 我之所以这样说&#xff0c;通常是因为如果您要编写将要进入RBM的一系列子例程&#xff0c;则无需命名函数main&#xff08;&#xff09;。

因此&#xff0c;要用C编写经典的“ Hello World”程序&#xff0c;这就是您需要做的所有事情。

#include
main();
{
printf("Hello World\n");
}

这比在COBOL下所需的代码少得多&#xff0c;但仍然比您在BASIC中要做的要多。 我在这里看到的问题是&#xff0c;仅对于一个printf&#xff08;&#xff09;语句就必须执行stdio.h的包含&#xff0c;这将导致您的程序对于某些琐碎的事情而言相当大。

编码的便携性或速度

您会听到许多关于可移植C的知识&#xff0c;以及如何编码可移植性。 平台之间的变化是如此之多&#xff0c;以至于为可移植性编写代码确实很繁琐。 我知道有很多工具包可以帮助解决这个问题&#xff0c;例如Qt&#xff0c;但是我们在这里只是在讨论原始代码。

如果您编码以利用CPU的本机体系结构&#xff0c;则将看到速度大大提高&#xff0c;代码大小减小了。 如果使用本机语言构建可移植性代码&#xff0c;则您的程序将更大&#xff0c;更慢。 如果您希望两全其美&#xff0c;则需要编写自己的中间包含文件&#xff0c;以允许您在体系结构之间进行切换。

摘要

那么我从这一切中得出什么结论呢&#xff1f; 在告诉您之前&#xff0c;让我告诉您我读过的一封信&#xff0c;该信是某人发给《计算机语言》杂志的。 这位先生很生气&#xff0c;因为他们不愿意将COBOL包括在他们的杂志中&#xff0c;如果他们打算这样做&#xff0c;那么他们也应该包括RPG&#xff0c;因为他们都不是真正的语言。 他使用真实语言的标准几乎由您在C中可以完成的一些事情构成&#xff0c;而您在C中无法做到。 例如使用指针和声明局部变量。 那么&#xff0c;为什么这位先生喜欢那么多没有内置I / O功能的语言&#xff0c;并且将字符串作为字节数组来处理&#xff1f;

现在&#xff0c;这一定是我见过的更精明的陈述之一。 COBOL是用于业务应用程序的最受欢迎的语言之一&#xff0c;尽管我不喜欢RPG&#xff0c;但IBM确保它也保持了庞大的安装基础。 那么&#xff0c;为什么我要提这个呢&#xff1f; 因为正如我在揭幕战中所说的那样&#xff0c;那里仍然有大量的COBOL&#xff0c;而且它可能正在管理您的薪水和投资&#xff0c;所以不要太快打折。

翻译自: https://hackernoon.com/c-from-a-cobol-perspective-444dc30554d6

c 调用 cobol



推荐阅读
  • 本文介绍了使用哈夫曼树实现文件压缩和解压的方法。首先对数据结构课程设计中的代码进行了分析,包括使用时间调用、常量定义和统计文件中各个字符时相关的结构体。然后讨论了哈夫曼树的实现原理和算法。最后介绍了文件压缩和解压的具体步骤,包括字符统计、构建哈夫曼树、生成编码表、编码和解码过程。通过实例演示了文件压缩和解压的效果。本文的内容对于理解哈夫曼树的实现原理和应用具有一定的参考价值。 ... [详细]
  • 学习SLAM的女生,很酷
    本文介绍了学习SLAM的女生的故事,她们选择SLAM作为研究方向,面临各种学习挑战,但坚持不懈,最终获得成功。文章鼓励未来想走科研道路的女生勇敢追求自己的梦想,同时提到了一位正在英国攻读硕士学位的女生与SLAM结缘的经历。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • 本文介绍了解决二叉树层序创建问题的方法。通过使用队列结构体和二叉树结构体,实现了入队和出队操作,并提供了判断队列是否为空的函数。详细介绍了解决该问题的步骤和流程。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • Android源码深入理解JNI技术的概述和应用
    本文介绍了Android源码中的JNI技术,包括概述和应用。JNI是Java Native Interface的缩写,是一种技术,可以实现Java程序调用Native语言写的函数,以及Native程序调用Java层的函数。在Android平台上,JNI充当了连接Java世界和Native世界的桥梁。本文通过分析Android源码中的相关文件和位置,深入探讨了JNI技术在Android开发中的重要性和应用场景。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • 李逍遥寻找仙药的迷阵之旅
    本文讲述了少年李逍遥为了救治婶婶的病情,前往仙灵岛寻找仙药的故事。他需要穿越一个由M×N个方格组成的迷阵,有些方格内有怪物,有些方格是安全的。李逍遥需要避开有怪物的方格,并经过最少的方格,找到仙药。在寻找的过程中,他还会遇到神秘人物。本文提供了一个迷阵样例及李逍遥找到仙药的路线。 ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • JDK源码学习之HashTable(附带面试题)的学习笔记
    本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
  • 本文介绍了Codeforces Round #321 (Div. 2)比赛中的问题Kefa and Dishes,通过状压和spfa算法解决了这个问题。给定一个有向图,求在不超过m步的情况下,能获得的最大权值和。点不能重复走。文章详细介绍了问题的题意、解题思路和代码实现。 ... [详细]
  • Iamtryingtocreateanarrayofstructinstanceslikethis:我试图创建一个这样的struct实例数组:letinstallers: ... [详细]
  • Gitlab接入公司内部单点登录的安装和配置教程
    本文介绍了如何将公司内部的Gitlab系统接入单点登录服务,并提供了安装和配置的详细教程。通过使用oauth2协议,将原有的各子系统的独立登录统一迁移至单点登录。文章包括Gitlab的安装环境、版本号、编辑配置文件的步骤,并解决了在迁移过程中可能遇到的问题。 ... [详细]
author-avatar
佳妤善真1729
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有