C - Assignment 1 This assignment will help you get a handle on basic C programming and compiling. We are going to convert much of the code you wrote in Fortran to C, organizing it as we would a regular C program. You will work out of your C directory for this assignment. When you are finished the assignment, you should have the following files in your C directory: findpower.c getturbinespecs.c getsounding.c globals.c myFunctions.h myProgram.c saveresults.c welcome.c HAND IN: findpower.c, getturbinespecs.c getsounding.c, globals.c, myFunctions.h, myProgram.c, saveresults.c, welcome.c These files will be collected for marking on 11:59pm March 19, 2012. Make sure your final copies are in your C directory! ============================================================================= PART 1: myFunctions.h First we are going to create a header file so that we can build functions in other source files and still include them in our main program easily. 1. Open myFunctions.h with your favorite editor (vi). 2. Add comments to the top with your name and student number. 3. Add #ifndef, #define, and #endif statements so that the header file will only be loaded once. You can use whatever defined name you wish, but it is customary to make the variable name be similar to the filename (ie MYFUNCTIONS_H) 4. Leave some blank space between the #define and #endif statements. This is where you will add your function prototypes. ============================================================================= PART 2: myProgram.c This part will focus on setting up the main program framework and getting a successful compilation with the object files. 1. Open a new file called myProgram.c with your favorite editor (vi). 2. Add comment lines identifying the file, purpose of the code, and the author (don't forget your name and student number). 3. This code will be your main program. As such, you will need to include some headers. Add include statements for stdio.h, stdlib.h, string.h, and the local header myFunctions.h. 4. Now add the 'main' function. Be sure to include the proper parameters and the starting and ending brackets. Add a 'return 0;' statement to the body of your main function. 5. At this point, you can compile your code even though it does not yet do anything. Save myProgram.c. Compile myProgram.c into an object file (use the -I option to tell the compiler where to find the myFunctions.h file). gcc -I./ -c myProgram.c The -I./ option tells the compiler to look for myFunctions.h in your current directory ('./' which is where you are compiling) so make sure you are in your C directory. If you move myFunctions.h somewhere else, or attempt to compile from another location, change the directory after -I to the location of myFunctions.h and put the full path to your source files (ie gcc -I/home/EOS004/src -c /home/EOS004/C/myProgram.c) Now you can link the object file into an executable. gcc myProgram.o -o myProgram.exe If all went correctly, you should have an executable (which does nothing) called myProgram.exe. This approach to compiling will be the one you use throughout this and next week's C assignments. If you ran into problems, it is most likely syntactical errors in myProgram.c. Review the file and correct any problems. 6. Delete the myProgram.o and myProgram.exe files. ============================================================================= PART 3: welcome.c The first thing we will do is convert the welcome function. To do this, we will need to add the function to the header file, then create the function code in its own source file. 1. Open myFunctions.h in your favorite editor. 2. Between the #define and #endif statements, add a definition for the function 'welcome'. The function should have a return type of 'void' (ie nothing) and should take no parameters. Don't forget to include a brief description of the function. Save myFunctions.h. 3. Open a new file welcome.c in your favorite editor. 4. Add comment lines to indicate the file name, purpose, and author (don't forget your student number). 5. Add the framework for your welcome function. Don't forget the starting and ending brackets. 6. To print to the screen, you will need to use the printf function from stdio.h (make sure you have an include statement above your welcome function). Print the message just as you did in your fortran subroutine. 7. Save welcome.c 8. Now you should test to see that welcome.c compiles into an object file properly. 9. Open myProgram.c. Add a call to your new welcome function before the return statement. Now compile myProgram.c into an object file (don't forget to use -I with myProgram.c to tell it where myFunctions.h is). Now, you should be able to link all the object files into an executable which will print your welcome message to the screen and quit. correct any errors you encounter before moving to the next section. 10. Clean up myProgram.o and the executable. Leave welcome.o, you'll need it in the coming sections and it will save you re-compiling it. ============================================================================= PART 4: getturbinespecs.c and globals.c In this next section, you are going to convert the getturbinespecs function over to C. You will also need to handle the variables in the turbine module. 1. Open myFunctions.h in your favorite editor. 2. Between the #define and #endif statements and after the definition for welcome, add a definition for the function 'getturbinespecs'. The function should return a type of void and take no parameters. Don't forget to include a brief description of the function. In the fortran version, you had a module which had variables for storing the hub height and radius. C does not work the same way. To get global or shared variables, we are going to need to add them to the header file. Add variables for hub height and radius and make sure to make them 'extern'. Save myFunctions.h. 3. Open a new file globals.c in your favorite editor. We are going to add all these shared variables from the modules to this file. Remember that a header file does not get compiled, so putting the variables in that file will not make them part of the program. We still need to make a source file containing declarations for these variables. Add any variables you put into the header file to this file, exactly as they appeared in the header file but without the 'extern' tag. Save and close globals.c. 4. Open a new file getturbinespecs.c in your favorite editor. 5. Add comment lines to indicate the file name, purpose, and author (don't forget your student number). 6. Add the framework for the getturbinespecs function. Don't forget the starting and ending brackets and include statements for myFunctions.h and any other headers you need (stdio.h?). Your function should have a return type of void and take no parameters. 7. Now you want to perform the same actions you did in fortran, namely print to the screen to prompt the user to enter values; printf should do that nicely. You will also need to read the values the user enters. For this, you will probably find it easiest to use fgets. Do not forget, stdin represents the stream of data from the keyboard. Make sure you perform the same data checks you did in the original fortran and store the data in the global variables you declared in the header file. fgets will retrieve a string but you need the numbers to be floats. atof(string) will convert a string to a float. You need to include stdlib.h to use it. 8. Save getturbinespecs.c 9. Now you should test to see that getturbinespecs.c compiles into an object file properly (don't forget to use -I to tell it where myFunctions.h is). You should also compile globals.c into an object file. 10. Open myProgram.c and add a function call to getturbinespecs just after the welcome function call. Re-compile myProgram.c into an object file just as you did previously. Now, you should be able to link all the object files into an executable which will give you a welcome message and prompt you for turbine specifications. If you get any errors, correct them. 11. Clean up globals.o, myProgram.o and the executable. Leave the other object files, you'll need them in the coming sections and it will save you re-compiling. ============================================================================= PART 5: getsounding.c and globals.c In this part, you are going to convert the subroutine getsounding to C. Just as with the getturbinespecs subroutine, you will also need to handle variables from a module as you did in the previous section. You can use the same sounding files you used in the previous fortran section. To make it simpler, you could copy them temporarily to your C directory. 1. Open myFunctions.h in your favorite editor. 2. Between the #define and #endif statements and after the definition for getturbinespecs, add a definition for the function 'getsounding'. The function should return a type of void and take no parameters. Don't forget to include a brief description of the function. In the fortran version, you had a module which had variables for storing the filename, title, maximum number of sounding lines, height above sea level, and wind speed. Again, you will need to make global variables in the header file and ensure they are 'extern'. Do not initialize any of the variables in the header file (some of them are initialized in the module). Uninitialized arrays can be declared like this: extern int example_array[]; Save myFunctions.h. Open globals.c and add the variables to the source file. Any variables that need to be initialized can be declared and initialized here. There is one exception, maxlines. You cannot use maxlines as a variable entry to the size of arrays if it is itself a variable. To get around this, instead of making maxlines a normal variable, we define it within myFunctions.h like so: #define maxlines 120 The is called a preprocessor directive and creates a static name maxlines with a value of 120. We do not need to declare it in globals.c, but we can use it as if it were a variable. Save globals.c. 3. With your favourite editor, open getsounding.c. 4. Add comment lines to indicate the file name, purpose, and author (don't forget your student number). 5. Add the framework for the getsounding function. Don't forget the starting and ending brackets and an include statement for myFunctions.h. Your function should have a return type of void and take no parameters. 6. Now you need to perform the same actions as the getsounding subroutine. Again, you will find printf and fgets useful for handling user interaction. There may be one wrinkle, you will need to remove the newline character from the end of your filename before you use it to open the file (fgets will include it). If you include string.h you can perform a simple operation to replace the newline character with an terminating character like this filename[strlen(filename)-1] = '\0'; You will need fopen to open the file and fclose to close it down (which means you will need a filehandle and you will need to include stdio.h). To recreate the error check for when the file does not open properly, you can check to see if your filehandle variable is NULL. If it is, quit the function (return;). You can cycle through the file with fgets (this might be easiest), and rewind the file with the rewind(filehandle) command (the parameter is whatever variable you set to be your filehandle). Reading text from a file in C is not quite as simple as fortran. You will need to parse each line either for specific characters, or specific fields. After you get a string with the height or wind speed (don't forget to convert to m/s too), you will first need to change the value from a string to a float using atof(string) (don't forget to include stdlib.h). If you plan to parse lines by field, you will find strtok to be a useful function. If you know exactly where the data will be in each line, you can use sprintf to write the characters to new strings. Either approach is fine, although the sprintf approach requires less code. 7. Save getsounding.c 8. Open myProgram.c and add a call to getsounding after your call to getturbinespecs. Save myProgram.c. 9. Now you will need to compile globals.c, getsounding.c and myProgram.c into object files, then link all the object files into an executable as you have been doing in the other sections. Don't forget to include all object files when compiling the executable. The executable should do all the things it was previously as well as taking a filename for a sounding file and reading that data into memory (as well as echoing it to the screen). 10. Clean up globals.o, myProgram.o and the executable. Leave the other object files, you'll need them in the coming sections and it will save you re-compiling. ============================================================================= PART 6: findpower.c and globals.c In this part, you will convert your findpower subroutine to a C function. As with the previous two sections, you are going to have to account for the variables in the power module when designing this function. 1. Open myFunctions.h in your favorite editor. 2. Between the #define and #endif statements and after the definition for getsounding, add a definition for the function 'findpower'. The function should return a type of void and take no parameters. Don't forget to include a brief description of the function. In the fortran version, you had a module which had variables for storing power output variables and total power. Again, you will need to make global variables in the header file and ensure they are 'extern'. Save myFunctions.h. Open up globals.c and add those variables. Save globals.c. 3. With your favourite editor, open findpower.c. 4. Add comment lines to indicate the file name, purpose, and author (don't forget your student number). 5. Add the framework for the findpower function. Don't forget the starting and ending brackets and include statements for myFunctions.h and any other header files you might need (like stdio.h, math.h?) Your function should have a return type of void and take no parameters. 6. Now you will convert the function to C. Compared to the other functions, this one is reasonably straightforward. You will need to print to the screen and do a series of calculations (which will store values to the variables you added to myFunctions.h). For the calculations, you may need functions from the math library (like sqrt(number)). If so, make sure you include math.h. The only new elements to this function is looping and helper functions. A for loop will most closely resemble the do loop of fortran although you can do it with a while loop if you prefer. The helper functions M() and density() will need to be added to your code, but since they are only used by findpower, you can put the definitions for them ahead of your findpower function in your findpower.c file. 7. Save findpower.c 8. Open myProgram.c and add a call to findpower after your call to getsounding. Save myProgram.c. 9. Now you will need to compile globals.c, findpower.c and myProgram.c into object files, then link all the object files into an executable as you have been doing in the other sections. Don't forget to include all object files when compiling the executable and use -lm if you included the math library (math.h). The executable should do all the things it was previously as well as making the new power calculations and echoing the results to screen. 10. Clean up myProgram.o and the executable. Leave the other object files, you'll need them in the last section and it will save you re-compiling. ============================================================================= PART 7: saveresults.c This is the last part of converting your fortran program, and once complete, you will have a fully functional program that works just like your fortran program did. In this section, you will create the saveresults function which will output the results to a file. 1. Open myFunctions.h in your favorite editor. 2. Between the #define and #endif statements and after the definition for findpower, add a definition for the function 'saveresults'. The function should return a type of void and take no parameters. Don't forget to include a brief description of the function. You have already declared the global variables from the modules saveresults uses in the header file, so there is no more you need to do. Save myFunctions.h. 3. With your favourite editor, open saveresults.c. 4. Add comment lines to indicate the file name, purpose, and author (don't forget your student number). 5. Add the framework for the saveresults function. Don't forget the starting and ending brackets and include statements for myFunctions.h and stdio.h. Your function should have a return type of void and take no parameters. 6. Most of the work is writing to a file which you can do using fprintf. You will find fopen and fclose very helpful for handling the output file. Do not forget that you need to open the file in write or append mode to write to it. The trickiest part of converting this function is generating the output filename. You can use strtok with the delimiter set to '.' to parse out the beginning of the filename, or to be more robust (in case there are multiple '.'s in the filename) you can use strlen and strncpy. In either case, you will likely need sprintf and a string buffer at least as big as your filename variable to create the complete output filename. 7. Save saveresults.c 8. Open myProgram.c and add a call to saveresults after your call to findpower. Save myProgram.c. 9. Now you will need to compile both saveresults.c and myProgram.c into object files, then link all the object files into an executable as you have been doing in the other sections. Don't forget to include all object files and -lm (if you used the math library math.h) when compiling the executable. The executable should do all the things that your complete fortran program did. Run the same cases you ran in fortran and compare. Ensure that the output files are the same. 10. Clean up all of your object files and the executable. ============================================================================= PART 8: MAKE SURE YOUR FINISHED FILES ARE IN YOUR C DIRECTORY! 1. Remove any executable or object files from your C directory. 2. Ensure that findpower.c, getturbinespecs.c getsounding.c, globals.c, myFunctions.h, myProgram.c, saveresults.c, and welcome.c are complete and in your C directory. DEADLINE: 11:59pm March 19, 2012