With a few exceptions, C++ contains ANSI C as a subset. Bjarne Stroustrup, who developed C++ in the early 1980s, wrote, "The name signifies the evolutionary nature of the changes from C. '++' is the C increment operator....The language is not called D, because it is an extension of C that does not attempt to remedy problems by removing features." C is a procedural language with its emphasis on function calls, while C++ is a hybrid of procedural and object-oriented languages. In this module, we consider syntax that will enable a C++ programmer to code in C.


Comments

Many versions of C now allow a double slash (//) to indicate that the remainder of the line is a comment, such as

// declarations
int i; // index

This new syntax allows us to comment out a line easily.

However, in ANSI C a comment begins with the two characters /* and ends with */, with no space between the two characters, and a comment cannot contain */ as part of its text. Since there is no nesting of comments in C, there is a danger of a comment that already exists in a segment will cause a premature end to a comment. For example, consider the following C segment.

pressure = ComputePressure(volume); /* calculate pressure */
PrintPressure(volume, pressure);

If during debugging, we attempt to comment out this segment and do not notice the internal comment, an error arises.

/*
pressure = ComputePressure(volume); /* calculate pressure */
PrintPressure(volume, pressure);
*/

The first */ ends the comment, and the second produces an error. To avoid the problem in C of "commenting out" a segment containing comments, we use preprocessor directives, such as

#if 0
pressure = ComputePressure(volume); /* calculate pressure */
PrintPressure(volume, pressure);
#endif

Quick Review Question
Quick Review Question 1
a. Give the character(s) to begin an ANSI C comment.

b. Give the character(s) to end an ANSI C comment.

c. Typing at most one blank, give the preprocessor directive to begin a segment that the compiler should ignore.

d. Give the preprocessor directive to end a segment that the compiler should ignore.
 
Call by Reference

Functions are an essential ingredient of structured programming. In the strictest sense, C offers only one method of passing a value from an argument (in the calling routine) to a parameter (in the called function), call by value or pass by value. When a function is called, a memory location is created for the parameter, and the value of the argument is copied to that location. Then, all communication is severed between the argument and parameter. A change in the value of the parameter does not effect the value of the corresponding argument.

Definition Pass by value is a method of passing information to a function whereby the parameter receives a copy of the value of the argument.

Many times the function must communicate values back to the calling routine. The function can return one value. If there are more than one, then the function must use pointers as parameters. The value of the pointer, which is the address it contains, cannot change; but the value of the memory location to which it points can. For example, suppose we need to call a routine to swap the contents of two int variables. The swap routine in ANSI C must use pointers to those variables. Within the routine, we dereference the pointers to access the contents of those variables.

/*
* ANSI C function to swap values
* Pre: x_ptr and y_ptr point to integers.
* Post: The values of *x_ptr and *y_ptr have been swapped.
*/

void swap(int *x_ptr, int *y_ptr)
{
int temp;

temp = *x_ptr;
*x_ptr = *y_ptr;
*y_ptr = temp;
}

The calling function passes to swap the addresses of the variables whose values we wish to switch. After execution of the following segment, a has the value 5, and b is 3.

int a = 3,
b = 5;
.
.
.
/* call ANSI C swap to exchange values of a and b */
swap(&a, &b);

Figure 1 shows the action of C's swap with a calling function of main.

Figure 1. Action of swap in ANSI C with a calling function of main




C does not have the call by reference or pass by reference mechanism for binding arguments and parameters that C++ has. With this method, the computer does not create a new memory location for a parameter, but allows it to share the memory location of the corresponding argument. To indicate that the parameter should be by reference, C++ uses an ampersand immediately after the type, such as with the following prototype:

void swap(int&, int&);

Thus, the function definition for swap is as follows:

//
// C++ function to swap values
// Pre: x and y are integer variables.
// Post: The values of x and y have been swapped.
//

void swap(int& x, int& y)
{
int temp;
temp = x;
  x = y;
y = temp;
}

To invoke this function in C++, we only need to use integer arguments, such as

int a = 3,
b = 5;
.
.
.
// call C++ swap to exchange values of a and b
swap(a, b);

Quick Review Question
Quick Review Question 2 In the answers, type exactly one blank before and no blanks after any asterisk.
a. Complete the prototype of a C function GetRate to communicate the value of a float value through the use of a pointer parameter rate_ptr.
void GetRate(___rate_ptr);

b. Complete the call to GetRate to obtain a value for the variable rate.
GetRate(___);				

c. Suppose the definition of GetRate places 5 in the location to which rate_ptr points, so that rate obtains the value 5. Complete the assignment in GetRate:
___ = 5;				
 
Standard Streams

Input and output are not part of the formal definition of the language C. Instead, the standard stream I/O library defines C I/O functions and macros. These routines handle the input and output of sequences of characters or streams of data.

In C programs, we include the I/O header file stdio.h instead of the C++ header file iostream.h. The C++ input stream cin corresponds to the standard C input stream stdin. The output stream cout is comparable to stdout; and cerr is analogous to stderr. Instead of the extraction operator (>>) for input and an insertion operator (<<) for output, C employs the function scanf for reading and printf for printing, respectively. For example, in C++, we can have the following segment:

cout << "Enter the price:";
cin >> price;
cout << "Enter the quantity: ";
cin >> quantity;
cout << "Quantity = " << quantity <<
" Total = " << price * quantity << '\n';

The equivalent segment in C is as follows:

printf("Enter the price: ");
scanf("%f", &price);
printf("Enter the quantity: ");
scanf("%d", &quantity);
printf("Quantity = %d Total = %f\n", quantity, price * quantity);

Because we are reading and returning values for price and quantity, an ampersand appears before each identifier in the calls to scanf. In C, we must specify how to convert between a value's internal format in memory and an external format with a conversion specification. The conversion specification %f is for a float or double value, and %d is for int. Printing a floating point number with the conversion specification of the form %m.nf (such as %9.2f) displays the number right-justified in a field width of m (such as 9 characters for the field width) with n digits after the decimal point (such as 2 places after the decimal). The compiler does not detect an incorrect conversion specification or the omission of & when necessary, but either error leads to unpredictable results.

Definition A conversion specification specifies to what notation the computer should convert a value for input or output operations.

Quick Review Question
Quick Review Question 3  In your answers, use exactly one blank after any comma, single blanks between words in quotation marks, and no other blanks.
a. Write a C statement to read a value for the integer variable num.

b. Write a C statement to print "The number is ", the value for the integer variable num, a period, and the new line character. Thus, if num has the value 5, the output appears as follows with subsequent output another line:
The number is 5.		

c. Give the conversion specification to display the number 27.5 so that exactly 3 blanks appear before the number and one digit (5) appears after the decimal point.
 
Strings

A string or character string is any group of characters enclosed in quotation marks. There is no string type in C. The language, however, treats an array of type char as a string if the ASCII value 0, the null character '\0', follows its last meaningful character We sometimes refer to a character string constant, such as "computer", as a string literal. The length of a string is the number of non-null characters it contains, so the number of locations needed to store a string is one more than the string's length. The type of a string literal is char *. The declaration

char str[] = "computer";

is an abbreviation for the declaration

char str[] = { 'c', 'o', 'm', 'p', 'u', 't', 'e', 'r', '\0' };

To print the string that the char array str stores, we can use the %s conversion specification with printf , such as

printf("%s\n", str);

A minus in front of a field width, such as %-9s, causes the string to be left-justified. To read or print one character, we employ the conversion specification %c, such as

printf("The first character is %c.\n", str[0]);

With the conversion specification %s , we can read a string into str using a scanf statement:

scanf("%s", str);     /* No & before string variable str */

Since the array name is a pointer to the first element in the array, we use str without a subscript; and there is no ampersand (&) before the array name. We can use a maximum field width with the %s specification in reading a string. For example, for the char array, str, of 10 elements, we use %9s to read no more than 9 characters and ensure against overflow of the array.

scanf("%9s", str);

The header file stdio.h declares BUFSIZ to be the size of the area of memory that holds the input stream. We can declare str to be of that length with

char str[BUFSIZ];

Quick Review Question
Quick Review Question 4
a. Suppose alloy is a 14-element char array. Complete the statement to read no more than the maximum possible length string into car.
scanf(___, alloy);			

b. Give the conversion specification to display alloy left-justified in a field of width 20.

The detection of erroneous input or validation of data is an important feature of interactive programming. To validate data, we can read an input datum as a string with the scanf or gets function. We check the string character by character to make sure it is valid. If input is satisfactory, then we can use one of the ANSI C standard library function atoi (ASCII to int) or atof (ASCII to floating point) to return the int or double equivalent, respectively, of the string argument. For example, if input is the string containing the user input, which should be an integer, and num is of type int, we perform the conversion with

include <stdlib.h>
...
num = atoi(input);

Quick Review Question
Quick Review Question 5
a. Give the name of the function that we can use to convert the string "25.6" held in a character array to the corresponding floating point number.

b. Give the header file that contains the prototype for this function.

The ANSI C header file string.h includes the definitions of other string functions and of the type size_t, which is the type of the value that sizeof returns. The sizeof operator applied to a type or expression gives the number of storage bytes needed for the operand. For example, sizeof(float) or sizeof(x) for a float variable x is the number of byes to store a floating point value in memory.

The ANSI C string library function strlen returns the number of characters (other than '\0') in the string as a value of type size_t. Thus, after execution of

length = strlen(str);

length holds the length of str. The function strcpy with prototype in string.h accomplishes string copying. The statement

strcpy(destination, source);

copies the string in source to destination. The function strcat replaces the first string variable argument with the concatenation or joining of the two arguments with a call such as

strcat(str1, str2);

The first parameter to the strcat function must be a variable string (an array) and large enough to hold the concatenated string.

One of the basic operations of word processors is to search for the first occurrence of a string in the text. In C, the function call strstr(str, substr) returns a pointer to the first occurrence of the string substr in the string str. Should substr not be a substring of str, the function returns NULL. A similar function call, strchr(str, ch), returns a pointer (or NULL) to the first occurrence of a character, ch, in a string, str. The library function strcmp (string compare) accomplishes the comparison of strings by returning an integer. If the first string argument is less than the second, strcmp returns a value less than zero. If the first argument is equal to the second, the function returns a zero. If the first is greater than the second, strcmp returns an integer greater than zero. Table 1 presents a summary of these string functions that we covered.

Table 1 Summary of six string functions
Function
Action
Returns
strcat(ToS, FromS) Concatenate string FromS onto the end of string ToS ToS
strchr(s, c) Find char c in string s Pointer to first occurrence of c in s or NULL
strcmp(s1, s2) Compare lexically strings s1 and s2 If s1 before s2, negative integer; if s1 the same as s2, 0; if s1 after s2, positive integer
strcpy(ToS, FromS) Copy string FromS into string ToS ToS
strlen(s) Length of string s Length of s
strstr(s, find) Find string find in string s Pointer to first occurrence of substring in s or NULL

Quick Review Question
Quick Review Question 6  For each of the parts, start with the following declaration-initializations.

char s1[20] = "well",
     s2[20] = "come",
     *loc;
int comp;


a. Not using quotation marks, give the value of s1, after execution of the following statement:
s1[strlen(s1) - 1] = '\0';				

b. Not using quotation marks, give the value of s1 after execution of the following statement:
strcat(s1, s2);			

c. Which variable changes value after execution of the following statement:
strcpy(s1, s2);
s1 s2 s1 and s2 neither


d. Write statement to point loc to the start of the substring "me" in s2.Have exactly one blank after any comma and before and after the assignment operator.

e. Give the value of comp after execution of the following statement:
comp = strcmp(s1, s2);				
0 An integer less than 0 An integer greater than 0

 
File I/O

A text file is a file of characters. The data type FILE describes various features of a file. Each file in a program must have an associated pointer to this type. We can declare a pointer to file, file_ptr, as

FILE *file_ptr;

We can open a file for reading (input) and a file for writing (output) as follows:

infile_ptr = fopen("astronomy.dat", "r");     /* open input file */
outfile_ptr = fopen("asteroid.dat", "w");     /* open output file */

If the file does not exist, fopen returns a special constant, NULL. We should verify that the computer successfully opened the file before continuing, such as

if (infile_ptr == NULL)
{
printf("astronomy.dat does not exist.\n");
exit(1);
}

The standard library with header file stdlib.h contains exit, which aborts the program and returns its argument to the operating system. To close the file with pointer file_ptr, we use fclose, as follows:

fclose(file_ptr);

The standard I/O library function fprintf, which behaves almost the same as printf, sends its output to a specified file. An example call to this function follows:

fprintf(outfile_ptr, "%d\n", amt);

The header file stdio.h also declares a file input function, fscanf, which reads from the file specified by a FILE pointer as the first parameter. An example call to this function follows:

fscanf(infile_ptr, "%d", &amt);

One method to accomplish continuous processing is to read and test for the correct amount of input in a while condition. Afterwards, we use the feof in an if statement to check for end-of-file.

while (fscanf(infile_ptr, "%f", &price) == 1)
{
...
}

if (!feof(infile_ptr))
{
fprintf(stderr, "There was an error reading the file.\n");
exit(1);
}

The function fputs writes a string to a file, such as

fputs(str, outfile_ptr);

If fputs cannot write the string to the file, the function returns EOF. The function fgets to read from a file into a string accepts three arguments, the string variable, the maximum number of characters (including '\0') to place in the string, and a pointer to the input file. For instance,

fgets(str, 15, infile_ptr);

If fgets cannot read the string to the file, the function returns NULL. Tables 2 and 3 summarize I/O with strings.

Table 2 Functions to write strings up to '\0'

Example Function Call
Write to
Adds '\n'?
Error Return
printf("%s", str);
stdout
no
negative
puts(str);
stdout
yes
EOF
fprintf(outfile_ptr, "%s", str);
output file
no
negative
fputs(str, outfile_ptr);
output file
no
EOF

Table 3 Functions to read strings, placing '\0' at the end
Example Function Call
Read from
Skip White Space before?
Read
Stop Reading with
Error Return
scanf("%s", str);
stdin
yes
word
white space
EOF
gets(str);
stdin
no
line
'\n' (discard)
NULL
fscanf(infile_ptr, %s", str);
input file
yes
word
white space
EOF
fgets(str, n, infile_ptr);
input file
no
line
'\n' (keep), eof, or n - 1 characters
NULL

Quick Review Question
Quick Review Question 7  Type exactly one blank before any asterisk, after any comma, and on each side of an assignment equals.
a. Complete the declaration of fp as a file pointer:

_____fp;


b. Write a statement to open the file to which fp points for input. On disk, this file is mustard.mol.

c. If this file is not found, give the subsequent value of fp.

d. Suppose AtomName is a character array of at most three elements. Using fgets, write a statement to read the next two characters from the file to which fp points into AtomName.

e. Suppose natoms and nbonds are int variables. Using fscanf, write a statement to read the next two integers (separated by one blank) from the file to which fp points into these variables.
 
Enumeration Types

The declaration of structures and enumeration variables in C is similar, but not identical, to that of C++. Consider the following enumeration definition:

enum answer {NO, YES}; /* C or C++ definition */

Unlike C++, to declare a variable cont to be of this type in ANSI C, we must preface answer with enum, as follows:

enum answer cont; /* ANSI C declaration */

One method of avoiding writing enum repeatedly in declarations is to use a typedef.

typedef enum answer answer_t; /* ANSI C definition */

We could also define the values of the enumeration type and define answer_t in one statement.

typedef enum {NO, YES} answer_t; /* ANSI C definition */

With either definition, we can declare cont to be of this equivalent type without using the prefix enum.

answer_t cont; /* ANSI C declaration */

Quick Review Question
Quick Review Question 8
Complete the type definition of enumeration type color_t.

  a   b   {RED, GREEN, BLUE}   c  ;
 
Structure Types

Similarly, ANSI C requires declaration of a structure variable to start with struct, unless we have glued "struct" to the structure name in a typedef. For example, with the structure definition in C

struct SolventRec_t /* C or C++ definition */
{
char SolventName[21];
int FreezingPoint;
};

we must declare solvent of this type as

struct SolventRec solvent; /* ANSI C declaration */

Quick Review Question
Quick Review Question 9
Complete the type definition of structure type BondData_t using typedef.

  a   b   {int first, second, BondType}   c  ;
 
Type Conversions

The syntax of casting a variable to another type is different in C than in C++. For example, suppose we want to compute the percentage correct on an exam. There are 250 possible points (TotalPossible) on the final, and the student earns 200 (TotalEarned) of them. The percentage score percent is 200 / 250 = 0.80 = 80%. In C or C++, the integer division 200 / 250 results in a truncation of the quotient to 0. Consequently, we must cast TotalEarned or TotalPossible or both to a float or double before the division.

int TotalEarned, TotalPossible;
float percent;
.
.
.
percent = (float)TotalEarned / TotalPossible; /* C casting */

To perform this type conversion in C++, we use a function notation, as follows:

percent = float(TotalEarned) / TotalPossible; // C++ type conversion


Allocation and Deallocation of Space

In C, we can allocate space with malloc (memory allocation) and restore the space to available memory with free, which are in the standard library, stdlib. The C++ counterparts of malloc and free are new and delete, respectively. For example, suppose int_ptr is a pointer to an int.

int *int_ptr;

In C, we can allocate space and point int_ptr to that area using appropriate casting, as follows:

int_ptr = (int *)malloc(sizeof(int));

In C++, we can use the new operator as

int_ptr = new int;

To allocate an integer array of ten elements dynamically, in C++ we write

array_ptr = new int[10];

In C, we determine the total amount of space and cast as follows:

array_ptr = (int *)malloc(10 * sizeof(int));

As with new, if malloc cannot allocate space, the operator returns NULL.

In C, to make available the cell to which int_ptr points we use free:

free(int_ptr);

In C++, we use delete:

delete int_ptr;

If array_ptr points to an array, in C we write

free(array_ptr);

while in C++, we place empty brackets between delete and the array or pointer name, as follows:

delete [] array_ptr;

Quick Review Question
Quick Review Question 10  Type exactly one blank before any asterisk, after any comma, and on each side of an assignment equals.
a. Complete the declaration of AtomName as a character pointer.
___AtomName;			

b. Allocate space for 3 characters to which AtomName points.

c. Deallocate the space.
 
Exercises

Write answers to the following exercises in C:

1. Write statements to prompt the user and to read a value for int variable num.

2. Write a statement to print the value of string variable bird and int variable count along with descriptions of the values.

3. Write statements to print the number and integer total on one line and floating point average another. Double space the output. If number is zero, display "No data". Otherwise, compute the average.

4a. Define RhFactor_t as an enumeration type with possible values PLUS and MINUS. Use typedef

  b. Define BloodType_t as an enumeration type with possible values M, N, and MN. Use typedef.

  c. Declare Rh and BloodType to be variables of types RhFactor_t and BloodType_t, respectively. Have appropriate comments.

  d. Declare subject to be a char pointer.

  e. Allocate space for subject so that it can hold a name of length 30. Be sure to allocate enough space to hold the null character, too.

  f. Write a prototype for a function GetBloodInfo that has input parameter subject, a character pointer, and sends back values for the Rh factor and blood type.

  g. Call GetBloodInfo, sending it the name of the subject and obtaining the Rh factor and blood type.

  h. Define a structure type to contain a subject's name, Rh factor, and blood type. Use typedef.

5a. Declare array_ptr to be a pointer to a float, and dynamically allocate space for a float array of 100 elements.

  b. Write an error message to the standard error file if allocation was not possible.

  c. Dynamically deallocate the space obtained in Part a.

Programming Projects

Develop a program in C for one of the following projects:

1. Project 1 or 2 in module "Database Introduction".

2. Project 1 or 2 in module "Genomic Data".

3. Project 1 or 2 in module "Genomic Sequence Comparison".

4. One of Projects 1-6 in module "Searching Genomic Databases".

5. A psychology researcher's file, R10502.dev, contains data for an experiment with a pigeon in two-lever box. Each line contains an event code as in Quick Review Question 1 of "Relational Databases" and the time of occurrence. Develop a program to report the count of each event and the average time of pellet delivery. (Data contributed by Dr. Alliston Reid, Psychology Department, Wofford College.)

6. A biology researcher's file contains data for a subject's name, Rh factor (+ or -), and blood type (M, N, or MN). Count the number of subjects in each of the following categories: all, +, -, M, N, MN, + M, + N, + MN, - M, - N, and -MN. Use enumeration types.

Copyright © 2002, Dr. Angela B. Shiflet
All rights reserved