Considerations When Using Built-in Data Types



Definition of Built-in Data Types

In a generic sense, built-in data types are all the predefined data types which are explicitly distinguished from user defined ones. Built-in data types are language dependent, i.e. different languages have different built-in data types. In built-in data types, there are primitive data types such as char, integer, float and Boolean (in most languages). As well, there are aggregate data types such as array, struct, record, or class in some languages.

Topic 1 - Numbers in General

Some special considerations should be given when using numbers.

  1. Avoid "Magic Numbers." "Magic numbers" are any literal constants that mean something more than their actual numeric values and appear in the middle of a program without previous declaration or explanation. The only numeric literals that should be considered are 0s and 1s since they have special significance and are more simple, direct indicators. 0s are often used to initialize a loop or check the first invalid entry; 1s are usually used to increment by one unit in a loop. Use more descriptive options such as symbolic constants ( if your programming language supports constants) that represent the special meanings, or global variables when it is feasible to. These alternatives yield benefits:



    Bad C Example of Magic Numbers
    Good C Example
    A Java Example of Using 0s and 1s
    Bad C++ Example of Magic Numbers
    Good C++ Example

  2. Avoid Mixed Type Comparisons If two operands compared are of different types, most compilers will generate an error. To avoid this problem, use a type conversion.

    A C++ Example of Conformed Type Comparison
    A Bad Java Example of Mixed Comparison
    A Good Java Example

  3. Watch for Divide-by-Zero Error Each time you use the division symbol (/ in most languages), make sure that it is not possible to divide by zero.

    A C Example of Divide-by-Zero
  4. Use Explicit Conversions Don't assume that the readers of your code will be aware of all the implicit type conversions in you programming language. Use explicit conversions and comments whenever possible to make the conversions obvious both to your readers and to yourself, now and later.
    
    
    
            int radius = 3, circum;
    
            const double PI=3.1416;
    
            circum = 2* PI * radius;
    
    



    A Bad C++ Example of Implicit Conversion
    Good Example
    A Bad C Example of Implicit Conversion
    Good Example
    A Java Example of Explicit Conversion

Topic 2 - Integers

Generally speaking, a series of digits with no decimal point is typed as an integer. Integer numbers are generally used in programs as counters to keep track of the number of times something has occurred. You can specify a long integer by putting an 'L' or 'l' after the number. 'L' is preferred as it cannot be confused with the digit '1'.

  1. Check for Integer Division Remember integer operations produce integers in computer algorithm. 2/4 produces 0, 3/2 gives 1, all their fractional tailings are cut off since the result is not an integer. This is not the same case as in math or in real-world concepts. Therefore, avoid integer division as possible.

    A Bad C++ Example of Integer Division
    A Good Example
    Bad C Examples of Integer Division
    A Good C Example
    A Bad Java Example of Integer Division
    A Good Java Example

  2. Check for Integer Overflow Integer overflow often happens when you are doing arithmetic operations such as multiplication and addition. Integer overflow is always silent. The following table specifies the size and range of integer type. All of the types are illustrated as signed integers. You should at least have a rough idea of the different range.
    
    
    Size Range                      
    
    signed 8 bits                    -128 to 127
    
    unsigned 8 bits                  0 to (127 * 2) +1
    
    signed 16 bits                   -32,768 to 32,767      
    
    unsigned 16 bits                 0 to (32,767 * 2) + 1   
    
    signed 32 bits                   -2,147,483,648 to 2,147,483,647 
    
    unsigned 32 bits                 0 to (2,147,483,647 * 2) + 1 
    
    signed 64 bits                   -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
    
    unsigned 64 bits                 0 to (9,223,372,036,854,775,807 * 2) + 1
    
    

    Note, Java programming language specifies the size and format of its primitive data types. Hence, you don't have to worry about system-dependencies, and once overflow occurs, the complier will not compile. In other languages, the format and size of primitive data types may depend on the platform on which a program is running. So, once overflow occurs, the compiler cannot detect the danger; when the program runs, errors appear. Handle this kind of problem by declaring a larger size for the assigned variable.

    A Bad C++ Example of Integer Overflow
    A Good C++ Example
    A C Example of Integer Overflow

  3. Watch for Intermediate Results Incorrect values such as integer division or overflow in intermediate results are often disguised within a larger expression and can be a troublesome error to detect. Handle this kind of problem by combining the techniques for handling integer division and overflow.

    A Bad C Example of Intermediate Errors
    A Good Example
    A Java Example of Intermediate Errors




Example Programs

A Bad C Example of Magic Numbers

#include 

int main ()

{

        int loop_index;

        //0 is initialized to loop_index, ok!

        //10 is a magic number

        //increment loop_index by 1 is ok, but not good style

        for (loop_index=0; loop_index<10; loop_index+="1)" { printf ("Goodbye!\n"); } return 0; } 

A Good C Example

# include 

int main ()

{

        //LOOP_LIMIT is not a magic number but a named constant

        const int LOOP_LIMIT = 10;

        int loop_index;

        //0 is initialized to loop_index, ok!

        //increment loop_index by 1 with ++ operator

        for (loop_index=0; loop_index

A Java Example of Using 0s and 1s

//A lot of use of 0s,1s and symbol literal constants

import java.io.*;

//class begins here

class magic3

{

        public static void main(String[] args) throws IOException

        {

        //0s to initilize

        int count, num, odd=0, even=0, counter=0;

        String numString, iString;

        BufferedReader stdin=new BufferedReader

                                        (new InputStreamReaderSystem.in));

        System.out.print("How many numbers are you going to enter?");

        numString=stdin.readLine();

        count=Integer.parseInt(numString);

        while(countercount)

         {

                System.out.print("Enter an integer(-1 to quit): ");

                iString=stdin.readLine();

                num=Integer.parseInt(iString);

                //1 to increment (counter++ is much better)

                counter=counter+1;

                 int modular=2;

                if(num%modular==0)

                //1 to increment (even++ is much better)

                even=even+1;

                else

                //1 to increment (odd++ is much better)

                odd=odd+1;

                //same type comparison

                if(counter==count)

                System.out.println("Already entered " 

                                        + count + "     integers.");

         }

         

         System.out.println("There are " + even + " even numbers.");

         System.out.println("and there are " + odd + " odd numbers.");

         

        }

}//end class

 

 

 

 


A Bad C++ Example of Magic Numbers

#include  

int main ()

{

        

        //A lot of magic numbers:20000,0.02,0.05 

        //and implicit conversions

        float taxes, taxable;

        cout <<"Please enter the taxable income: "; cin>> taxable;

        if (taxable <= 20000) taxes="0.02" * taxable; else taxes="0.05" * (taxable 20000) + 400; cout <<"\n\nTaxes are $ "<< taxes << endl; return 0; } 

A C++ Example

#include  

int main ()

{

        //use meaningful symbol constants

        //instead of magic numbers to improve benefits

        const float LIMIT = 20000.0;

        const float FIXED = 400.0;

        const float REGRATE = 0.02;

        const float HIGHRATE = 0.05;

        double taxes, taxable;

        cout <<"Please enter the taxable income: "; cin>> taxable;

        if (taxable <= LIMIT) taxes="REGRATE" * taxable; else taxes="HIGHRATE" * (taxable LIMIT) + FIXED; cout <<"\n\nTaxes are $ " << taxes << endl; return 0; } 

A C++ Example of Conformed Type Comparison

// show conformed type comparison

# include 

int main ()

{

        int my_number = 10;

        int user_guess = 0;

        //user_guess vs my_number 

        while ( user_guess != my_number )

        {

        cout << "Guess my number:?"; cin>> user_guess;

        }

        cout << "Good work!" << endl; return 0; } 

A Bad Java Example of Mixed Comparison

import java.io.*;

class mixed4

{

        public static void main(String[] args) throws IOException

        {

        double my_number = 10.1;

        int user_guess;

        String input, entry;

        BufferedReader stdin=

        new BufferedReader(new InputStreamReader (System.in));

        System.out.println("Enter your number: ");

        input=stdin.readLine();

        User_guess=Integer.parseInt(input);

        //user_guess cannot accept an input like 10.1(double)

        //the equality condition will never be reached 

        while (user_guess != my_number)

        {

        System.out.println("Try another number:?");

        entry=stdin.readLine();

        user_guess=Integer.parseInt(entry);

        }

        System.out.println("Good work! Bye!");

        System.out.println();

        }

}//end class

 


A Good Java Example

import java.io.*;

class mixed5

{

        public static void main(String[] args) throws IOException

        {

        int my_number = 10;

        int user_guess = 0;

        String input,entry;

        BufferedReader stdin=

        new BufferedReader(new InputStreamReader(System.in));

        System.out.println("Enter your number: ");

        input=stdin.readLine();

        //cast to ensure input number is of integer type

        user_guess=Integer.parseInt(input);

        while (user_guess != my_number)

        {

        System.out.println("Try another number:?");

        entry=stdin.readLine();

        user_guess=Integer.parseInt(entry);

        }

        System.out.println("Good work! Bye!");

        System.out.println();

        }

}//end class

 


A C Example of Divide-by-Zero

//disguised divide-by-zero error

# include 

int main ()

{

        int x, y, z, result;

        x=2;

        y=5;

        z=(10/2);

        result = x/(y-z);

        printf ("The result is %i. ", result);

        return 0;

}


A Bad C++ Example of Implicit Conversion

# include 

int main()

{

        int radius = 3, circum;

        const double PI=3.1416;

        circum = 2* PI * radius;

        cout << "The circumference is " << circum << " inches" << endl; return 0; } 

A Good C++ Example

# include 

int main()

{

        //declaring circum as double 

        //is good consideration

        double circum;

        int radius = 3;

        const double PI=3.1416;

        //a second consideration is explicitly converting radius 

        circum = 2* PI * double(radius);

        cout << "The circumference is " << circum << " inches" << endl; return 0; } 

A Bad C Example of Implicit Conversion

# include 

main ()

{

        int profits, employees;

        profits = 3;

        employees = 2;

        //expected result is 1.5, but the output is 1

        //0.5 is rounded off

        printf ("Each employee gets %d. ", profits/employees);

        return 0;

}

 


A Good C Example

# include 

int main ()

{

        int profits, employees;

        profits = 3;

        employees = 2;

        //explicit conversion to float

        printf ("Each employee gets %f. ", (float) profits/employees);

        return 0;

}


A Java Example of Explicit Conversion

import java.io.*;

//class begins here

class conversion5

{

public static void main(String[] args) throws IOException

        {

        BufferedReader std=new BufferedReader(new InputStreamReader(System.in));

        String name, price;

        int cost;

        Double totalCost;

        float tax;

        const double TAXRATE=0.07;

        System.out.println("\nPlease enter your name (full): ");

        name=std.readLine();

        System.out.println("\nEnter the price of textbook: ");

        price=std.readLine();

        //use method to do explicit conversion

        cost=Integer.parseInt(price);

        //use cast feature to do explicit conversion to float

        tax=(float) Math.round(cost * TAXRATE);

        totalCost=double(cost+tax);

        

        System.out.println("Hello, " + name +"\nWelcome to CS170.");

        System.out.println("\nThe textbook price is: " + cost);

        System.out.println("\nAnd the sales tax is: " + tax);

        System.out.println("\nThe addtotal cost is: " + totalCost);

        System.out.println("\nGood luck!");

        }

}//end of class

 


A Bad C++ Example of Integer Division

// The result of the program is wrong

//though the syntax and logic are all right

# include 

int main()

{

        

        float fahr, cel;

        cout << "Enter the temperature in degrees Fahrenheit: "; cin>>fahr;

        //integer division in 5/9

        cel = 5/9 * (fahr - 32);

        //the result is always 0 since 5/9 is truncated to 0

        cout << fahr<<" degrees Fahrenheit is "<< cel <<" degrees Celsius" << endl; return 0; } 

A Good C++ Example

# include 

int main()

{

        const float FACTOR1=5.0/9.0;

        const float FACTOR2=32.0; 

        float fahr, cel;

        cout << "Enter the temperature in degrees Fahrenheit: "; cin>>fahr;

        //avoid integer division and using named constants

        cel = FACTOR1 * (fahr - FACTOR2);

        cout << fahr <<" degrees Fahrenheit is "<< cel <<" degrees Celsius" << endl; return 0; } 

A Bad C Example of Integer Division

# include 

main ()

{

        int profits, employees;

        profits = 3;

        employees = 2;

        //expected result is 1.5, but the output is 1

        //0.5 is rounded off

        printf ("Each employee gets %d. ", profits/employees);

        return 0;

}


A good C Example

# include 

int main ()

{

        //declare profits to be a float

        float profits;

        int employees;

        profits = 3.0;

        employees = 2;

        //explicit conversion to float 

        printf ("Each employee gets %f. ", (float) profits/employees);

        return 0;

}


A Bad Java Example of Integer Division

import java.io.*;

//class begins here

class integer5

{

public static void main(String[] args) throws IOException

        {

        BufferedReader std=new BufferedReader(new InputStreamReader     (System.in));

        String name, price;

        int totalCost, cost, tax;

        //this results in taxRate==0

        int taxRate=7/10;

        System.out.println("\nPlease enter your name (full): ");

        name=std.readLine();

        System.out.println("\nEnter the price of textbook: ");

        price=std.readLine();

        cost=Integer.parseInt(price);

        tax= (cost * taxRate);

        totalCost=cost+tax;

        //total cost equals to cost, tax is 0 for 7/10 is treated as 0

        System.out.println("Hello, " + name +"\nWelcome to CS170.");

        System.out.println("\nThe textbook price is: " + cost);

        System.out.println("\nAnd the sales tax is: " + tax);

        System.out.println("\nThe addtotal cost is: " + totalCost);

        System.out.println("\nGood luck!");

        }

}//end of class

 


A Good Java Example

import java.io.*;

//class begins here

class integer6

{

        public static void main(String[] args) throws IOException

        {

        BufferedReader std=new BufferedReader

        (new InputStreamReader(System.in));

        String name, price;

        float totalCost, cost, tax;

        double taxRate=0.07;

        System.out.println("\nPlease enter your name (full): ");

        name=std.readLine();

        System.out.println("\nEnter the price of textbook: ");

        price=std.readLine();

        //use method to do explicit conversion

        cost=Integer.parseInt(price);

        //use cast feature to do explicit conversion to float

        tax=(float) Math.round(cost * taxRate);

        totalCost=cost+tax;

        

        System.out.println("Hello, " + name +"\nWelcome to CS170.");

        System.out.println("\nThe textbook price is: " + cost);

        System.out.println("\nAnd the sales tax is: " + tax);

        System.out.println("\nThe addtotal cost is: " + totalCost);

        System.out.println("\nGood luck!");

        }

}//end of class

 


A Bad C++ Example of Integer Overflow

# include 

int main ()

{

        int words_total, words_per_page, pages_per_chapter,

        chapters_per_volume, volumes_per_book, books_in_library ;

        words_per_page = 400;

        ages_per_chapter = 100;

        chapters_per_volume = 80;

        volumes_per_book = 20;

        books_in_library = 60000;

        //the product is more than the limit of unsigned integer 

        words_total = words_per_page * pages_per_chapter * chapters_per_volume

                         * volumes_per_book * books_in_library;

        //the result is negative for overflow

        cout << "The total number of words for the set is: " << words_total << endl; return 0; } 

A Good Example

# include 

int main ()

        {

        int words_per_page,pages_per_chapter,chapters_per_volume ,

         volumes_per_book, books_in_library;

        //unsigned long integer to prevent overflow

        unsigned long int words_total;

        words_per_page = 400;

        pages_per_chapter = 100;

        chapters_per_volume = 80;

        volumes_per_book = 20;

        books_in_library = 60000;

        words_total = words_per_page * pages_per_chapter * 

                        chapters_per_volume * volumes_per_book * books_in_library;

        cout << "The total number of words for the set is: " << words_total << endl; return 0; } 

A C Example of Integer Overflow

#include 

//overflow through inadvertent function call

int powerFreq (int f);

int main ()

{

        int frequency = 3000000; 

        printf ("The timed frequency is %i.", powerFreq (frequency));

        return 0;

}

int powerFreq (int f){return f * f; }

 


A C Example of Intermediate Errors

# include 

int main ()

{

        

        int finals, a, b, c, d;

        a = 6;

        b = 7;

        c = 6/7;

        d = 7/6;

        //incorrect value in intermediate expression

        finals = a + b + c + d;

        //incorrect result for embedded intermediate error

        printf ( "The final number is %i.", finals);

        return 0;

} 

 


A Good C Example

# include 

int main ()

{

        //declare variables of operands to be floats

        //since they include fractional results

        float finals, a, b, c, d;

        a = 6.0;

        b = 7.0;

        c = 6.0/7.0;

        d = 7.0/6.0;

        finals = a + b + c + d;

        printf ( "The final number is %f.", finals);

        return 0;

} 

 


A Java Example

import java.io.*;

//class begins here

class integerinter3

{

public static void main(String[] args) 

{

        float finals, a, b, c, d;

        a = 6;

        b = 7;

        c = 6/7;

        d = 7/6;

        finals = a + b + c + d;

        System.out.println ("The final is "+ finals);

        System.out.println();

        }

}//end of class

 

Topic-3 Named Constants

A named constant is a variable that you use to set a value in a function that

cannot be changed once assigned. They enable the programmer to refer to a value 

as a word rather than a number. For example, if the maximum number of students 

in a school is 10,000, you would create a variable called MaxStudents and assign 

the value of 10000 to it. This makes the program much easier to read.

Another benefit of using named constants is ease of change. If the capacity of the school suddenly goes up to 15,000, you can change the value throughout your program by changing the declaration variable at the beginning.

Tips on using Named Constants:



  1. Use named constants in data declarations:
    Using named constants helps the program become more readable and maintainable. The size of the data declarations and statements that use the named constants are easily identified and modified, if nessecary.
  2. Don't Use Literals:
    It is better to use named constants. Avoid the use of numbers throughout the program,and eliminate them in old programs. Simulate named constants with global variables: If the language you are using doesn't support named constants, use global variables to create them. This will ensure that you have access to the advantages of the named constants in your programs.
  3. Use named constants consistently:
    Do not mix named constants and literals in the same function or statement. This causes many errors, not only in the original project, but in subsequent modifications. For example, when modifiying, it is easy to change the named constant, but it is difficult to find the hard-coded literals in the function.



Example Programs





Good Java Example

Const ZipCodeLength_c = 5;

int [] StudentZipCode_t = new [ZipCodeLength_c ];

for (int i = 0;i  9))

System.out.println ("Enter a valid Zip Code");

}

Bad Java Example

int [] StudentZipCode_t = new [5];

for (int i = 0;i <5; i++) { if ((StudentZipCode[i] < 0) || (StudentZipCode[i]> 9))

System.out.println ("Enter a valid Zip Code");

}


Good C++ Example

const int ZipCodeLength_c = 5;

char StudentZipCode_t [ZipCodeLength_c];

for (int i = 0; i 9))

cout << " Enter a valid Zip Code"; } 

Bad C++ Example

char StudentZipCode_t [5];

for (int i = 0; i <5; i++) { if ((StudentZipCode[i] < 0) || (StudentZipCode[i]>9))

cout << " Enter a valid Zip Code"; } 

Good C Example

const int ZipCodeLength_c = 5;

char StudentZipCode_t [ZipCodeLength_c];

for (int i = 0; i 9))

printf " Enter a valid Zip Code";

}

Bad C Example

const int ZipCodeLength_c = 5;

char StudentZipCode_t [ZipCodeLength_c];

for (int i = 0; i <5; i++) { if ((StudentZipCode[i] < 0) || (StudentZipCode[i]>9))

printf " Enter a valid Zip Code";

}

Topic-4 The float Data Type

The floating-point number is another data type in the C/C++ and Java languages. Unlike 

an integer number, a floating-point number contains a decimal point. For instance, 7.01 is

a floating-point number; so are 5.71 and -3.14. A floating-point number is also called 

a real number.


The main consideration for floating-point numbers is that many fractional decimal numbers can't be represented using 1s and 0s available on a digital computer. Nonterminating decimals like 1/3 or 1/7 can usually be represented to only 7 or 15 digits of accuracy.



 

Specific guidelines for using floating-point numbers:




Example Programs

Good example for C

=====================================================================

/* Filename: good1.c */

/* This function adds two floats and return the result */

 

#include 

 

float flt_add (flt m, flt n)

{

 

float result1;

result1 = m + n; // adds two floats

return result1; // assigns the computation result to result1

}

 

int main ( )

{

float sum;

 

sum = flt_add (2,000,000.00, 1,000,000.00);

printf("The sum is %f.\n", sum);

 

return 0;

}

=====================================================================

The output of the program is:

The sum 3,000,000.00

 




A Bad Example for C

=====================================================================

/* Filename: bad1.c */

/* This function subtracts two floats and return the result */

 

#include 

 

float flt_subtract (flt p, flt q)

{

float result2;

result1 = p - q;

return result2;

}

 

int main ( )

{

float difference;

 

difference = flt_subtract ( 2,000,000.00, 0.02);

printf ("The difference is %f\n", difference);

 

return 0;

}

=====================================================================

The output of the program is:

The difference is 2,000,000.00 

 




A Good Example for C++

=====================================================================

// Filename: good1.cpp

// Demonstrate addition floating-point numbers with greatly different magnitude

 

#include 

 

int main()

{

float sum;

float first_num = 1.00;

float second_num = 0.0001;

sum = first_num + second_num;

cout << "Sum is: " << sum << "\n"; return 0; }="====================================================================" The output of the program is: Sum is: 1.0001 

A Bad Example for C++

=====================================================================

// Filename: bad1.cpp

// Demonstrate subtraction of floating-point numbers with greatly different

magnitude

 

#include 

 

int main()

{

float difference;

float first_num = 100.00;

float second_num = 0.000001;

difference = first_num - second_num;

cout << "Difference is: " << difference << "\n"; return 0; }="====================================================================" The output of the program is: Difference is: 100 

A Good Example for Java

=====================================================================

// Filename: good1.java

// Addition of floating-point numbers

 

import java.io.*;

 

class Numbers {

public static void main (String[ ] args) {

double num1 = 1.00;

double num2 = 2.03;

double num = num1 + num2;

System.out.println (num);

} // end main

} // end class

=====================================================================

The output of the program is:

3.03

 




A Bad Example for Java

=====================================================================

// Filename: bad1.java

// Addition of floating-point numbers

 

import java.io.*;

 

class Number { 

public static void main (String[ ] args) {

                double num1 = 1.000000001;

                double num2 = 20000000;

                double num = num1 + num2;

                System.out.println (num);

} // end main

} // end of classs {

=====================================================================

The output of the program is:

2.0000001E7

 

 


Good Example for C

=====================================================================

// Filename: good2.c

// Comparisons of floating-point numbers

 

#include 

 

main( )

{

float x, y, sum; // Declare the variables

 

x = 0.50;

y = 0.50;

sum = x + y;

if (sum = = 1) // compare if sum equals to 1

printf("Equal");

else

printf("Not equal");

return 0;

}

=====================================================================

The output of the program is:

Equal

 

 

 

A Bad Example for C

=====================================================================

// Filename: bad2.c

// Comparisons of floating-point numbers

 

#include 

 

main( )

{

int x, y

float division;

 

x = 1;

y = 2;

division = x / y;

if (division = = 0.50)

printf("Equal");

else

printf("Not equal");

return 0;

} // end main

=====================================================================

The Output of the program is:

Not equal

 

The equal-to relationship does not hold. This is because the truncation of the

integer division which is 1/2 produces 0, not 0.5.

 

 




A Good Example for C++

=====================================================================

// Filename: good2.cpp

// Equality comparison

#include 

#include 

 

class payGroup

{

char name[25];

float choosen_num;

public:

inline void init(char N[], float C);

inline char * getName (void);

inline int operator== (const payGroup & person);

inline int operator!= (const payGroup & person);

};

 

void payGroup::init(char N[], float C)

{

strcpy(name, N);

choosen_num = C;

}

 

char * payGroup::getName(void)

{

return name; // Return pointer to the name

}

 

int payGroup::operator = = (const payGroup & person)

{

if (choosen_num = = person.choosen_num)

return 1; // True

else

return 0; // False

}

 

int payGroup::operator != (const payGroup & person)

{

if (choosen_num != person.choosen_num)

return 1; // True

else

return 0; // False

}

 

main()

{

payGroup person1, person2;

// Put data in the object variables

person1.init("Stacy Miller", 1000.01); // avoid comparing numbers with greatly

different

// magnitude

person2.init("Lloyd Swadley", 1000.00);

 

// Perform comparisons

if (person1 != person2)

{

cout << person1.getName() << " and " << person2.getName(); cout << " have choosen different number \n"; } if (person1="=" person2) { cout << person2.getName() << " and " << person2.getName(); cout << " have choosen the same number \n"; } return 0 ; }="====================================================================" The output of the program is: Stacy Miller and Lloyd Swadley have choosen the same number 

A Bad Example for C++ ===================================================================== // Filename: bad2.cpp // Equality comparison #include #include class payGroup { char name[25]; float choosen_num; public: inline void init(char N[], float C); inline char * getName (void); inline int operator== (const payGroup & person); inline int operator!= (const payGroup & person); }; void payGroup::init(char N[], float C) { strcpy(name, N); choosen_num = C; } char * payGroup::getName(void) { return name; // Return pointer to the name } int payGroup::operator = = (const payGroup & person) { if (choosen_num = = person.choosen_num) return 1; // True else return 0; // False } int payGroup::operator != (const payGroup & person) { if (choosen_num != person.choosen_num) return 1; // True else return 0; // False } main() { payGroup person1, person2; // Put data in the object variables person1.init("Stacy Miller", 1000.001); // avoid comparing numbers with greatly different // magnitude person2.init("Lloyd Swadley", 1000.00); // Perform comparisons if (person1 != person2) { cout << person1.getName() << " and " << person2.getName(); cout << " have choosen different number \n"; } if (person1="=" person2) { cout << person2.getName() << " and " << person2.getName(); cout << " have choosen the same number \n"; } return 0 ; }="====================================================================" The output of the program is: Stacy Miller and Lloyd Swadley have choosen different number

A Good Example in Java ===================================================================== // Filename: good2.java // Determine the average and maximum grade of a set of test scores import java.io.*; class Average { public static void main (String [ ] args) throws IOException { int grade = 9999, count = 0, max = 0; // Careful initializations permits a different float sum = 0, average; // approach to the problem BufferedReader stdin = new BufferedReader (new InputStreamReader (System.in)); // Read and process the rest of the grades while (grade >= 0) { System.out.print ("Enter a grade (-1 to quit): "); System.out.flush(); grade = Integer.parseInt(stdn.readLine( )); if (grade >= 0) { count =count + 1; sum = sum + grade; if (grade > max) max = grade; } } if (count = = 0) System.out.println ("No valid grades were entered."); else { average = sum / count; System.out.println( ); System.out.println (" Total number of students: " + count); System.out.println ("Average grade: " + average); System.out.println ("Highest grade: " + max); } } // method main } // class average ===================================================================== The output of the program is: Enter a grade (-1 to quit): 87 Enter a grade (-1 to quit): 82 Enter a grade (-1 to quit): 94 Enter a grade (-1 to quit): 98 Enter a grade (-1 to quit): 73 Enter a grade (-1 to quit): 98 Enter a grade (-1 to quit): 80 Enter a grade (-1 to quit): -1 Total number of students: 7 Average grade: 87.4285 Highest grade: 98

A Bad Example in Java

=====================================================================

// Filename: bad2.java

// Determine the average and maximum grade of a set of test scores

 

import java.io.*;

 

class Average {

 

public static void main (String [ ] args) throws IOException {

int grade, count = 0, sum =0, max, average;

 

BufferedReader stdin = new BufferedReader

(new InputStreamReader (System.in));

 

// Get the first grade. Give max that initial value.

System.out.print ("Enter the first grade (-1 to quit): ");

System.out.flush();

grade = Integer.parseInt(stdn.readLine( ));

 

max = grade;

 

// Read and process the rest of the grades

while (grade >= 0) {

count =count + 1;

sum = sum + grade;

if (grade > max)

max = grade;

System.out.print ("Enter the next grade (-1 to quit): ");

System.out.flush();

grade = Integer.parseInt(stdn.readLine( ));

}

if (count = = 0)

System.out.println ("No valid grades were entered.");

else {

average = sum / count; 

System.out.println( );

System.out.println (" Total number of students: " + count);

System.out.println ("Average grade: " + average);

System.out.println ("Highest grade: " + max);

}

} // method main

} // class average

=====================================================================

 

The output of the program is:

 

Enter the first grade (-1 to quit): 87

Enter the next grade (-1 to quit): 82

Enter the next grade (-1 to quit): 94

Enter the next grade (-1 to quit): 98

Enter the next grade (-1 to quit): 73

Enter the next grade (-1 to quit): 98

Enter the next grade (-1 to quit): 80

Enter the next grade (-1 to quit): -1

 

Total number of students: 7

Average grade: 87

Highest grade: 98

 



Topic-5 Characters and Strings:



C++

Characters are stored in variables of type char. The statement 

		char ch3;

creates space in memory for a character and names it ch3. To store a particular character 

in this variable, use a statement like

		ch3 = 'a';

Character constants, such as 'a', 'B', '&' or '4', are surrounded by single quotes. 

The equal sign (=) causes the value on its right to be assigned to (placed in) the 

variable on its left; that is, following this statement, the variable ch3 will have the 

value 'a'. All characters are actually stored as numbers (which, as you know, is all a 

computer understands). ASCII code is used to translate characters into numbers. Thus 'A'

is 65, 'B' is 66, and so on.




Various special characters are represented by letters preceded by a backslash. This is 

called an escape sequence because the backslash causes the interpretation of the next 

character to "escape" from the normal ASCII code and indicate something different.




Some common escape sequence are listed as following:




'\n' New line. Causes the cursor to move to the start of the next line. (Same as a 

         carriage return plus a line feed.) 

'\t' Tab character. 

'\b' Backspace. 

'\r' Carriage return. Causes the cursor to move to the start of this line. Also generated 

         by the key.




Variables of type char are occasionally used to store whole numbers rather than characters. 

You can say

	ch3 = 44;

However, the range of numerical values that can be stored in type char is from -128 to 127, 

so this works only for very small numbers. Whole numbers are usually stored in variables of 

type int, which is faster for the computer to process than type char. A variable of type char 

occupies 1 byte, or 8 bits, of memory.




Tips for using characters and strings:



Bad example:

if (input_char =='\027') ...

Good example:

if (input_char ==ESCAPE) ...






C

Char type

* Be aware of the difference between string pointers and character arrays. The problem with

string pointers and character arrays arises because of the way C handles strings. 
  1. Be careful when expression involves an equal sign. Most C operations of string are strcmp(), strcpy() and strlen(). In C, assignments do not copy string literals to a string variable. For example, StringPtr= "A String"; In this case, "A String" is a pointer to a literal text string and the assignment simply lead pointer StringPtr to a point to the text string. It does not copy the contents to StringPtr.
  2. Remember to declare strings with length+1. In C, it is common to forget to leave room for the null terminator (the byte set to 0 at the end of the string). Easiest way to avoid this problem is to use a named constant to declare a string. The named constant you used should be used in the same way whenever you declare a string.


Example Programs

The following are two example using NAM E_LENGTH:





Good example: 




/* Declare the string to have length of "constant+1". 

Every other place in the program,

"constant" rather than "constant+1" is used. */

//string of length NAME_LENGTH

char string[NAME_LENGTH+1] ={0};        

//doing here...

/* Set the string to all 'A's using the constant, NAME_LENGTH, 

as the number of 'A's that can be copied. Note that NAME_LENGTH 

rather than NAME_LENGTH+1 is used. */

for (i=0; i 

Bad example:




char string[10] ={0};   //string of length 9. The "9" is a magic number.

//doing something here...

for (i=0; i<9; i++) string[i]="A" ; //doing something here... strncpy (string, some_other_string, 9); 

JAVA

Char types

In JAVA, the character class wraps a value of the primitive type char in an object. An object 

of type character contains a single field whose type is char. In addition, this class provides 

several methods for determining the type of a character and converting characters from 

uppercase to lowercase and vice versa.

Many of the methods of class character are defined in terms of a "Unicode attribute table" 

that specifies a name for every defined Unicode code point. The table also includes other 

attributes, such as a decimal value, an uppercase equivalent, a lowercase equivalent, and/or 

a titlecase equivalent.Similar to other languages, do not use magic characters and strings in

declaration.







Bad example:







//do not declare string using magic values

if (the_char =='\027') ...







Good example:







if (the_char ==ESCAPE) ...






 

Topic-6 Boolean Type


The bool keyword and the related literals true and false are used in situations involving 

logic tests. Bool type was typically implemented using an enum type. 

Use boolean variable to document your program. Instead of testing a boolean expression, you 

can assign the expression to a variable that makes the implication of the test unmistakable. 

In the example that follows, it is not clear whether the prpose of the if test is to check 

for completion, for an erro condition, or for something else.







Bad example:


 

if ((Element<0)|| (MAX_ELEMENTS < ElementIdx) || ElementIdx="=" LastElementIdx ) { //do your job here } 
In the next example, the use of boolean variables makes the purpose of the if test very clear. Good example: Finished = ((Element<0)|| (MAX_ELEMENTS < ElementIdx) ); RepeatedEntry="(ElementIdx" LastElementIdx ); if (Finished || RepeatedEntry) { //do your job here }
Use boolean variables to simplify complicated tests. Often you need to design a complicated test, it takes a long time before it is correct. When you try to modify it later, it can be very hard to understand the purpose of the program. The following examples show one example with vague boolean variable declaration which makes it difficult to correct later on.




Bad example:




bool AgeLargerThan60 = true;

if (AgeLargerThan60)

{

//doing something here...

}




Good example: 




bool IsOld= true;

if (IsOld)

{

//doing something here...

}

Topic-7 Enumerated type

An enumerated type is a type of data that allows each member of a class of objects to be 

Described in English. Enumerated types are a powerful alternative to display explicitly 

schemes such as "1 stands for red, 2 stands for green, 3 stands for blue, ...". This suggests 

several guidelines to use enumerated types.




*Use enumerated types for readability

instead of writing statements like:

if ChosenColor =1;


you can write readable expression like:

if ChosenColor =RED;


 

Bad example:




enum ChosenColor {1, 2, 3};

if ChosenColor = 1;

//doing something here...

if ChosenColor = 2;

//doing something here...

if ChosenColor = 3;

//doing something here...


 

Good example:




enum ChosenColor {RED, GREEN, BLUE};

if ChosenColor = RED;

//doing something here...

if ChosenColor = GREEN;

//doing something here...

if ChosenColor = BLUE;

//doing something here...

 




An enumerated data type-specified by the keyword enum -allows the programmer to invent a data

type and then specify exactly what values are allowed for the type.Creating a new type using 

enumerated data types is similar to creating a new type using a class. However, enumerated 

data types are much more limited than types created using classes. You can't create member 

functions to specify the operation of enum types; instead, they always behave more or less 

like integers. Enumerated types existed in C long before OOP was invented. You can think of 

them as a sort of poor person's approach to creating one's own data types. However, given the

right situation, they work well and they are simpler to implement than classes. Enumerated 

types are usually used when a variable has only a few allowable values, because every value 

must be named.


Here's how it would look:




Good example:




enum days_of_week {Sun, Mon, Tue, Wed, Thu, Fri, Sat };


They keyword enum is followed by the name of the type, days_of_week in this example, and then by braces enclosing a list of comma-separated value names. Enumerated means that all the values are listed explicitly. This is unlike the specification of an int, for example, which has a range of possible values (such as -32,768 to 32,767). In an enum, you must give a specific name to every allowable value. This is potentially confusing. Remember, the names used for enum values are not the names of variables. An int has values 0, 1, 2, and so on. The enum shown above has the values Sun, Mon, and so on up to Sat. As with classes and structures, specifying an enumerated type is not the same as actually is defined as an int variable,
Bad example:
day1 = Easter;
will not compile because day1 is a variable of type days_of_week and Easter is not on the list of possible values for days_of_week.

Topic-8 Use of Pointers in C and C++ Programming Languages:

C and C++ use pointers, while Java does not make use of pointers. Pointers are a very tricky concept to make use of in programming languages. Pointers are an area where errors are easy to make, and special precautions should be used when they are part of a program. To use pointers easily, you should have an thorough understanding of the memory usage given by the particular compiler you are using.

Memory Location:

Hexadecimal notation is often used in computers to contain an address. A pointer has only this address contained in it. You must get to the address to make use of the data that the pointer points at, and this information must be interpreted correctly.

Interpreting the Contents of a Memory Location:

A pointer can have different base types - it can be of type integer (int), string (str), floating-point, etc. All these types could simultaneously point one memory location, but only one will correctly interpret the contents of that address. A strategy to use in understanding pointers is to remember that by using a specific type of pointer, the contents of a certain address will be interpreted correctly. Depending on the base type of pointer being used, the memory contents will be interpreted as strings, integers, floating point, etc. You must use careful judgement when using the pointer to get at the memory contents; the incorrect pointer type for what the memory address contains will give meaningless results.

I. Things to Watch Out for With Pointers:

The bulk of the work in correcting a pointer error is trying to locate the cause of the error. Mostly, errors occur because the pointer is not pointing at what you intend it to point at. Memory corruption can occur when after giving a value to badly chosen pointer variable, then you put data into a memory area where you should not have. This is not something you want to do - it can have unpredictable results on your program, and cause it to crash hard. Successful pointers requires a two sided strategy. The first thing is to avoid creating pointer errors to begin with. The second thing is to detect errors as soon after they are coded as possible. Here is how to do this:

Isolate pointer operations in routines:

If you are linked to several places in a program with pointers. It is easier to write access routines such as Next(), Previous(), etc. rather than traversing the list manually each time. This minimizes the possibility of making mistakes that spread throughout the program. Check pointers before using them: Make sure that pointers point to a reasonable memory location. If you have pointers that point to memory locations before or after your data structure, you will have a problem. Write access routines that manipulate your pointers for you, and automatically bounds check your data structures.Check the variable referenced by the pointer before using it: Perform reasonableness checks on the value your pointer points to. If the range of values is between 0 and 100, and you should be wary of a value over 100. This can also be done automatically if you use access routines.

Use tag fields to check for corrupted memory:

Use a "tag field" in your field for error checking. When you allocate a variable, you can add a structure that error checks. This value should remain unchanged when you use the variable. If has changed, the data has been corrupted.

Add explicit redundancies:

The alternative to tag fields, redundancies also can error check for you. If the data in redundant fields doesn't match, you know the memory has been corrupted.

set pointers to NULL after freeing or disposing of them:

A dangling pointer is the use of a pointer that has been cleared. These errors are hard to detect because it doesn't produce any symptoms. You can also do this automatically in an access routine.

Use extra pointers for clarity:

A variable shouldn't be used for more than one purpose, so add them if it makes the code easier to read.

Simplify complicated pointer expressions:

Complicated pointer expressions make for code that has to be figured out rather than read. If your code contains a complicated expression, assign it to a well named variable to clarify the intent of the operation. It will help in readablility.

Write routines to keep track of pointer allocations:

It is easy to ruin a program by freeing a pointer once its already been freed. Not may languages detect this problem, so you can write a routine to do this for you. You can keep a list of the pointers you have allocated and check whether a pointer is in the list before you dispose of it.

Allocate a tag field in the null pointer detection routines:

This will help check the null pointer for corruption. If you accidentially nullify the pointer again, the tag field will have changed, and the routine will detect the corruption.

Draw a picture:

Code descriptions can be confusing, so it helps to draw a picture.

Free pointers in linked lists in the right order:

A common problem in working with dynamically allocated linked lists is freeing the first pointer in the list first and then not being able to get to the next pointer in the list. To avoid this problem, make sure that you have a pointer to the next element in a list before you free the current one.

Write a routine to output pointer addresses:

Write a routine that takes a pointer as an argument and returns a string version of the pointer. Then use this routine to output the address to the screen.

Allocate a reserve parachute of memory:

If your program uses dynamic memory, you need to avoid suddenly running out of memory. One way to give your program a margin of error is to pre-allocate a memory parachute. Allocate the amount of memory needed at the beginning of the program as a reserve parachute. When you run out of memory, write the program to free the reserve parachute, clean up and shut down.

Use a nonpointer technique:

Pointers are harder than average to understand, their error prone, and they tend to require machine dependent, unportable code. Try to use an alternative to pointers that works reasonably well.

II. C-Pointer Pointers

Use explicit pointer types rather than the default type:

C lets you use char or void pointers for any type of variable. As long as the pointer points, the language doesn't care what it points at. If you use expicit types for your pointers, the compiler can give you warnings about mismatched pointer types and inappropriate dereferences. If you don't, you can't. Use the specific pointer type whenever you can.

Avoid type casting:

Avoid squeezing a variable of one type into the space for avariable of another type. This turns off the compliers ability to check for mismatches and creates a hole in the defensive programming technique.

Follow the asterix rule for parameter passing:

You can pass an argument back from a routine in C only if you have an asterix (*) in front of the argument in the assignment statement.Use sizeof() to determine the size of a variable in a memory allocation: It's easier to use sizeof() than to look up the size in a manual, and it works for self made structures. It requires little maintentance since you can change types you have defined and allocations will be adjusted automatically.

Example Programs:


Java doesn't have an explicit pointer type C++ Example is listed as same as C Example

C Example Code


 

C Example of Bad Code

void insert_link

( 

NODE * CrntNode,

NODE * InsertNode

)

{

/* insert "InsertNode" after "CrntNode"*/

InsertNode -> Next = CrntNode -> Next;

InsertNode -> Previous = CrntNode;

if ( CrntNode -> Next != NULL)

{

CrntNode -> Next -> Previous = InsertNode; // this line is difficult to read

}

CrntNode -> Next = InsertNode;

}




 

C Example of Bad Code




 

void insert_link

( 

NODE * CrntNode,

NODE * NewMiddleNode

)

{

NODE * FollowingNode;

/* insert "NewMiddleNode" between "StartNode" and "FollowingNode" */

FollowingNode = StartNode -> Next;

NewMiddleNode -> Next = FollowingNode;

NewMiddleNode -> Previous = StartNode;

if ( FollowingNode != NULL)

{

FollowingNode -> Previous = NewMiddleNode;

}

StartNode -> Next = NewMiddleNode;

}



Go back to Considerations When Using Built-in Data Type


 Chapter Top 



Go to Next: Aggregated Data Type


 Aggregate 



Go back to Computer Science Department Homepage

 

CS Home Page




Author: Quanxiang Li, Sirigon Sukpan, Hua Ma, Cyren Aldecoa, Gerald Barrie, Curtis Ferchoff
Reference:
Code Complete, A Practical Handbook of Software Construction. Steve McConnell. Microsoft Press (1993).

Last Modified: Friday, 06-June-2000 15:03:53 CST By Quanxiang Li
Copyright 2000 Department of Computer Science, University of Regina.


[CS Dept Home Page]