Thursday 5 April 2012

Passing An Array to Functions in C & C++


The previous entry looked at various ways to pass a variable to a function: by value, by reference or by pointer. This entry looks at passing an array to a function. In C/C++ arrays are passed by reference or by pointer, not by value. This means the called function can directly change the array as passed by the caller. You can however pass one element of an array by value in the same way you pass an integer or other data type.

The sample code calls a function, CapFirstLetter, which takes a character array from the caller and raises the first letter of each word to uppercase.

The character array is created by:

     char Text[] = "Some words to cap.";

I can then define the function signature in one of two ways: with or without a pointer.

int CapFirstLetter(char vText[]);
int CapFirstLetter(char * vText);

The code inside the function is the same.

I can then call the function in one of three ways:

CapFirstLetter(Text);

CapFirstLetter(&Text[0]);

char * pText = &Text[0];
OR
char * pText = Text;
CapFirstLetter(pText);

The critical point to remember is that using the name of the array, in this case, Text, is actually a pointer to the first element of the array. Thus, using Text is the same as using &Text[0] and a pointer can be assigned using either method. The result is the same.

Sample Code.

// Standard I/O library.
#include <cstdio>

// Prototypes.
int CapFirstLetter(char vText[]);
int CapFirstLetter2(char * vText);

int main()
{

     printf("Call Function To Cap First Letter of Every Word\n\n");

     /////////////////////////////////////////////////////////////////
     // 1. Pass array by array name.

     printf("1. Pass array by array name.\n\n");
     char Text[] = "Some words to cap.";
     CapFirstLetter(Text);
     printf("Version 1: %s\n", Text);
    
     // The name of the array is a pointer to first element.
     char Text2[] = " This   function   handles extra spaces.";
     CapFirstLetter(&Text2[0]);
     printf("Version 2: %s\n\n\n", Text2);

     /////////////////////////////////////////////////////////////////
     // 2. Pass array by pointer variable.

     printf("2. Pass array by pointer variable.\n\n");
     // Create pointer.
     char Text3[] = "a statement with all lowercase letters";

     // Option 1.
     // The name of the array, Text3, is a pointer to Text3[0].
     // char * pText = Text3;

     // Option 2.
     // Another way to get the address of the first element.
     char * pText = &Text3[0];
     CapFirstLetter(pText);
     printf("Version 3: %s\n", Text3);
    
     // Start later in the array.
     char Text4[] = "a statement with all lowercase letters";
     pText = &Text4[2];
     CapFirstLetter(pText);
     printf("Version 4: %s\n", Text4);

     // Close the file.
     fclose(stdout);

     // Return something.
     return 0;
}
int CapFirstLetter(char vText[])
{
     /////////////////////////////////////////////////////////////////
     // Capitalize first letter of a string of text.

     short i;
     bool PrevSpace = true;

     for (i = 0; vText[i]; i++)
     {
           // Look to find start of new word.
           if (PrevSpace)
           {
                // Ignore space.
                if (vText[i] == ' ')
                     // Go to next char.
                     continue;
                // Not a space, reset flag.
                PrevSpace = false;
                // Want lowercase only.
                if ((vText[i] >= 97) && (vText[i] <= 122))
                {
                     // Appy uppercase.
                     vText[i] -= 32;
                }
           }
           else
           {
                // Start of new word.
                if (vText[i] == ' ')
                     // Reset.
                     PrevSpace = true;
           }
     }

     // Return success.
     return 0;
}

Output.


Wednesday 4 April 2012

Passing Data to Functions in C & C++


C and C++ are built on functions. All programs in C/C++ start with a main() function and branch out from there to other functions. Generally, since it's considered poor coding practice to use global variables, you will need a way to pass local variables from one function to another. This blog looks at the different way of passing data to a function.

1. Pass By Value.

The default in C/C++ is to pass the value of a variable to a function. This means the function cannot change the value of the variable in the caller function. Here is some test code to show this point.

int i = 10;
printf("Pass Argument by Value.\n");
printf("Value before function call: %d.\n", i);
ByVal(i);
printf("Value after function call: %d.\n", i);

void ByVal(int Parameter)
{
     // Change won't happen.
     Parameter = 100;
     printf("Value in function: %d.\n", Parameter);
}

>Pass Argument by Value.
>Value before function call: 10.
>Value in function: 100.
>Value after function call: 10.
 
When a variable is passed to a function by value, the language copies the value to the heap—the dynamic runtime memory. The variable in the caller function is thus duplicated—one copy in the caller function and one copy for the called function. This is not an efficient use of resources. It uses up memory and it takes time to copy the data. A better way is to pass a memory address of the variable to the called function.

2. Pass By Reference.

If I declare MyVar as integer type, I can find out its memory address with the & operator. The first method of passing a memory address to a variable uses this operator. I define the function with a parameter of DataType &VariableName.

i = 20;
printf("\nPass Argument by Reference.\n");
printf("Value before function call: %d.\n", i);
printf("Address of i in main: %#X.\n", &i);
ByRef(i);
printf("Value after function call: %d.\n", i);


void ByRef(int &Parameter)
{
     // Value changes.
     Parameter = 200;
     printf("Value in function: %d.\n", Parameter);
     printf("Address of Parameter in function: %#X.\n", &Parameter);
}


>Pass Argument by Reference.
>Value before function call: 20.
>Address of i in main: 0X36EB8C.
>Value in fn: 200.
>Address of Parameter in function: 0X36EB8C.
>Value after function call: 200.

Because the function ByRef function has direct reference to the i variable, it can change the value. You will note the memory address is the same inside the function as it is in the caller function.

3. Pass By Pointer.

The previous example indirectly passed the memory address for the parameter with ByRef(i) instead of ByRef(&i). The function used the & operator. In this example, the caller must pass a pointer—a direct reference to the memory location. The end result is the same.

int* pi = &i;
i = 30;
printf("\nPass Argument by Pointer.\n");
printf("Value before function call: %d.\n", i);
printf("Address of i in main: %#X.\n", pi);
ByPointer(pi);
printf("Value after function call: %d.\n", *pi);

void ByPointer(int* Parameter)
{
     // Value changes.
     *Parameter = 300;
     printf("Value in function: %d.\n", *Parameter);
     printf("Address of Parameter in function: %#X.\n", Parameter);
}

>Pass Argument by Pointer.
>Value before function call: 30.
>Address of i in main: 0X36EB8C.
>Value in fn: 300.
>Address of Parameter in function: 0X36EB8C.
>Value after function call: 300.
 
Calling the function with a pointer, ByPointer(pi), is equivalent to this: ByPointer(&i).

These examples used the integer data type. The code could be modified to use the other built-in data types: char, bool, double, float. For passing an array, especially a character array, to a function, see the next blog entry.

Tuesday 3 April 2012

The freopen Functions in C & C++


The freopen Function.

The freopen function in the C Standard I/O library <cstdio> is a useful to redirect output destined for the stdout to a text file. I discussed how to use the fprintf function to send output to either a text file or the stdout. See here. The same result is achieved here using the printf and freopen functions.

Method 1.

freopen(Filename, "w", stdout);

There is no return value to indicate if the file was opened or if there was an error.

Method 2.

iReturn = freopen(Filename, "w", stdout);

On failure, a null pointer is returned otherwise the return value is a pointer to the file. Beyond testing for an error, this return value is used to close the file.

fclose(iReturn);

While my example uses the stdout, the freopen function can be used with the stdin and stderr objects.

 
Test Code.

I tested the functions in Visual C++ 2010 as an console application.

// The standard library includes the system function.
#include <cstdlib>

// C++ standard I/O library.
#include <cstdio>

int main()
{
     //**************************************************************
     // Redirect stdout to a file.

     // Declare pointer to the file.
     FILE* pFileHandle;
     char Filename[] = "MyFile.txt";

     // Returns null is the open failed.
     pFileHandle = freopen(Filename, "w", stdout);
     printf("pFileHandle is %X.\n\n", pFileHandle);

     //**************************************************************
     // Header.
     printf("Using freopen in C & C++\n\n");

     //**************************************************************
     // Some use of printf.
     printf("Sending the printf output to a file instead of the stdout.\n");
     printf("The freopen function allows for this redirection.\n\n");

     // Use variable for a string.
     char * Text = "A text string only from a variable.\n\n";
     printf("%s", Text);

     // Int type.
     int Salary = 375000;
     int Bonus = -35000;
     printf("Salary is: %8d.\n", Salary);
     printf("Bonus  is: %8d.\n", Bonus);
     printf("\n");

     //**************************************************************
     // Close the file.
     fclose(pFileHandle);

     // Keep console window open.
     system("pause");

     // Return some value.
     return 0;
} // end main

 Output.

Monday 2 April 2012

The printf Function in C & C++


The printf Function.

The printf function in the C Standard I/O library <cstdio> is a useful and versatile way to send output to the stdout. Your output is a string that may include formatted variable values. The most basic form doesn't use any variables, such as:

printf("This output is a text string only. No variables.\n");

>This output is a text string only. No variable.

The next step is to include a variable as part of the output. For example,

char * Text = "A text string only from a variable.\n";
printf("%s", Text);

>A text string only from a variable.

The code %s is a format specifier for a character array or string. The %s is replaced by the value of Text. This principle applies to other data types. A decimal integer uses %d or %i.

int Salary = 375000;
printf("Salary is: %d.\n", Salary);
printf("Salary is: %i.\n", Salary);

>Salary is: 375000.
>Salary is: 375000.

The definition of the specifier is:

%[flags][width][.precision][length]specifier

The square brackets means the parameter is optional. Hence, the most basic specifier is % followed by a letter of: c, d, i, e, E, f, g, G, o, s, u, x, X, p, or n.

This blog will go through examples of these specifiers and the various parameters. Once you understand the printf function, you can apply this knowledge in using the fprintf, fscanf, scanf, sprintf, sscanf functions.


Integer Data Types.

There are three specifiers for the integer data type in decimal format (Base 10). %d and %i apply to signed integers. %u applies to unsigned integers. If you use %u with a signed integer, the output will be garbage.

Salary = -35000;
printf("Using it with a negative value: %u doesn't work.\n\n", Salary);

>Using it with a negative value: 4294932296 doesn't work.

You can use an unsigned integer with %d or %i.

unsigned ActNum = 1234;
printf("Unsigned variable works with %%i or %%d. ActNum is %i.\n\n", ActNum);

>Unsigned variable works with %i or %d. ActNum is 1234.


Width.

You specify the width the value takes up by adding a number such as %8d or %8i. Setting a width allows you to align numbers.

int Salary = 12345678;
int Bonus = 52000;
printf("Salary is: %8d.\n", Salary);
printf("Bonus  is: %8d.\n", Bonus);

>Salary is: 12345678.
>Bonus  is:    52000.

If the number is larger than the width, the amount will be displayed, but the alignment will be askew.

int Salary = 1234567890;
int Bonus = 52000;
printf("Salary is: %8d.\n", Salary);
printf("Bonus  is: %8d.\n", Bonus);

>Salary is: 1234567890.
>Bonus  is:    52000.


Alignment.

The default is to align numbers to the right. You can add a minus sign such as %-8d to specify left alignment.

printf("Salary is: %-8d.\n", Salary);
printf("Bonus  is: %-8d.\n\n", Bonus);

>Salary is: 375000  .
>Bonus  is: 52000   .


Decimal. Hexadecimal. Octal.

To output a hexadecimal numbers use %x (lowercase) or %X (uppercase). An octal can be outputted with %o. It's the lowercase letter o for octal, not zero. See more examples here.

int num = 65535;
printf("Decimal: %d Hexadecimal: %X Octal: %o \n", num, num, num);
printf("Hexadecimal Uppercase: %X Lowercase: %x \n", num, num);

>Decimal: 65535 Hexadecimal: FFFF Octal: 177777
>Hexadecimal Uppercase: FFFF Lowercase: ffff

Use '#' to add a hex or octal notation prefix.

printf("Use # to create hexadecimal prefix '0X' or '0x'. Such as %#X, %#x.\n", num, num);

>Use # to create hexadecimal prefix '0X' or '0x'. Such as 0XFFFF, 0xffff.

printf("Use # to prefix octal with 0. Such as %#o.\n", num);
>Use # to prefix octal with 0. Such as 0177777.

int * pNum = &num;
printf("It works with pointers. Such as %#X, %#x.\n\n", pNum, pNum);

>It works with pointers. Such as 0X34EDD8, 0x34edd8.


Floating-point Numbers.

Floating point numbers use the f specifier such as %f.

float irrational = 123.456789;
double irrational2 = 123.456789;
printf("Default: %f \n", irrational);
printf("Default: %f \n", irrational2);

>Default: 123.456787
>Default: 123.456789

Set shorter decimal points.

printf("4 decimal points: %.4f \n", irrational);
printf("4 decimal points: %.4f \n", irrational2);

>4 decimal points: 123.4568
>4 decimal points: 123.4568

Set longer decimal points.

printf("14 decimal points: %.14f \n", irrational);
printf("14 decimal points: %.14f \n", irrational2);

>14 decimal points: 123.45678710937500
>14 decimal points: 123.45678900000000


Plus or Minus.

The flag + will show a plus sign or minus sign before a number.

Salary = 375000;
Bonus = -27500,
printf("Salary and bonus: %+d, %+d.\n", Salary, Bonus);

>Salary and bonus: +375000, -27500.

Padding With Zeroes.

The flag 0 (zero) places zeroes in front of a number. It only applies if a width has been specified.

Salary = 375000;
Bonus = 27500,
printf("Salary is: %08d.\n", Salary);
printf("Bonus  is: %08d.\n", Bonus);
printf("Salary is: %0d.\n", Salary);

>Salary is: 00375000.
>Bonus  is: 00027500.
>Salary is: 375000.


Scientific Notation.

Use %e or %E with a floating point number to display it in scientific notation. A number is formatted as: x.xxxxxxEnnn. The decimal equivalent is x.xxxxxx multiplied by 10 to the power of nnn.

double Notation = 100;
printf("100 is: %E.\n", Notation);

> 100 is: 1.000000E+002.

In base 10, a number greater than zero has 1s, 10s, 100s etc. So, 100 is 1 one-hundred. A common mistake happens when a number is less than zero. 0.001 is not 1/100 but 1/1000. So, 0.1 is tenths, 0.01 is hundreds, 0.001 thousands and so on.
 
Notation = 1.0/100.0;
printf("1/100 is: %f or %E.\n", Notation, Notation);

> 1/100 is: 0.010000 or 1.000000E-002.

double LargeNum = 123456789123;
printf("Number using E: %E.\n", LargeNum);
printf("Number using e: %e.\n", LargeNum);

>Number using E: 1.234568E+011.
>Number using e: 1.234568e+011.

printf("Specify width: %15E.\n", LargeNum);
printf("Specify decimals: %.2E.\n", LargeNum);

>Specify width:   1.234568E+011.
>Specify decimals: 1.23E+011.

double SmallNum = 0.123456789123;
printf("Number using E: %E.\n", SmallNum);

>Number using E: 1.234568E-001.

The scientific notation doesn't work with integer data types.

int Num = 100;
printf("Doesn't work with integers: %E.\n", Num);

>Doesn't work with integers: 5.820601E-308.