You are expected to complete this assignment individually. If you need help, you are invited to come to office hours and/or ask questions on piazza. Clarification questions about the assignments may be asked publicly. Once you have specific bugs related to your code, make the posts private.
This homework has several problems. We are also providing you with some resources on printf and error handling for this assignment.
You should submit four files for this assignment ( hw3.h, hw3.c, hw3_main.c, and Makefile) in your subversion repository as directed below.
For problems 2 and 3, you will be using ppm, a simple image format for storing pictures (ppm stands for "portable pixel map"). The ppm format exists independent of C programming; it is a simple plaintext image format that you can produce (or consume) with programs written in any language. It is not an efficient representation, but it has the great virtue of being human-readable, and so it is relatively easy to examine and debug.
Colors in programs are stored as rgb - red, green, and blue. In our ppm format, we will allow the values to range from no color (0) to full saturated (255). Any color can be created using these three numbers. As you would expected, red is (255,0,0), green is (0,255,0), and blue is (0,0,255). When combining colors, though, you need to remember that these are light palettes, not paint palettes. Therefore, white is the saturation of all colors of light (255,255,255), and black is the absence of light (0,0,0). To get the values for red, orange, yello, green, blue, and purple, you can look at this website.
A plain ppm image is a text file containing the following:
For example: the following is a 3x3 square image of the HTML color dodgerblue (which has RGB values 30, 144, 255) in plain ppm:
The first three triples are the three pixels in the first row (left to right), the second three pixels are the second row, the last three are the third row.P3 3 3 255 30 144 255 30 144 255 30 144 255 30 144 255 30 144 255 30 144 255 30 144 255 30 144 255 30 144 255
Assuming this text were saved in a file named dodgerblue.ppm, you could* (see below) view the file with the command-line program display, like so:
*However, at the time of this writing display is not properly configured on the CSIL Macs, so you won't be able to use it today; as such, please use Photoshop to view the PPMs. (Using Photoshop to view a PPM is sort of like taking a stretch limousine to the corner store, but it will suffice for the time being). We will work on getting display working in the meantime (it's a much lighter weight, open-source tool, and you can all install it on your own machines).$ display dodgerblue.ppm
The last problem requires user input. Because we have not covered user input in class, we will only get the simplest of input. Each time you want user input, you will ask a question. You will receive only integer responses and string responses. You will not get two responses in one line. Each query will have only one response. If you need two pieces of information, ask for them separately.
For example, if I want to ask the user how many students are in the class, this is the code to do so. Note the last step - calling atoi to take the string representation of the number and translating it into the integer.
/* make a spot to put what we read in */ char buffer[100]; /* ask the question */ printf("How many students are in the class? "); /* read in up to 100 characters (or to the \n, whichever comes first), place * those in the buffer, and read it from stdin, which is the keyboard */ fgets(buffer, 100, stdin); /* translate the first thing from a set of characters to the integer number */ int num_students = atoi(buffer);If we want to get a string result, the complicating factor is that fgets reads in the string and a '\n' before the '\0'. We need to get rid of the '\n'. In this code, we'll assume buffer was already declared and allocated - we can use the same buffer for all of the questions.
char *response; printf("What is your name? "); fgets(buffer,100,stdin); /* now call strdup to make a new string to hold it so we can reuse buffer*/ response = strdup(buffer); /* now get rid of the '\n' */ int length = strlen(response); // step 1: find out length response[length-1] = '\0'; // step 2: put '\0' there to end string one earlier
Because you are adding a second set of files to your directory, you need to add a second target to your Makefile. In your makefile, add another two lines (with a space between these and the ones already there).
hw3: hw3.h hw3.c hw3_main.c clang -Wall -o hw3 hw3.c hw3_main.c
Now you need to make the skeleton code so that your program will minimally execute. You must do this in case you do not complete your assignment. Our testing infrastructure needs to compile and execute even if you did not complete the entire assignment.
/* surface_area_cylinder * Calculates the surface area of a cylinder given height and radius * inputs: height, radius * output: double */ double surface_area_cylinder(double height, double radius);
double surface_area_cylinder(double height, double radius) { return 0.0; }
int main() { surface_area_cylinder(1.0, 5.0); // add the rest of the function calls here }
A digit, such as 7, can be written as an English word, such as "seven," and 79 as "seventy-nine." This word has a certain number of letters; in this case, five and twelve, respectively. Write a function, digit_string that takes in a single number,no more than one digit, represented as an unsigned int, and returns a C string representing that number. Remember that in C, a string is an array of characters ending with '\0'.
If the user enters anything other than a single digit number, print out an error "error (digit_string): [description of error]". Remember, as described above, to use fprintf rather than printf and send the output to stderr. Return NULL to indicate that an improper input was received.
Note: You may use string functions for this problem.The function headers must be as follows:
char* digit_string(unsigned int digit);
Now expand on this by creating number_string that returns a string for a number with up to three digits. 127 is written "one hundred twenty-seven" and 513 is written "five hundred thirteen".
Don't forget to complete this portion, test it, and commit it before moving on!char* number_string(unsigned int number);
typedef struct { int red, green, blue; } pixel; typedef struct { int height, width; pixel **pixels; } image;
For your first function, create vertical stripes in an image of height h and width w. The left-most stripe contains pixels p1, second stripe is p2, third stripe is p1, etc.
If h or w is 0, then set pixels to NULL and height and width to 0.
image vertical_stripes(pixel p1, pixel p2, unsigned int h, unsigned int w);
For your second function, create diagonal stripes in an image of height h and width w. The stripes are at a 45 degree angle, going up and to the right (or down and to the left). In the top row, the pixels alternate in pairs. The top-left pixel is p1, the one next to it is also p1, but the one next to that is p2, and the one next to that also p2, the one next to that is p1, etc. In the second row, the pixels are offset by one. The first pixel is p1, but the second two pixels are p2, the next two p1, next two p2, etc.
If h or w is 0, then set pixels to NULL and height and width to 0.
image diagonal_stripes(pixel p1, pixel p2, unsigned int h, unsigned int w);
You are going to write a function that writes the image to a file. I will give you the code to open and close the file. Instead of printing with printf, print with fprintf, as shown below. The skeleton of the function is given - you just need to fill in the missing parts.
int print_ppm(char *filename, image pic) { FILE *fp; fp = fopen(filename,"w"); if (!fp) { fprintf(stderr,"error: could not open file %s\n",filename); return 0; } fprintf(fp,"P3\n"); fprintf(fp,"%d %d\n",pic.width,pic.height); fprintf(fp,"255\n"); // print out all of the pixels, row by row, one per line fclose(fp); return 1; }If I made file "hello.txt", I can look at it on the command line:
$ cat hello.txt
In order to create an application that someone can use, you need an event loop. The event loop asks the user what he/she wants to do, then asks any questions that are necessary to perform that particular task. Once complete, it comes back and asks the user again what he/she would like to do.
This can also provide you a way of testing your code without having all of the tests hard-coded into main.
You have written two functions to create images, and they can create patterns of different colors. You are going to write an event loop that continually asks the user what he/she wants to do (create image diagonal or vertical stripes), what color the user wants (red, orange, yellow, green, blue, purple), what height and width, and what the filename should be.
Then you will call the appropriate functions you already wrote to accomplish the task.
In order to make sure we all have the same questions and question order (the testing infrastructure will need everyone's to be the same), here is code that implements the questions for a run of the program:
void event_loop() { printf("What would you like to do?\n"); printf("(0 = quit, 1 = vertical stripes, 2 = diagonal): "); // read in answer, interpret it printf("What is the first color?\n"); printf("(red, orange, yellow, green, blue, purple): "); // read in answer, interpret it printf("What is the second color?\n"); printf("(red, orange, yellow, green, blue, purple): "); // read in answer, interpret it printf("What height? "); // read in answer, interpret it printf("What width? "); // read in answer, interpret it printf("Filename of file to write it in: "); // read in answer, interpret it }Your job is to fill in the code that reads in each answer, translates it so it is useful to the program, and does any action based on it. You also need to loop rather than just go through once.
So that everyone agrees on the rgb values of different colors, here are the rgb values we'll use:
$ svn add hw3.h hw3.c hw3_main.c
$ svn commit -m "hw3 complete"