EXAM REVIEW: -What is a function prototype? Provide an example. It tells the compiler that a particular function exists, along with its return type and parameters. int exampleFunction( char parameter ); -What is a function definition? It is the full implementation of a function, including all the information in the function prototype along with the function body. -Write a function definition that takes a character as a parameter and returns 1 if the character is a vowel. If it's not a vowel, return 0. (Note: a vowel is either 'a', 'e', 'i', 'o', or 'u'). Name the function `isVowel`. int isVowel( char c ) { switch ( c ) { case 'a': case 'e': case 'i': case 'o': case 'u': return 1; default: return 0; } } -Write a function definition that will read in a character from the terminal, and print out "vowel" if it read in a vowel. The function doesn't return anything. If it's not a vowel, don't print anything. You must call the previously defined `isVowel` function. Name the function `readAndPrintVowel`. void readAndPrintVowel() { if ( isVowel( getchar() ) ) { printf( "vowel" ); } } -What is needed in the following code to make it compile without warnings or errors? Fix the code with respect to this. // void bar(); needed here void foo() { printf( "foo" ); bar(); } void bar() { printf( "bar" ); } // Needs a function prototype -What is the value of x, y, and z after this code executes? int x = 0; int y = 0; int z = 0; while ( y <= x ) { x++; z = y; y = x; x = z; } // x = 0; y = 1; z = 0; -What is the value of x after this code executes? int x; for ( x = 0; x < 50; x++ ) { printf( "%i\n", x ); } -What is the value of x after this code executes? int x; for ( x = 0; x < 50; x++ ) { printf( "%i\n", x ); x++; } -What is the value of x after this code executes? int x = 0; do { x++; } while ( x == 5 ); For the following questions, assume that integers never overflow and are of infinite size. -Is this a finite or an infinite loop? What is the output (if any)? (If the output is infinite, just put the output of the first three iterations). int x; for ( x = 0; x < 4; x++ ) { printf( "%i ", x ); } // finite // 0 1 2 3 -Is this a finite or an infinite loop? What is the output (if any)? (If the output is infinite, just put the output of the first three iterations). int x; for ( x = 4; x > 1; x-- ) { printf( "%i ", x ); } // finite // 4 3 2 -Is this a finite or an infinite loop? What is the output (if any)? (If the output is infinite, just put the output of the first three iterations). int x; for ( x = 0; x <= 0; x-- ) { printf( "%i ", x ); } // infinite // 0 -1 -2 -Is this a finite or an infinite loop? What is the output (if any)? (If the output is infinite, just put the output of the first three iterations). int x; for ( x = 0; x < 0; x-- ) { printf( "%i ", x ); } // finite // -Declare an array of 50 integers named `arr`. int arr[ 50 ]; -In one statement, declare an array named arr2 that holds 50 integers and whos first three elements are 1, 2, and 3, respectively. int arr2[ 50 ] = { 1, 2, 3 }; -Consider the following code: int arr3[] = { 1, 2, 3, 4 }; What is the value of each of the following expressions with respect to this code? Note the values may be undefined. arr3[ 0 ] // 1 arr3[ 3 ] // 4 arr3[ 4 ] // undefined arr3[ -1 ] // undefined -Consider the following code: int arr4[] = { 1, 2, 3, 4 }; int* p = &(arr4[ 1 ]); What are the values of the following expressions with respect to this code? Note the values may be undefined. p[ 0 ] // 2 p[ -1 ] // 1 p[ -2 ] // undefined p[ 2 ] // 4 p[ 3 ] // undefined -Write a function definition named `isum` that will sum elements in a given array of integers. The function also takes the length of the array as a second parameter. It should return the sum. It should NOT change the array. int isum( int* array, int n ) { int x; int retval = 0; for( x = 0; x < n; x++ ) { retval = retval + array[ x ]; } return retval; } -Consider the following code: #define LENGTH /* some positive integer */ int isPrime( int x ); int[] arr = { /* some positive integers. The number of positive integers == LENGTH */ }; Assume that the isPrime function is defined elsewhere. Write a function called `firstPrime` that will return the first prime number in the given array. Return -1 if no prime numbers were found. int firstPrime() { int x; for( x = 0; x < LENGTH; x++ ) { if ( isPrime( arr[ x ] ) ) { return arr[ x ]; } } return -1; } -Consider the following code: #define LENGTH /* some positive integer */ int[] arr2 = { /* some positive integers. The number of positive integers == LENGTH */ }; Write some code that will add 3 to each element of arr2. For example, for the following declaration and initialization of LENGTH and arr2: #define LENGTH 4 int[] arr2 = { 1, 2, 3, 4 }; …arr2's contents should be { 4, 5, 6, 7 } after your code runs. int x; for( x = 0; x < LENGTH; x++ ) { arr2[ x ] = arr2[ x ] + 3; } -What is wrong with the following code? // filename is the name of a file that is guaranteed to be able to be opened. void doSomething( char* filename ) { FILE* file = fopen( filename, "r" ); int input; if ( fscanf( file, "%i", &input ) == 1 ) { fclose( file ); printf( "%i\n", input ); } } // it's possible for the file not to be closed, namely when it doesn't start with an integer -Write some code that will attempt to open a file named "moo.txt", and try to read the first character from it. Make sure to close the file when you're done. -If we could open the file and read in a character, print out the character. Note the placeholder for printf and scanf for characters is %c. -If we could open the file but we couldn't read in a character, print "failed to read". -If we could not open the file, print "failed to open" FILE* file = fopen( "moo.txt", "r" ); if ( file == NULL ) { printf( "failed to open" ); } else { char c; if ( fscanf( file, "%c", &c ) == 1 ) { printf( "%c", c ); } else { printf( "failed to read" ); } fclose( file ); } -Write some code that will list the integers 0 through 100 (inclusive) in a file named "numbers.txt". Separate the integers by newlines. Assume that you can open the file for writing. FILE* file = fopen( "numbers.txt", "w" ); int x; for( x = 0; x <= 100; x++ ) { fprintf( file, "%i\n", x ); } fclose( file ); -Consider the following struct: struct Foo { int x; int y; }; After the following code runs, what are the values of the variables a and b? int a, b; struct Foo foo; foo.x = 10; b = foo.x; foo.x = 20; foo.y = foo.x; a = foo.y; // a = 20, b = 10 -Consider the following struct: struct Foo { int x; int y; }; As the following code runs (starting at main), what are the values of the variables a and b at the point specified? void doSomething( struct Foo foo ) { foo.x = 10; foo.y = 20; } int main() { int a, b; struct Foo foo; foo.x = 2; foo.y = 3; doSomething( foo ); a = foo.x; b = foo.y; // What are a and b at this point? return 0; } // a = 2, b = 3 // doSomething is working with a copy of foo -Consider the following struct: struct Foo { int x; int y; }; As the following code runs (starting at main), what are the values of the variables a and b at the point specified? void doSomething( struct Foo* foo ) { foo->x = 10; foo->y = 20; } int main() { int a, b; struct Foo foo; foo.x = 2; foo.y = 3; doSomething( &foo ); a = foo.x; b = foo.y; // What are a and b at this point? return 0; } // a = 10, b = 20 // doSomething is working directly with foo through a pointer -Consider the following struct definitions and variable declarations: struct Foo { int i1; int i2; }; struct Bar { int* ip; double d; struct Foo* foop; }; int i; int* ip; double d; double* dp; char c; char* cp; struct Foo foo; struct Foo* foop; struct Bar bar; struct Bar* barp; int[] arr = { 1, 2, 3 }; // initialization code is implicitly here Assume that each of these variables were initialized to valid values. For each of the following expressions, specify its type with respect to these definitions. Specify "error" if the expression is invalid. i // int ip // int* *i // error *ip // int &i // int* d // double dp //double* *d // error *dp // double &d // double* c // char cp // char* *c // error *cp // char &c // char* foo // struct Foo foop // struct Foo* foo.i1 // int foo.i2 // int foo.i3 // error foo.ip // error foo->i1 // error foo->i2 // error foop->i1 // int foop->i2 // int foop->ip // error foop.i1 // error foop.i2 // error bar // struct Bar barp // struct Bar* bar.ip // int* &(bar.ip) // int** *(bar.ip) // int barp->ip // int* barp->foo // struct Foo* bar.foo // struct Foo* &(barp->foo) // struct Foo** barp->foop->i1 // int barp->foop.i1 // error barp->i1 // error *barp // struct Bar (*barp).i1 // int (*barp)->i1 // error (&bar)->ip // int* arr // int[] arr[ 0 ] // int &(arr[ 0 ]) // int* -What is printed by the following code? int x = 1; if ( x == 1 ) { int x = 2; printf( "%i\n", x ); } printf( "%i\n", x ); // 2 // 1 -What is wrong with the following code? int x = 2; if ( x > 0 ) { int y = 7; } x = y; // y is neither in scope nor alive in x = y; -What does the following code print (starting execution at main)? void foo( int x ) { printf( "%i\n", x ); } void bar( int x ) { x = x + 2; printf( "%i\n", x ); } void baz( int x ) { if ( 1 ) { int x = 2; } printf( "%i\n", x ); } int main() { int x = 3; printf( "%i\n", x ); foo( x ); printf( "%i\n", x ); bar( x ); printf( "%i\n", x ); baz( x ); printf( "%i\n", x ); return 0; } // 3 // 3 // 3 // 5 // 3 // 3 // 3 -Does testing your code prove it works in general? // No. Testing can find bugs but it's not for showing there are no bugs. -If you're given all the code to test, what kind of testing is this called? // white box testing, as opposed to black box testing