C - Assignment 2 This assignment will help you get a handle on pointers and cross-compiling with fortran code. You should find the following files in your C directory: findpower.c getturbinespecs.c getsounding.c globals.c myFunctions.h myProgram.c saveresults.c testf95.o welcome.c When you are finished the assignment, you should have the following files in your C directory: binary.c findpower.c getturbinespecs.c getsounding.c globals.c myFunctions.h myProgram.c myProgram2.c powerarray.c saveresults.c testf95.o welcome.c HAND IN: binary.c, myFunctions.h, myProgram2.c, powerarray.c These files will be collected for marking on 11:59pm March 26, 2012. Make sure your final copies are in your C directory! ============================================================================= PART 1: myFunctions.h The focus of this assignment will be to write a couple of new functions and a new main program that utilizes them. These functions will take advantage of pointers and be capable of being cross-compiled with fortran code. To utilize the functions within our new C program, you will first need to add them to myFunctions.h. 1. Open myFunctions.h with your favorite editor. 2. After the existing definitions, create a new function prototype for binary. Because we want this new function to be useable by fortran calling code, you will need to add an underscore to the end of the function name. Make the binary function return a long, but take as its parameter an integer pointer (int*). Make sure you comment the function. 3. After the binary function definition, add a defintion for the function powerarray. Again, you will need an underscore on the end to make it cross-compilable. This function should return void and take three integer pointers (x, y, and array) as parameters. 3. Save myFunctions.h. ============================================================================= PART 2: myProgram2.c Your new main program will be setup in this file. Basically, the program will print a menu of options for the user, wait for a selection, then make an appropriate call to binary or powerarray and print the output. Afterwards, it will echo the menu again and wait for more input. 1. Create and open myProgram2.c with your favorite editor. 2. Add comment lines with the file name, description, and author (don't forget your student number). 3. Add the main function declaration and brackets. Do not forget include statements for stdlib.h, stdio.h, and myFunctions.h. Declare any variables you think you might need. 4. Now you will need to create an endless loop. The easiest way to do this is with the statement 'while (1)'. Remember that if you find your program cannot be quit during testing, you can use ctrl-C to kill it. The endless loop will allow you to setup a simple algorithm that will just keep executing until you tell it to quit. The remainder of the main function will be contained within this loop. 5. Print out a menu. It should look like this: Hello, welcome to the C test program! Choose a function to test: 1) binary 2) powerarray enter anything else to quit Choice: printf will be helpful for printing out the menu. fgets with stdin is an easy way to get what the user inputs (you will need a character buffer to hold the input). 6. Once you have the input, you need to execute appropriately. A nested if statement can handle the different options. The strcmp function can be used to compare the input buffer to strings "1\n" and "2\n", each done separately. strcmp returns a number that signifies the location within the buffer string where the first detected difference occurs. Thus two strings that are identical will return 0. So one of your if statements would look like if (strcmp(line, "1\n") == 0) // The choice was 1, run binary If you get a '1', you want to execute binary. If you get a '2', you want to execute powerarray. If anything else is entered, you want your program to quit (return 0;). 7. In the nested if statement portion relating to binary, you need to print the following to the screen: Executing binary, please enter the number to convert: Then you will need to get the number entered by the user (and convert it from a string to integer). At this point you have not yet written binary, so you can simply set the result to 111. Then print to screen: converts to where is whatever the user supplied, and result is the preset 111 (later it will be the result you get from binary). You are now finished this section of the if statement. 8. In the nested if statement portion relating to powerarray, you need to print the following to screen: Executing powerarray, please enter x: y: You will need to retrieve both numbers. Create a predefined result array with the numbers [1 2 3 1 4 9 1 8 27] (later you will call powerarray and use the result). Print the array to screen like this: Resulting array is: [ 1 1 1] [ 2 4 8] [ 3 9 27] You will need to print the brackets. Each element of the array should be 10 spaces wide and there should be a single space between elements. You will likely need loops to print the array out properly and you will need to calculate out the index. For that, check out the discussion of how to handle the array index in Part 4. You are now finished this section of the if statement. 9. Finish the last portion of the if statement (quitting). Print the following to the screen: Thanks for using the testing program! then exit (return 0). 10. Save and close the file. 11. Compile into an object file. You can link the file by itself to create an executable. Do this and try it out to make sure it works properly (binary and powerarray will just print out the presets regardless of what you input). Make sure the program quits when you enter anyting else. If you program will not quit, remember you can use ctrl-C to force it to stop. Clean up your executable. ============================================================================= PART 3: binary.c Now you are going to write the a new function called binary. This function will take an integer pointer as a parameter and return a long which will be the binary representation of the parameter. 1. Create and open binary.c with your favorite editor. 2. Add comment lines with the file name, description, and author (don't forget your student number). 3. Add the function declaration and brackets (this should match the prototype you put in myFunctions.h). 4. Add the code to calculate the binary number in loop format (do not write a recursive version). The algorithm to convert a base 10 integer N into a binary number is: - take a base 10 number N - repeatedly divide N by 2 - if there is a remainder, store a 1 - if there is no remainder, store a 0 - when the only thing left is a remainder of 1, stop dividing - reverse the sequence of 1's and 0's For example, converting 13 to binary: 13 / 2 = 6 with a remainder of 1 6 / 2 = 3 with a remainder of 0 3 / 2 = 1 with a remainder of 1 1 / 2 = 0 with a remainder of 1 In order that forms 1011, reverse the order to get 1101 which is 13 in binary. Do not forget that you are working with pointers here, so make sure you dereference your parameter before you use it. You may want to use the modulus operator (%) to determine the remainder at each step. 5. Make sure you return the result. 6. Save and close the file. 7. Compiling the object file at this point to find compiler bugs in your code. ============================================================================= PART 4: powerarray.c In this part, you are going to create a function which returns an array of that is x by y where each element is x^y. The function will need to return an integer pointer and take two integer pointers x and y as parameters. Since we want to cross compile this function, you will need to add an underscore to the name. 1. Create and open powerarray.c with your favorite editor. 2. Add comment lines with the file name, description, and author (don't forget your student number). 3. Add the function declaration and brackets (this should match the prototype you put in myFunctions.h). If you plan to use any of the built in math functions, you should add an include statement for math.h. 4. You are going to assume that array is already allocated (we will handle this later in myProgram2.c) and that it is x by y in size. The biggest problem here is that fortran will flatten the array making it appear as a one dimensional array to the powerarray function. As a result, the parameter is only an integer pointer and the index for each spot within the array must be calculated. Furthermore, fortran is column major in its ordering while C is row major so we will need to account for that. In terms of your algorithm, you are still going to need to do a nested loop over x and y and use these indices to calculate where you are in the flattened array. Suppose you are given a fortran array that is x by y where x = 2 and y = 3. The array might look like this: [ 1 2 3] [ 4 5 6] In memory, fortran stores the array in column major format so it will appear flattened into a one dimensional array like this [ 1 4 2 5 3 6] which is how it will appear to C. So, if we are doing a calculation for the i,j th element, in C the index would be i j element C index 1 1 1 0 1 2 2 2 1 3 3 4 2 1 4 1 2 2 5 3 2 3 6 5 So we need to figure out a mathematical relation between the variables i and j (as we loop), the size limits x and y, and the C index. The solution is to recall that we are reading in column order. If we know what column we are in (j), then we know how many columns we have already passed completely (j - 1) and we know the size of each column (it is the number of rows, or x). So we are at least (j - 1) * x elements into the array. How far we are into the current column is given by i (the number of the row we are into the array). However, since C starts indexing at 0, we need to remove 1 from this value to accomodate. Thus our C index is given by (j - 1) * x + (i - 1) All we need to do now is set array at that index to be i^j and we are done (the pow function can be very helpful with that). 5. Save and close the file. 6. Compiling the object file at this point to find compiler bugs in your code. ============================================================================= PART 5: Cross Compiling You have now built the binary and powerarray functions. They have been designed to be cross-compiled with fortran code, so you are going to test them by cross compiling them against a fortran object file that has been provided for you (testf95.o). 1. You should find testf95.o in your C directory, but if you do not you can get a copy from the website. 2. Make sure you have object files for binary.c and powerarray.c. If not, compile object files for those source files. 3. Now you will cross-compile. To do this, you will use the fortran compiler to do the linking. It is as simple as compiling a regular executable with the fortran compiler. gfortran binary.o powerarray.o testf95.o -o test.exe If you used the math library, you will also need to add -lm. Normally there won't be any errors linking, but if you have problems, make certain that your functions conform to the requirement for linking with fortran (pointer parameters, underscore in the name) and that their declaration has the correct return type and parameters. Now run test.exe and try out a number of values to make sure the code is working properly. If you get odd values, go back and examine your code. Correct any errors, recompile and try again. Keep working on it until your tests complete correctly. 4. Remove test.exe but leave your object files. ============================================================================= PART 6: Return to myProgram2.c Now you are going to finish up your myProgram2.c file by making calls to the binary and powerarray functions as well as dynamically allocating memory for your array. 1. Open myProgram2.c with your favorite editor. 2. Go to the section where you would be making a call to binary. Right now, it should simply be printing out a preset result. Prior to that printout, add a call to binary. Do not forget to match the function declaration exactly (you will need to reference your parameter variable unless it is already a pointer). 3. Now go to the section where you will make a call to powerarray. If you have preset x and y, make sure to comment these out. You should be getting x and y from the user. The array will will need to be one dimensional and x * y in size. At the top, you can redefine your array variable to be a pointer, then in the section where you call powerarray you can use malloc to allocate it before the powerarray call. After you are done printing out the array, make sure to free it. 4. Save an close myProgram2.c. 5. You you are ready to compile. Make sure you have compiled binary.c and powerarray.c into object files. Compile myProgram2.c into an object file and then link all the object files together (do not forget -lm if you used the math library). Try running your executable and make sure that it handles menu selections and gives proper results for calls to binary and powerarray. 6. Clean up your executable and all your object files. ============================================================================= PART 7: MAKE SURE YOUR FINISHED FILES ARE IN YOUR C DIRECTORY! 1. Remove any executable or object files from your C directory. 2. Ensure that binary.c, myFunctions.h, myProgram2.c, and powerarray.c are in your C directory. DEADLINE: 11:59pm March 26, 2012