440 likes | 592 Views
Data Structures. Instructor: Sanchita Mal-Sarkar Course: CIS 265. Data representation. Computer represents “on” with a 1 and “off” with a 0. These numbers are called binary digits or bits. Binary number system: most widely used method for interpreting bit settings as nonnegative integers.
E N D
Data Structures Instructor: Sanchita Mal-Sarkar Course: CIS 265
Data representation • Computer represents “on” with a 1 and “off” with a 0. These numbers are called binary digits or bits. • Binary number system: most widely used method for interpreting bit settings as nonnegative integers. • 38 (decimal) = 21 +22+25 = 00100110
Ones complement notation • One of the widely used methods for representing negative binary numbers. • A negative number is represented by changing each bit to the opposite bit setting. • Example: • 38 (decimal) = 00100110 (binary) • -38 (decimal) = 11011001 (binary)
Twos complement notation • Another popular method of representing negative binary number • In this method, 1 is added to the ones complement representation of a negative number. • Example: -38 (decimal) = 11011001 (ones complement) -38 (decimal) = 11011010 (twos complement)
Floating-point notation • Usual method to represent real numbers • Real number is represented by a number, called a mantissa, times a base raised to an integer power, called an exponent. • Example: 387.53 = 38753 x 10 -2 Other possibilities .38753 x 10 3, 387.53 x100 (we choose mantissa is an integer with no tailing 0s)
Floating-point notation(cont.) • A real number is represented by a 32-bit string. • 24-bit for mantissa and 8-bit for exponent. • Base is fixed to 10. • Example 100 = 0000000000000000000000100000010 -387.53 = 11111111011010001001111111111110 387.53 = 00000000100101110110000111111110 ( 24-bit binary representation of 38753 is 000000001001011101100001 8-bit twos complement binary representation of -2 is 11111110)
Modular Programming & Pointers • Modules in C are called functions. • Each module or smaller piece is more manageable than the original program. • This technique is called divide and conquer. • Arguments make functions more versatile because it enable a function to manipulate different data each time it is called. • You know, how to pass input parameters into a function. • I will discuss how to use output parameters to return multiple results from a function. • Pointer to a variable provides the address to that type of variable.
Example • #include <stdio.h> • #include <math.h> • void determine_sign(double num, char *signp); • int main(void) • { • double value; • char sn; • printf(“Enter a value>”); • scanf(“%lf”, &value); • determine_sign( value, &sn); • printf(“The sign of %.4f is: %c\n”, value, sn); • return (0); • }
Example • void determine_sign(double num, char *signp) • { • if (num < 0) • *sign = ‘-’; • else if (num == 0) • *sign = ‘ ‘; • else • *sign = ‘+’; • }
Pointers • A pointer is a variable that contains memory address as its value. • A variable directly contains a specific value. • A pointer contains an address of a variable that contains a specific value. • We use pointers extensively to create and manipulate dynamic data structures ( linked lists, queues, stacks, and trees), and to simulate call by reference.
Pointer • Pointers should be initialized either when they are declared or in an assignment statement. • Pointer can be initialized to 0, NULL, or an address. • A pointer with the value NULL points to nothing. • Initializing a pointer to 0 is equivalent to initializing to NULL (NULL is preferred); • NULL is a symbolic constant defined in <stdio.h> header file.
84 ptr x Representation of a Pointer • int x = 84; // declaration • int *ptr; // declaration • ptr = &x; X directly references a variable whose value is 84 84 Assigned the address of the variable x to pointer variable ptr. Direct value of ptr is the address of x. x ptr indirectly references a variable whose value is 84
ptr x 60000 84 50000 60000 Ptr indirectly references a variable whose value is 84 X directly references a variable whose value is 84 Representation of x and ptr in memory • int x = 84; // declaration • int *ptr; // declaration • ptr = &x; // assigned the address of the // variable x to pointer variable ptr.
Different ways to pass arguments to a function • Two ways to invoke functions: • Call by value • Call by reference • Call by value: • When arguments are passed call by value, • a copy of the argument’s value is made and passed to the called function. • Changes to the copy do not affect an original variable’s value in the caller.
Call by Reference • When an argument is passed by reference, • the caller actually allows the called function to modify the original variable’s value. • It is possible to simulate call by reference by using address operators and indirection operators.
Cube a variable using call by value • #include <stdio.h> • int cubeByValue(int); • main() • { • int number = 5, number1; • printf(“The original value of number is %d\n”, number); • number1 = cubeByvalue(number)); • printf(“The new value of number is %d\n”, number1); • return 0; • } • int cubeByValue(int n) • { • return n * n * n; • }
Cube a variable using call by Reference • #include <stdio.h> • void cubeByReference(int *); • int main() • { • int number = 5; • printf(“The original value of number is %d\n”, number); • cubeByReferencee(&number)); • printf(“The new value of number is %d\n”, number); • return 0; • } • void cubeBy Reference(int *nPtr) • { • *nPtr = *nPtr ** nPtr * *nPtr; • }
Pointer Arithmetic • A limited set of arithmetic operators may be performed on pointers. • A pointer may be incremented (++) or decremented (--). • An integer may be added to a pointer (+ or +=). • An integer may be subtracted from a pointer • (+ or +=). • One pointer may be subtracted from another.
ptr 1 2 3 4 5 a a + 1 a + 3 Example • int a[10]= {1,2,3,4,5}; • int *ptr; • ptr = a; • When an integer is added to or subtracted from a pointer, the pointer is not simply incremented or decremented by that integer. • It depends on the size of the object a pointer point to => machine dependent.
3016 3000 3008 3004 3012 1 2 3 4 5 a ptr a + 3 a + 1 Example (Increment) • When an integer is added to a pointer, the pointer is incremented by that integer times the size of the object to which the pointer points to. • int *ptr; • ptr = a; • ptr += 2; • will produce: • 3008 (3000 + 2 * 4) • integer is stored in 4 bytes of memory.
Example (Decrement) • When an integer is subtracted from a pointer, decremented by that integer times the size of the object to which the pointer points to. • int *ptr; • ptr = a; • ptr += 2; • ptr -= 1; • will produce: • 3004 (3008 - 1 * 4) • integer is stored in 4 bytes of memory. 3016 3000 3008 3004 3012 1 2 3 4 5 a ptr a + 3 a + 1
3016 3000 3008 3004 3012 1 2 3 4 5 a ptr1 ptr2 Subtraction • Pointer variables may be subtracted from one another. • ptr1 contains the location 3000. • ptr2 contains the location 3008. • x = ptr2 - ptr1; • = 2 • will assign to x • the number of • array elements • from ptr1 to ptr2
ptr 1 2 3 4 5 a a[1] a[3] Relationship between Pointers and Arrays • Arrays and Pointers are intimately related in C. • Array subscripting notation is converted to pointer notation during compilation. • Array name is a pointer to the first element of the array. • ptr = &a[0] • *(ptr + 3) a[3] • &a[3] (ptr + 3) • a += 2 invalid => attempts to modify the value of array name with pointer arithmetic. Offset to the pointer
Array of Pointers • Array may contain pointers (e.g. string array). • In C, string is essentially a pointer to its first character. • Each entry in an array of strings is actually a pointer to the first character of a string. • Example: • char *names[4] = {“John”, “Cynthia”, “David”, “Daniel”}; • names[4] => an array of 4 elements. • Char * => each element of array names is of type “pointer to char.” • Four array elements are: “John”, “Cynthia”, “David”, “Ruben”. • Each of these are stored in memory as a NULL-terminated character string that is one character longer than the number of characters between quotes. • E.g. Four strings are 5, 8, 6, and 7.
names[0] ‘J’ ‘o’ ‘h’ ‘n’ ‘\0’ names[1] ‘C’ ‘y’ ‘n’ ‘t’ ‘h’ ‘i’ ‘a’ ‘\0’ names[2] ‘D’ ‘a’ ‘v’ ‘i’ ‘d’ ‘\0’ names[3] ‘D’ ‘a’ ‘n’ ‘i’ ‘e’ ‘l’ ‘\0’ Example of array of pointers • It seems that the strings are placed in the names array, • Actually, only the pointers are stored in the array. • Each pointer points to the first character of its corresponding string. • Names is a fixed size array. • However it provides access to character strings of any length. • Names could have been placed into a double array of fixed number of columns per row => memory could be wasted.
Pointer to Functions • Pointer to a function contains the address of the function in memory. • A function name is really the starting address in memory of code that performs the function’s task. • Pointers to functions can be passed to functions, returned from functions, stored in arrays, and assigned to another function pointers. • int (*compare)(int num[1], int num[4]) Parenthesis s are needed around *compare because * has lower precedence than parentheses enclosing the function parameters.
Representation and conversion of Numeric Types • Why we need more than one numeric type ? • We could use data type double for all numbers. However, they are represented in the computer’s memory in different ways. Here are some advantages of integer data type: • On many computers, operation will be faster if we use integer instead of type double. • We need less space to store integer number . • Operations with integer are always precise. But in operations with double numbers can result in some loss of accuracy or round-off error.
Advantages of Type double Format • A real number has an integral part and a fractional part. But an integer number can not have a fractional part. So real number can not be represented by an integer, it can be represented by double data type. • Another advantage of the data type double is that much larger range of numbers can be represented as compared to type int. • Actual ranges vary from one implementation to another. • ANSI standard for C • min range of positive values of type int: 1- 32, 767 • min range of positive values of type double: 10 -37 to 10 37
type int format type double format binary number mantissa exponent Internal formats of Type int & Type double • All data are represented in memory as binary strings (strings of 0s and 1s). • However, the binary string stored for type int value 24 is not the same as the binary string stored for the type double number 24.0. • The actual internal representation is computer dependent. • Positive integers are represented by standard binary numbers. Integer 24 is represented by binary number 11000. • The format of type double is analogous to scientific notation.
Scientific Notation • A real number has an integral part and a fractional part which are separated by a decimal point. • Very large or very small values can be represented by scientific notation. • Example: for the value 123000.0 => scientific notation: 1.23 • In C scientific notation: 1.23e5 or 1.23E5 • Read the letter e or E as "times 10 to the power". • If the exponent has a minus sign, the decimal point is moved to the left. • Example: 0.34e-4 == 0.000034
Numerical Inaccuracies • Sometimes an error occurs in representing real numbers. • Analogy: in decimal system, 1/3 is 0.333333….. • Some fractions canot be represented exactly as binary numbers in the mantissa of the type double format. • This inaccuracy is called representational error. • It depends on the number of binary digits used in the mantissa. • The more bits, the smaller the error. • An equality comparison of two type double values can lead to unexpected results. • Example • for (count = 0.0; count != 10.0; count = count + 0.1) • { • } Infinite loop
Cancellation Error • When you add a very large and a very small real numbers, the larger number may cancel out the smaller number. • Results in cancellation error. • Example: • 1000.0 + 0.000000231 = 1000.0 • (On some computers)
Arithmetic Underflow • If we multiply two very small numbers, the result may be too small to be represented accurately. • The computational result will be represented by zero. • This phenomenon is called arithmetic underflow.
Arithmetic Overflow • If we multiply two very large numbers, the result may be too large to be represented. • This phenomenon is called arithmetic overflow. • Different C compilers handle it in different ways.
Automatic Conversion of Data Types • In several cases, data of one numeric type are automatically converted to another numeric type. • Some examples: • int k = 5, m = 4, n; • double x = 1.5, y = 2.1, z; • Expression of different numeric types: • k + x Value of int variable k is converted • Value is 6.5 to type double format before operation is performed. • RHS is of type int and LHS is of type double: • z = k / m; Expression is evaluated first. Then, the result is converted to type double format for assignment. Expression value = 1 z = 1.0
Automatic Conversion of Data Types • Example: • int k = 5, m = 4, n; • double x = 1.5, y = 2.1, z; • RHS is of type double and LHS is of type int: • n = x * y; Expression is evaluated first. Then, the result is converted to type int format for assignment, and fractional part is lost. Expression value = 3.15; n = 3
Explicit Conversion of Data Types • C also provides an explicit type conversion operation called a cast. • Examples: • Using cast operation • int n1, n2; • double frac; • frac = (double)n1 / (double)n2; • 2.0 / 4.0 • 0.5 • Without cast operation • frac = n1 / n2; • 2 / 4 integer division • 0 Result: frac = 0.5 Result: frac = 0.0
Explicit Conversion of Data Types Difference • A. frac = (double)(n1 / n2); and • B. frac = (double)n1 / (double)n2; • C. frac = (double)n1 /n2; • The quotient n1/n2 is computed first, results in loss of fractional part. • The cast to double convertsthe whole number quotient tp type dpouble. • frac = (double)n1 / (double)n2; • 2.0 / 4.0 • 0.5 • frac = (double)n1 / n2; n2 will automatically be converted to double.
Explicit Conversion of Data Types • Sometimes we include casts that do not affect the result but simply make clear to the reader the conversions that would occur automatically. • Example: int x, sqrt_x; • sqrt_x = (int)sqrt((double)x); • The formal parameter of sqrt function is of type double. • The actual argument x is of type int. • x will automatically be converted to type double. • sqrt function returns a value of type double. • This value will automatically be converted to type int since sqrt_x is of type int. • Note: When a cast operation is applied to a variable, the conversion changes the value of the expression, but it does not change what is stored in the variable.
Representation & Conversion of Type char • We can declare variable of type char to represent a single character • A character can be a letter, digit, or punctuation mark. • A character is enclosed in apostrophes.(e.g. ‘A’, ‘3’). • We can compare character values using equality operators (== and !=) and relational operators (<,<=, >, >=). • In ASCII (American Standard Code for Information Interchange): • digit character ‘0’ = 48 (decimal code value) • ‘9’ = 57 (‘0’<‘1’<‘2’<‘3’<‘4’…….<‘9’) • ‘A’ = 65 • ‘Z’ = 90 (‘A’< ‘B’<‘C’……..<‘X’<‘Y’<‘Z’) • ‘a’ = 97 • ‘z’ = 122 (‘a’< ‘b’<‘c’……..<‘x’<‘y’<‘z’) • C allows conversion of type char to type int and vice versa.
Enumerated Types • ANSI C allows us to associate a numeric code with each category by creating an enumerated type that has its own list of meaningful values. • typedef can be used to name user-defined types. • Example: • typedef enum • { sunday, monday, tuesday, wednesday, thursday, friday, • saturday} • day_t; • enumerated type day_t has seven possible values (enumeration constants). • sunday will be represented as the integer 0, monday as integer 1, and so on. • day_t today; // declaration of variable today.
Examples of Enumerated Types • Class_t is an enumerated data type: • typedef enum • {fresh, soph, jr, sr} • class_t; • What is the value of each of the following? • (int) sr , (class_t) 0, (class_t)((int)soph + 1) • What is displayed by this code fragment? • for (class = fresh; class <= sr; ++class) • printf(“%d “, class); 3 fresh jr 0 1 2 3
Example of Enumerated Type • Example: • typedef enum • { sunday, monday, tuesday, wednesday, thursday, friday, • saturday} • day_t; • day_t next(day_t today) • { • day_t next; • if (today == saturday) • next = sunday; • else • next = (day_t)((int)today + 1); • return (next); • }
Another Example of Enumerated Type • typedef enum • { sunday, monday, tuesday, wednesday, thursday, friday, • saturday} • day_t; • void print_day (day_t day) • { • switch (day) • { • case sunday: • printf(“sunday”); • break; • case monday: • printf(“monday”); • break; • default: printf(“Invalid Code”); • } • }