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.
Some special considerations should be given when using numbers.
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
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
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'.
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
#includeint 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; }
# includeint 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 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
#includeint 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; }
#includeint 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; }
// show conformed type comparison # includeint 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; }
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
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
//disguised divide-by-zero error # includeint 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; }
# includeint main() { int radius = 3, circum; const double PI=3.1416; circum = 2* PI * radius; cout << "The circumference is " << circum << " inches" << endl; return 0; }
# includeint 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; }
# includemain () { 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; }
# includeint main () { int profits, employees; profits = 3; employees = 2; //explicit conversion to float printf ("Each employee gets %f. ", (float) profits/employees); return 0; }
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
// The result of the program is wrong //though the syntax and logic are all right # includeint 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; }
# includeint 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; }
# includemain () { 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; }
# includeint 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; }
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
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
# includeint 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; }
# includeint 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; }
#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; }
# includeint 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; }
# includeint 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; }
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
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.
Const ZipCodeLength_c = 5; int [] StudentZipCode_t = new [ZipCodeLength_c ]; for (int i = 0;i9)) System.out.println ("Enter a valid Zip Code"); }
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"); }
const int ZipCodeLength_c = 5; char StudentZipCode_t [ZipCodeLength_c]; for (int i = 0; i9)) cout << " Enter a valid Zip Code"; }
char StudentZipCode_t [5]; for (int i = 0; i <5; i++) { if ((StudentZipCode[i] < 0) || (StudentZipCode[i]>9)) cout << " Enter a valid Zip Code"; }
const int ZipCodeLength_c = 5; char StudentZipCode_t [ZipCodeLength_c]; for (int i = 0; i9)) printf " Enter a valid Zip Code"; }
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"; }
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.
===================================================================== /* Filename: good1.c */ /* This function adds two floats and return the result */ #includefloat 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
===================================================================== /* Filename: bad1.c */ /* This function subtracts two floats and return the result */ #includefloat 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
===================================================================== // Filename: good1.cpp // Demonstrate addition floating-point numbers with greatly different magnitude #includeint 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
===================================================================== // Filename: bad1.cpp // Demonstrate subtraction of floating-point numbers with greatly different magnitude #includeint 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
===================================================================== // 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
===================================================================== // 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
===================================================================== // Filename: good2.c // Comparisons of floating-point numbers #includemain( ) { 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
===================================================================== // Filename: bad2.c // Comparisons of floating-point numbers #includemain( ) { 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.
===================================================================== // 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
===================================================================== // 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
Rounding-error problems usually occurs when numbers with greatly different magnitude is used in the program. The theory behind this is similar to the first guidelines.
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.
Bad example: if (input_char =='\027') ... Good example: if (input_char ==ESCAPE) ...
* 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.
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; iBad 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);
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) ...
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... }
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.
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.
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.
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.
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:
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 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.
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.
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.
A variable shouldn't be used for more than one purpose, so add them if it makes the code easier to read.
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.
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.
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.
Code descriptions can be confusing, so it helps to draw a picture.
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 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.
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.
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.
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 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.
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.
Java doesn't have an explicit pointer type C++ Example is listed as same as C Example
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.