350 likes | 487 Views
Lecture 2. System Programming in C. Announce. Sample programs texts available on home page The C Programming Language – available in electronic form at: http://ldw.ok.ee/C/piibel/index.html. Lecture Summary. More on standard I/O Type conversion Character type and programs
E N D
Lecture 2 System Programming in C
Announce • Sample programs texts available on home page • The C Programming Language – available in electronic form at: http://ldw.ok.ee/C/piibel/index.html
Lecture Summary • More on standard I/O • Type conversion • Character type and programs • Arrays & Pointers • String • main function arguments
More on Standard I/O - printf int printf(string, param1, param2, …) • param1, param2, etc. are optional, their number depends on the string contents • String consists of: • Ordinary characters • Conversion specifiers – commands to print corresponding parameter instead of it • Conversion specifier has form of: • %[flag][width][.precision][length]type • For now, we need three fields: • width – minimal width of printed parameter • precision – number of digits after the decimal point
Printf contd. • Type – may be one of: • d, i - int, print as decimal • o - unsigned int, print as octal • x, X - unsigned int, print as hexadecimal • u - unsigned int, print as decimal • c - char, print character • s - string • f - double, print in 1234.5678 notation • % - print ‘%’ sign, no parameter is consumed • See MSDN for the rest of types/specifiers.
Printf examples int x = 10; double a = 6.0; double b = 5.8888; printf ("just a string\n"); /* output is: just a string*/ printf ("%d dec = %o oct = %X hex\n", x, x, x); /* output is: 10 dec = 12 oct = A hex */ printf ("x is %d, 50%% of x is %d\n", x, x / 2); /* output is: x is 10, 50% of x is 5 */ printf ("a=%6.3f b=%6.3f\n", a, b ); /* output is: a= 6.000 b= 5.889 */
Symbolic constants • A way to define meaningful names to important constants • #define namereplacement_text • For example: #define PI 3.14 #define LOWER_LIMIT 0
Example on symbolic constants #include <stdio.h> #define LOWER 0 /* lower limit */ #define UPPER 300 /* upper limit */ #define STEP 20 /* step size */ main() { int fahr; fahr = LOWER; while(fahr <= UPPER) { printf ("%d\t%d\n", fahr, 5 * (fahr-32) /9); fahr += STEP; } }
Integer division • If both operands are integers, the result is integer too: • 5/2 = 2 (integer part of result is taken) 3/2 = 1 • 5 % 2 = 1 (integer division remainder) • Example: int fahr; for (fahr = LOWER; fahr <= UPPER; fahr += STEP) printf ("%d\t%d\n", fahr, 5 * (fahr-32) /9); • Output: 0 -17 20 -6 40 4 60 15 • What if non-integer division is needed?
Type Conversions • Explicit conversion: (type)variable_name • Example: int i = 7, j = 5; float f = (float)i/(float)j; /* f = 1.4*/
Type Conversions contd. • Implicit Conversion • If one of the operands is float, another (if it’s int) is converted to float, for example: int i = 7; float f = 5.0; float d = i/f; /* d = 1.4*/ • Note that constants differ: 5 represents integer constant, while 5.0 represent double constant. This may be used to initiate implicit conversion – compare: int i = 7; double j = i/5; /* j=1.0 */ double k = i/5.0; /* k=1.4 */
Corrected conversion program Loop body: int fahr; for (fahr = LOWER; fahr <= UPPER; fahr += STEP) printf ("%3d %6.1f\n", fahr, (5.0/9.0)*(fahr-32)); Output: 0 -17.8 20 -6.7 40 4.4 60 15.6 Now correct (FP) results!
More on Implicit Conversion • General rule is that if operands are of different type, they are converted to “most capable one” – capability order is: long double > double > float > long > int • short and char are always converted to int • Rules are more complex if consider unsigned types too…
Unsigned Data Types – Conversion • If one operand is unsigned int and another – signed int, then signed int is converted to unsigned. For instance: int i = -1; unsigned int j =0; if (j>i) printf("0 is greater than -1\n"); else printf("0 is less than -1\n"); • i (which is -1) is converted to unsigned int, which gives INT_MAX – 1 = big number. • To avoid problem, explicitly convert both numbers to (long): if ((long)j>(long)i)
Character Types • Character constants are given in single quotes: ‘a’, ‘b’, ‘1’, ‘$’ • Characters are represented as numbers – thus arithmetic operations are allowed: char c = 'a'; int k = (c < 'b'); /* =1 if c < 'b', else = 0 */ c = 65; /* numeric representation of A*/ For numeric values consult ASCII table (e.g. available at http://www.asciitable.com/)
Special Characters Some of the special characters are: \n new line \b backspace \t move to next tab position \’ ’ \” ” \\ \ \xhexadecimal_digit character with code=hexadecimal digit. E.g. \xa – character with code 0xA Consult references (MSDN, ASCII table, etc.) for more special characters.
Character I/O • Standard library functions: char c; c = getchar (); /* get character from standard input */ putchar (c); /* output character c to standard output*/ • Note: stdio.h should be included to use these functions.
Character I/O - Example • Copy input to output: #include <stdio.h> /* copy input to output */ main() { int c; while ((c = getchar()) != EOF) putchar(c); } • NOTE: EOF – special (character) constant – character with this value indicates end of input stream. • Try to write a program to determine numeric value of EOF.
Character I/O – Another Example Word Counting Program Algorithm: state = OUT of word; number of words = 0; read next character while the character is not EOF If character is whitespace state = OUT If character is not whitespace AND state=OUT state = IN increment number of words read next character
Word Counting Program #include <stdio.h> #define IN 0 #define OUT 1 main() { int c, nw, state; state = OUT; nw = 0; while ((c = getchar()) != EOF) { if (c == ' ' || c == '\n' || c == '\t') state = OUT; else if (state == OUT) {state = IN; ++nw; } } printf("there were %d words in the input\n", nw); }
Relational and Logical Operations • Relational expressions: a<b, a>b, a<=b, a>=b, a==b, a!=b Equal 1 if condition is true, 0 otherwise. Have type int. • Logic expressions: !a NOT a a || b a OR b a && b a AND b
Arrays • Syntax: type name[size]; for instance int a[10]; /*declare array of 10 integers*/ • Array elements are: a[0], a[1], … a[9] • a[10] is NOT an element of this array! But compiler does not check this, thus following will compile but crash at run time: int a[10]; a[10] = 1; /* overwrites memory past the end of the array*/
Arrays • Initialization: int a[10] = {1,2,3,4,5,6,7,8,9}; • Multi-dimensional arrays: /*2 rows 3 columns*/ int a[2][3] = {{1,1,1},{2,2,2}}; • More on multi-dimensional arrays later in the course
Arrays in Memory • For array defined as int a[3] relative address of its 2nd element (a[1]) is sizeof(int)*1. When array element is accessed, compiler computes its address: Address = base address + index * sizeof (type) Relative addresses 0 4 8 Array elements a[0] a[1] a[2]
Pointers - Introduction • Pointer – variable storing address of another variable • Definition: type *name; float f1; float *pf1; pf1 = &f1; /* now PF1 stores address of f1*/
Pointers – Introduction contd. • “Address of” operator: & &variable gives us the address of variable • “Value of” operator: * *pointer gives us the variable referenced by the pointer Example: float f1 = 1.0, f2 = 2.0; float *pf1 = &f1; /* now pf1 holds address of f1*/ f2 = *pf1; /* now f2 = 1.0 */
Pointers and Arrays • There’s important relation between pointers and arrays. By defining int a[10]; • A is automatically set to type int* (pointer to int), and has the value of &a[0] (address of first array element) • Thus int *pa = a; is valid expression
Pointers • Pointes are numbers (addresses), thus certain arithmetic operations are allowed on them. Most common is increment/decrement: int a[10]; int *pa=a; /* now pa points to a[0] */ int *pb= a+1; /* now pb points to a[1] */ *(pb+2)=3; /* now a[3] = 3;*/
Example - Pointers Task: swap two arrays int a1[10], a2[10]; int *pa1 = &a1, pa2 = &a2, *temp; /* now we can use pa1 instead of a1: pa1[2] = a1[2], *(pa1+3)=a1[3], etc. */ /* to swap arrays, just swap references*/ temp = pa1; pa1=pa2; pa2=temp; /* now pa1 references to a2 elements */ /* and pa2 references to a1 elements */
Pointers to Pointers • Since pointer is a variable, it’s stored somewhere and its address may be taken. • Syntax: int **ptr_to_ptr; int *ptr; int i = 1; ptr_to_ptr = &ptr; /* now ptr_to_ptr stores ptr address */ ptr = &i; /* now ptr stores i address */ *ptr_to_ptr = &i; /* assign ptr to address of i */ *(*ptr_to_ptr) = 2; /* assign 2 to i */ • More on pointers later – this is just an introduction.
Passing function arguments – by value vs. by reference • For each argument a copy is made, which is destroyed after function returns control. • If it is needed that function modifies the variable, pass pointer to that variable!
Passing function arguments – by value vs. by reference void test(int in_parameter, int *in_out_parameter) { in_parameter = 1; /* local copy is modified*/ *in_out_parameter = 1; /* variable is modified*/ } main() { int i1 = 0, i2 = 0; /* i1 passed by value, i2 - by reference*/ test (i1,&i2); /* i1 is unchanged, i2 is modified*/ }
Strings • Constant string is defined as: char just_a_string[6]="abcde"; char just_a_string[]="abcde"; • I.e. string is array of characters • Constant strings are terminated with ‘\0’ character - just_a_string has length 6 – 5 characters + ‘\0’ terminator. • Only character arrays can be initialized this way. • Functions for manipulation with strings are defined in <strings.h> • More on strings – later in the course.
Arguments to main • main function has an interface to the “outer world” – calling program. It is pre-defined –main can receive pre-defined arguments: main (int argc, char ** argv) {…} • argc – number of string arguments • argv – array of strings (arguments). Argv[0] is always a program name. • When program is executed: TEST.EXE arg1 arg2 argc = 3 argv[0] = “TEXT.EXE” argv[1] = “arg1” argv[2] = “arg2”
Arguments to main - example #include <stdio.h> /* program prints passed to the program. in MSVC IDE program arguments can be set from project menu-settings item-debug tab-program arguments value */ main (int argc, char **argv) { while (argc--) {printf ("%s\n", *(argv++));} }