CSSE 120 — Intro. to Software Development
Final C Project — Ascii Art
Overview
You will create a menu-driven system that can display and transform ASCII
art and read and write ASCII art data files.
This is an individual project. We want everyone to keep practicing their C programming so you do well on the final exam!
- Reminder: As always with individual work, it is fine to get help with general issues, or to get help learning how to (say) use structures, or to understand a mysterious compile-time error, but sharing code is never allowed for individual projects.
Your work for this project should be done in the AsciiArtPart2 project that you can check out from your individual or pair SVN repository.
Sample Input and Output
The main menu should look something like:
1. Change the base filename.
2. Change the number of rows and columns to use (optional).
3. Load a coordinate file.
4. Load an image file.
5. Display the image on the console.
6. Save a coordinate file.
7. Save an image file.
8. Transform the data by ...
(possibly more transformations here)
99. Exit
Enter your choice now:
Note that you already completed options 3 and 8 in part 1 of this project.
- If you use the form shown above, the user should enter one of the numbers shown (1, 2, 3, 4, 5,
6, 7, 8, 99) and the program should then do the associated action. If they
enter another number, it should ask them to try again. If they enter a
non-number, it is OK if your program does the wrong thing or crashes.
- Your main() function will initialize the base name and data matrix,
and contain a while loop that repeatedly asks for the user to enter an option.
The computer will then respond to that choice by calling the appropriate function.
So you will need to write eight functions, for example
void enterBaseName(char base[])
and void loadCoordinateFile(char
base[], char image[][SIZE])
.
Follow good top-down design and don't write your whole program in main()!
- You will choose one or more transformations to implement.
Suggestions are given in the next section.
- As part of your testing, we strongly recommend that you create an image and give it in both file formats to a friend,
who can run your files using their program to display your image.
This will help expose bugs in both of your programs.
- When testing, please change the base name before writing to a file
so you don't overwrite your input data!
Ideas for Transformations
- Replace one set of letters with another set of letters, hardcoding the sets
as strings.
- Translation (shift image by a number of rows and columns specified by the user).
- Reflection (mutating matrix so that the image is mirrored. Could mirror vertically, horizontally, even diagonally).
- Rotation (rotate the matrix by a multiple of 90 degrees).
- Scale (for example, double size the image, so the upper-left 50x50 expends to fill entire image, with each letter becoming a 2x2 block of letters).
How to Create Images Using Eclipse's Text Editor
- Images must be exactly 100x100 (unless you allow for variables sizes, see below).
- Make a copy of the blank.txt file
- Show whitespace so you can see that all rows have the right number of spaces. Windows > Preferences > General > Editors > Text Editors:

- Press insert key on keyboard to go into OVERWRITE (vs insert) mode. Your cursor will change from a flashing line to a flashing block.
Type your pic. If it's small, put it roughly in the upper-left corner of the matrix.
- Some text editors allow you to select a vertical block of text for copy-paste,
which can be pretty handy. For example, in Notepad++ (which is available for
free online), just hold down the alt key while you move the mouse.
Other Requirements
It is not enough to just get the program to work!
Programming style will also affect your grade. An A or B
program will use functions correctly, willl have well-named variables and
functions, and will avoid global variables and magic numbers.
Grading: 100 points total
Basic features (70 points; get these working first):
- (5) Allows the user to input the basename.
- (5) Reads in a coordinate file
- (15) Read in an image file
- (10) Writes a coordinate file
- (5) Writes an image file
- (5) Menu works appropriately in a loop, exiting when specified.
- (5) The code has appropriate documentation (comments).
- (10) The code uses appropriate style regarding: variable names,
breakdown into functions and structures, indenting, use of white space, and so forth.
- (10) Allows the user to transform the matrix in any one of the ways specified above.
Intermediate features (20-35 points)
- (10) Allows the user to transform the matrix in a second of the ways specified above.
- (10-25) Adds one other function to your code. A third transformation from the list above would earn you 10 points
(and thus a total of 90 points). A totally
different kind of transformation could earn you 15-25 points depending on
how challenging and creative it is. I'm pretty
flexible, but feel free to ask me.
- One "interesting" (= 25 points) new function to your code
is to deal with images that have dimensions other than 100x100. Input files, whether coordinates or
image data, will start with the number of rows and columns, which must each be
less than SIZE. Look at the data files named "withSize" for examples.
You must store the size in a struct. You may continue to declare your
matrix as 100x100, and leave some part of it unused. But I'm requiring
you to store and pass around the dimensions in a struct, not
two separate
parameters and not as global variables. You must
implement option 2 in the sample menu and experiment with data files
that are non-100x100. Hint: structs in
C are like ints: you can return them, but you can't mutate them unless
you use a pointer to one (which shouldn't be necessary in this program,
just return it if needed).
Suggestions for C Projects —Read and Obey These! You'll be sorry if you don't!
Iterative enhancement
This is critical: For the rest of your coding, identify one TEENY additional functionality that seems right to do next. Implement and test. Don't proceed until you get that teeny functionality working.
- This way, you ALWAYS have an operative program.
- We cannot grade an inoperative program, so this is really important.
- Additionally, using this iterative enhancement ensures that you don't lose control of your program — in C, you risk losing control each time you add more than 50 lines of code or so. So work and test in much smaller increments.
The key is testing as you go. Work through the problem in an order than helps you accomplish that.
Gotcha's
As you have seen, the hard part of C is avoiding mistakes. Once you make a mistake, it is often time-consuming to track down the error.
So try to avoid these common mistakes:
- Abusing scanf.
- Have exactly as many variables to be set as there are % signs in the format string.
- Make sure your variable types match up to your % formatting character:
-
%d
for int variables
-
%f
for float variables
-
%lf
for double variables (memory aid: lf means “long float”)
-
%s
for strings (and remember that %s
stops when it sees whitespace — that's why we made the restriction of no spaces in course names)
- Remember to send pointers as the arguments after the format string.
- Abusing printf. Likewise, make sure that printf has exactly as many variables to be set as there are % signs in the format string, and that the types match.
- Mixing scanf with other input functions. Don't, unless you know what you are doing. Instead, stick to scanf (and fscanf for reading from a file).
- Launching with errors. Never run the program if you see compiler error-messages. If you see:
Errors exist in a required project. Continue launch?
always respond No.
- If you do the run, you are running an old version of the program that contains who-knows-what.
- So fix the compiler error messages FIRST, then run.
- Even warning messages are usually worth fixing. Your compiler does an excellent job with warnings, far better than compilers from a decade ago.
If you see a little asterisk by the name of the file on the tab in the Editor, that means that file has not been saved. Never run unless it has been saved (for most of you, running asks if you want to save it).
- Mysterious compile-time error messages. If you experience this, here are several things to try:
- First, make sure you are looking at the right line of code. Click on the relevant blue link in the Console.
- Change the file in some innocuous way (add a space somewhere). Save the file manually. Then do Project ~ Clean. This forces a recompile and often “wakes up” the compiler when it falls behind.
- Do Edit ~ Format (or its shortcut Control-Shift-F). If your code is now indented in an unexpected way, you probably have a missing curly-brace somewhere (or possibly an extra one). Find the first place where the indentation is not what you expect. You are probably missing a curly-brace right above that point.
- Get another set of eyes — ask someone else to look at the line with the error and offer their advice.
- Compiling while running. If you get an error message that is something like:
mingw32\bin\ld.exe: cannot open output file [SOMETHING HERE].exe: Permission denied
that almost certainly means that you are still running the program in this or another console. To fix this, you often have to use the pull-down menu on the right-hand-side of Console et al windows that says Display Selected Console. Select it, find the running programs and stop them with the usual red boxes. There are often MANY running programs in this situation; you must stop them all.
- Missing functions. Suppose you get a compile-time error message like:
implicit declaration of function 'foo'
or perhaps:
conflicting types for 'foo'
Any of the following could be the problem:
- You misspelled the name of the function, either in the call or the definition of the function.
- You called or defined the function with the wrong number or wrong type(s) of arguments.
- The function belongs to a library that you failed to #include.
- You defined the function BELOW the place in the file where you called it.
- The C compiler barfs at this because it processes a source file from top to bottom,
so when it hits the function call it does not yet know what it needs to know about the function.
- One way to solve this problem is to move the function definition ABOVE its call(s).
- Another, perhaps better, way is to put prototypes
near the top of the file (before any function definitions), like this:
double foo(double y[], int size); // Prototype, near the top of the file.
...
double foo(double y[], int size) {
... // Code for the function here
}
The prototype is shown in red. It's easy to obtain — just copy the first line of the function definition
and replace the curly-brace (and its preceding space, if any) by a semicolon. Its a good habit to make a prototype
every time you define a function, because it avoids this problem and provides a handy list of your functions
at the top of the file.
- Messy code is almost impossible to get correct. Keep things simple and clean. Refactor often to maintain that simplicity and cleanliness.
- Waiting to the last minute guarantees failure.
- Start early.
- Work steadily.
- The CSSE lab from 7 to 9 p.m. is the PERFECT place to work because you get instant help when needed.
- Email
csse120-staff@rose-hulman.edu
if you can't get help in person.
Turn In
Submit your work by committing it to your individual SVN repository. Commit often since that backs up your work.