Boy you must be a glutton for punishment if you are back from more COBOL vs. C. Last month we covered operators and looping constructs. This month is dedicated to Input/Ouput (I/O) for the two languages. This is a fairly lengthy topic, and I don't pretend to cover every permutation, but this should be more than adequate to get you started.
I/O
C is blessed with having no I/O facilities built into the language at all. Sort of like SPL, but SPL has the advantage of using the I/O intrinsics easily. So how do you do any sort of terminal or file I/O? Fortunately somebody back in the dark ages of C programming wrote the Standard I/O header file. So if you want to do any I/O you must include <stdio.h>. I will talk about some of the more basic features and functions included in stdio.
The most commonly used functions from stdio are 'printf' and 'scanf'. 'printf' is used to display information to STDLIST and 'scanf' is used to read information from STDIN. Both of these functions have extensive formatting capabilities included in their usage. COBOL is nice because you can use DISPLAY and ACCEPT to read or write virtually anything you want. You can't however do type conversion or variable formatting in the statements themselves, you would have to declare a formatting variable in working storage first. While C gives very little to no capability for declaring formatting variables, it does give you extensive control over formatting your output. A simple example would be displaying an integer that has two decimal points.
01 EDIT-INT
PIC ZZ9.99
01 MY-INT
PIC S9(3)V99.
MOVE MY-INT TO EDIT-INT.
DISLAY EDIT-INT.
float my_int;
printf("%3.2f\n",my_int);
As you can see, it's simpler to format in C, if somewhat less intuitive.
The way
'printf' works is that it takes a literal and/or formatting string
at the first
paramter, which is the part inside the quotes. And then takes
variable substitution
the second parameter. Then \n means issue a new line at that
point. Here is an
example of embedded text;
printf("I have %d apples and %d oranges",count_apple, count_orange);
This would substitute 'count_apple' into the first parameter and 'count_orange' into the second. There are almost a dozen different formatters available in the 'printf'. Another interesting feature of 'printf' is it's ability to do type conversion, for this example you need to know that %d means print an integer and %c means print a character;
printf("%c %d\n", 'A', 'A');
what do you think the output of this would be? Odds are you guessed wrong, you would see "A 65" because by specifying %d for the alpha character 'A' it would format it to the decimal ASCII code for 'A', which is 65. COBOL will automatically display a data in it's correct native format for you, however it doesn't give you the ability to do type conversion on the fly on the way out. I don't know if this is good or bad since I almost never need to do something like this.
Like 'printf()', 'scanf()' uses a control string followed by a list of arguments. The main difference is in the argument list. Printf() uses variable names, constants, and expressions. Scanf() uses pointers to variables. Fortunately, we don't have to know anything about pointers to use the function. Just remember these two rules:
1. If you want to read a value for a basic variable type, precede the variable name with an &. 2. If you want to read a string variable, don't use an &.
Here is a short example of displaying output and prompting for input:
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);
}
Which would look something like this if you were to run it.
enter your age, assets, and favorite pet.
32
10507.32
penquin
32 $10507 penguin
An interesting point here is that the scanf() can read more than one variable in at a time, unlike the COBOL ACCEPT verb. One last point on printf(), the following 2 statements work identically:
printf("Enter your option "); DISPLAY "Enter your option " NO ADVANCING. As I mentioned earlier, C is geared towards single characters, not strings. So there is a whole set of functions in stdio that are geared towards reading and writing single characters. Since COBOL cares very little about how big an array you use to read or write I am not going to get into the specifics, just remember these four functions names;
getchar
putchar
getc
putc
You could use the MPE file I/O intrinsics if you didn't want to use the functions in stdio. You can even mix and match the two I/O facilities if you wish, just like you can in COBOL.
I am going to cover just two more COBOL verb comparisons before I get into showing some small program shells. Two of my favorite verbs are STRING and UNSTRING, they are used to concatenate variables and literals and to parse strings based on user defined tokens. In general they are very easy to use, their C counterparts however aren't. I will just run through the COBOL example and then show the exact same code in 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 <stdio>
#include <string>
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" */
You know, I don't think I am going to show the equivalent of UNSTRING, it is just to confusing if you are just getting started with C. The function is called 'strtok' and it requires that you use pointers to strings, and since I didn't really get into pointers at all I don't want to confuse the issue. Keep in mind however that you MUST understand how pointers in C work or you will never be able to use the language effectively. It's just that a full discussion of pointers is beyond the scope of this paper.
Anyway, in our C example we used the 'strcpy' command to copy a string into a variable. The function also adds the null terminator and essentially initializes our character array. Using the 'strcat' function, concatenates the string in the second parameter to the variable named in the first parameter. It looks for the null terminator and then starts writing the string onto it.
As you can see, it is more difficult and roundabout to deal with strings in C t han COBOL. Now don't get the wrong idea, I think C is great for some things, it's just that if you are coding a standard business type application a lot of those things aren't necessary.
We have just about wrapped up our discussion on C and COBOL here. I have one more installment were I am going to show some code skeletons, talk about portability, and wrap up. That means we are going to have to come up with some ideas for the Christmas issue.