Before this is due, we will have expanded your abilities so that you can make extensive use of functions in your code. Pick one of the two options below to complete. We are now getting to the point where you don't want to just start coding. You want to start by sitting down and thinking about what your code needs to do and how you are going to make it do it, paper and pen might even be helpful for this. I can almost promise that every minute spent really thinking about what you are going to be doing will save you 2 minutes of coding/recoding/debugging.
After each problem description I've given you sample input and output files. If you run the program with the input I give you should get something pretty much identical to my output.
As a side note, be sure to save the code from all the programs you do. It is quite possible that later in the semester other assignments will include things that overlap with them and your code will be reusable.
To turn in this assignment just send the code in an e-mail to mlewis@cs.trinity.edu. You can do this with the command "mail mlewis@cs.trinity.edu < assn4.c" if assn4.c is the name of your source file.
Standard Problem:
If you choose this option, you will write a little program that does encryption and decryption of a message that you type in. You will also write the code to decrypt that same message. By using redirection of I/O you will be able to easily test to see if it works. Your program will not only have a main, but at least three other functions called encrypt, decrypt, and readTo10.
The encryption your program does will be a 2 part encryption. First, it will offset the characters in the ascii set by a given amount. Then to make things harder, it will throw in a random character after every nth character in the message. So the input of your program will be an e or d followed by two numbers, offset and spacing. Offset is what you will add to all the character values and should be between 1 one 10. Spacing is how far it is between the randomly inserted characters. After that, on a new line, will be the message itself. If the first letter was an e you should do encryption, otherwise do decryption.
Both the encrypt and decrypt functions will have a return type of char. You probably need to pass in the offset and spacing values. Depending on how you design your code, other values might need to be passed in as well.
The encrypt function will first check to see if it is time to insert a random character. If it is it will return a random character generated using the rand function. You can just put return rand()%26+'a'; into the code at that point. The rand function is part of stdlib.h and you can use "man 3 rand" to get more information on it. If it isn't time to insert a new character, you should read one character from standard input, scanf("%c",&oneChar), then return the character that is "offset" positions above it in the ascii table, oneChar+offset.
The decrypt function does something very similar to the encrypt function. If it is at a position where a random character would have been inserted, it reads in one character and ignores it. Whether or not is has reached "spacing" yet, it will read in a character and then return the character that is "offset" below that character in the ascii table.
The readTo10 function is just reads in characters until it gets to one with an integer value of 10 which is a newline. You need this to make sure that you read all the way to the end of the first line before the messages.
Back in main, after you read in the 'e' or 'd', the two integers, print them out, and call readTo10, you will want to go through a loop as long as there is more to be read. If you are using file redirection you can do this by looking at the return value from scanf. We haven't looked at this previously, but if you do a "man scanf", you will find that its return type is not void. Instead, it returns how many things it read in. If you try to read a character and this value is less than one then there was nothing left to read. I will leave it to you to decide how to turn this return value into something that will tell the loop in your main to stop. If you just type in your output instead of using I/O redirection, you will have to use ctrl-C to stop when you have put in everything you want.
To see what the program wants to read in and will print out look at the files below at examples that I did. Your encrypted version doesn't have to match mine perfectly, there is randomness after all, but when you decrypt your encrypted one it needs to be identical to the input you use.
orginal file : encrypted file : decrypted file
Graphics Problem:
By breaking a problem up into pieces things that might seem a bit intractable can become tractable. For this assignment you will start writing some routines that you could use to build a graphics library for doing 3D graphics or ray tracing. In particular, you will begin writing routines that could be used to find how brightly a particular surface should be lit given some information about the surface and the location of a light source.
The idea here is that we have a simple flat surface that is being lit by a single light source. You will be given the location of the light source as well as the location of three points on the surface (if it were a triangle, they would be the corners). For now we will do a simple form of lighting where you assume that the entire surface is lit uniformly. This is sufficient for basic 3D graphics but can easily be improved upon in many ways and will be if you do ray tracing. We will also assume that we are dealing with a matte surface so all light is reflected in a diffuse manner.
How bright a surface will appear depends on two things: distance from the light source, and the angle of the surface relative to the light source. You will write four distinct functions to help you compete these values. The easy one is distance. I will want you to use the distance from the first of the three points that you read in and create a function that returns a double that is the distance between the two points passed in. They will be passed in as six doubles for two sets of x, y, and z. The intensity goes as 1/(r*r), where r is the distance from the light to the point on the surface you are using.
To get the angle you need to know a vector from the light to the surface, as well as a vector for the direction normal to the surface (normal vectors are perpendicular to all lines in the plane of the surface). Then you want to know the cosine of the angle between the vectors. That sounds like a very difficult thing to find, but there are some simple math functions that can help us to get what we want. Getting the vector from the light to the surface is quite easy, just subtract the components of one from the other so that is easy. Getting the vector normal to the surface is a bit harder, but not that much. As it turns out, there is something in math called a cross product that operates on vectors. The cross product of two vectors is a vector that is perpendicular to both. So how do we get those two vectors? Well, they can be any combination of vectors between the three points you read in so maybe <x1-x2,y1-y2,z1-z2> and <x1-x3,y1-y3,z1-z3>. Then the question becomes, what is the cross product (also called the vector product). It is defined as the determinant of a matrix with the unit vectors in the top row, the first vector of the product in the second and the second vector in the third. So for the product a x b=<ay*bz-by*az, az*bx-bz*ax, ax*by-bx*ay>.
So now you have two vectors you need to find the cosine of the angle between them. As it turns out, there is another type of product between vectors called the dot product that does this. Actually, a.b=|a||b|cos(t)=ax*bx+ay*by+az*bz, where the |a| and |b| are the lengths of the two vectors. We just need the cosine, so we need to make the vector lengths equal to one and then that nice expression at the end gives us what we want. First you will write a function called normalize that takes the three components of a vector and divides them all by the length of the vector so you get a vector of length unity. Then you need a function that will take the dot product of two vectors.
So the functions you need to write are as follows: distance, normalize, dotProduct, and crossProduct. Some of these need to return multiple things so pass by reference might be handy. Your main will basically read in the x, y, and z position for the light followed by x, y, and z for each of the three points. It will then call the functions you have written and output the cosine of the angle divided by the distance squared which is the relative intensity of the lighting. If you ever get a "negative intensity", just flip the sign when you print it out.