I l@ve RuBoard Previous Section Next Section

16.10 C-Style Conversion Routines

C++ uses the << operator for formatted output and the >> operator for formatted input. C has its own set of output functions (the pstd::printf family) and input conversion functions (the std::scanf functions). This section goes into the details of these C-style conversion routines.

16.10.1 The std::printf Family of Output Functions

C uses the std::printf function call and related functions for output. A std::printf call consists of two parts: a format that describes how to print the data and a list of data to print.

The general form of the std::printf call is:

std::printf(format, parameter-1, parameter-2, ...);

The format string is printed exactly. For example:

std::printf("Hello World\n");

prints:

Hello World

To print a number, you must put a % conversion in the format string. For example, when C sees %d in the format string, it takes the next parameter from the parameter list (which must be an integer) and prints it.

Figure 16-1 shows how the elements of the std::printf statement work to generate the final result.

Figure 16-1. std::printf structure
figs/C++2_1601.gif

The conversion %d is used for integers. Other types of parameters use different conversions. For example, if you want to print a floating-point number, you need a %f conversion. Table 16-9 lists the conversions.

Table 16-9. C-style conversions

Conversion

Variable type

%d

int

%ld

long int

%d

short int

%f

float

%lf

double

%u

unsigned int

%lu

unsigned long int

%u

unsigned short int

%s

char * (C-style string)

%c

char

%o

int (prints octal)

%x

int (prints hexadecimal)

%e

float (in the form d.dddE+dd)

Many additional conversions also can be used in the std::printf statement. See your reference manual for details.

The std::printf function does not check for the correct number of parameters on each line. If you add too many, the extra parameters are ignored. If you add too few, C will make up values for the missing parameters. Also C does not type check parameters, so if you use a %d on a floating point number, you will get strange results.

Question 16-2: Why does 2 + 2 = 5986? (Your results may vary.)

Example 16-7. two/two.c
#include <cstdio>
int main(  )
{
    int answer;   

    answer = 2 + 2;

    std::printf("The answer is %d\n");
    return (0);
}

Question 16-3: Why does 21 / 7 = 0? (Your results may vary.)

Example 16-8. float3/float3.c
#include <cstdio>

int main(  )
{
    float result;

    result = 21.0 / 7.0;
    std::printf("The result is %d\n", result);
    return (0);
}

The function std::fprintf is similar to std::printf except that it takes one additional argument, the file to print to:

std::fprintf(file, format, parameter-1, parameter-2, ...); 

Another flavor of the std::printf family is the std::sprintf call. The first parameter of std::sprintf is a C-style string. The function formats the output and stores the result in the given string:

std::sprintf(string, format, parameter-1, parameter-2, ...); 

For example:

char file_name[40];        /* The filename */ 

/* Current file number for this segment */ 
int file_number = 0;     

std::sprintf(file_name, "file.%d", file_number); 
++file_number; 
out_file = std::fopen(file_name, "w"); 

The return value of std::sprintf differs from system to system. The ANSI standard defines it as the number of characters stored in the string; however, some implementations of Unix C define it to be a pointer to the string.

16.10.2 The std::scanf Family of Input Functions

Reading is accomplished through the std::scanf family of calls. The std::scanf function is similar to std::printf in that it has sister functions: std::fscanf and std::sscanf. The std::scanf function reads the standard input (stdin in C terms, cin in C++ terms), parses the input, and stores the results in the parameters in the parameter list.

The format for a scanf function call is:

number = scanf(format, &parameter1, . . .); 
number

Number of parameters successfully converted.

format

Describes the data to be read.

parameter1

First parameter to be read. Note the & in front of the parameter. These parameters must be passed by address.

If you forget to put & in front of each variable for std::scanf, the result can be a "Segmentation violation core dumped" or "Illegal memory access" error. In some cases a random variable or instruction will be modified. This is not common on Unix machines, but MS-DOS/Windows, with its lack of memory protection, cannot easily detect this problem. In MS-DOS/Windows, omitting & can cause a system crash.

There is one problem with this std::scanf: it's next to impossible to get the end-of-line handling right. However, there's a simple way to get around the limitations of std::scanf—don't use it. Instead, use std::fgets followed by the string version of std::scanf, the function std::sscanf:

char line[100];    // Line for data

std::fgets(line, sizeof(line), stdin);    // Read numbers
std::sscanf(line, "%d %d", &number1, &number2);

Finally, there is a file version of std::scanf, the function std::fscanf. It's identical to scanf except the first parameter is the file to be read. Again, this function is extremely difficult and should not be used. Use std::fgets and std::sscanf instead.

    I l@ve RuBoard Previous Section Next Section