Q) Something is wrong with my program and I cannot figure it out.
A) Here are a few steps you can take:
Try compiling with the "-Wall" option (e.g. "gcc -Wall -o ./bmp_edit ./bmp_edit.c"). This will give you the maximum number of compiler warnings with which to debug your program. Try to remove all warnings.
Try running your program on top of GDB. Don't forget to compile with the "-g" option to enable debug symbols. You can add breakpoints to observe variable values at different points in your program. Also, if your program segmentation faults, it would show where it crashed.
Try printing important values in your program as it is running using printfs.
Q) What if I get errors like "Disk quota exceeded"?
A) You can check your disk quota by the command:
thoth $ fs lq
This means the disk quota allocated to your Pitt account is full. By default it is 5 MB. Please follow the below steps:
1) Log into my.pitt.edu.
2) Click on "Profile" in the upper right hand corner.
3) Choose "Manage Your Account".
4) Manage E-mail Quota.
5) Click the "Increase my UNIX Quota" button. This will take you from 4 MB to 1 GB.
If you need help contact CSSD help desk: http://technology.pitt.edu/help-desk. I found that choosing the chat option leads to the fastest result. If for some reason you are not able to increase your quota, you can temporarily move unneeded files to your PC using an SFTP client like FileZilla.
Q) How do I transfer files back between thoth and my PC?
A) I have linked a couple of widely used open source GUI file clients to the course website such as WinSCP (for Windows users) and FileZilla (for All users). Also, Mac and Linux usually comes with a command line tool called 'scp' with which to copy files remotely.
Q) Sometimes the scanf returns immediately when apparently there is no user input?
A) It is due to a lingering newline '\n' character that was not consumed in the previous scanf.
Basically, you will have to drain the input stream buffer of all characters until you see a newline. As follows:
while(1) { char c; // drain until newline do { scanf("%c", &c); } while(c != '\n'); }
Q) How would you use rand() and srand() exactly to generate random numbers?
A) Please try reading the below links:
http://www.cplusplus.com/reference/cstdlib/srand/
http://www.cplusplus.com/reference/cstdlib/rand/
https://en.wikipedia.org/wiki/Random_seed
The former two describe the uses of srand and rand, and the last explains what a random seed is in a pseudorandom number generator.
Q) Do I have to handle all types of user input correctly?
A) You are encouraged to do so. But your programs will be tested and graded using only correct input.
Q) Why do you have two grayscale images for img1 and img2? They look exactly the same to me?
A) Floating point calculations can have slightly different results depending upon the order you do calculations and whether you use a double type (8 bytes) or float type (4 bytes). So both images "img1 grayscale" and "img1 grayscale (alternative)" are correct. They look almost the same because there are only a few pixels where this precision mattered. If you do a hexdump diff (see below) and you only see a few pixels that are different you might have come up with another correct answer so let me know and I'll add it to the list of correct solutions. If you are interested in learning more about floating point precision, follow this link:
https://en.wikipedia.org/wiki/Floating-point_arithmetic#Accuracy_problems
The link has an example real world problem that occurred when a Patriot missile was not able to intercept an incoming Scud missile in Saudi Arabia due to loss of precision.
Q) What if I am getting weird artifacts in my grayscale converter?
A) Most likely the issue has to do with types, assuming you implemented the formulas correctly. The pixel colors should be defined with 'unsigned char' types instead of 'char' types. Char has a range of -128 to 128, not 0 to 255 which is required for an RGB representation. So when you read the pixels from the file, you might end up with negative values inadvertently.
Q) Do I have to match the output files on the course website exactly?
A) Yes. A good way to check exactly is through the "diff" tool on thoth. For example,
thoth $ diff ./img1.bmp ./img1_answer.bmp
If there is nothing printed on the commandline, it means they are the same. Otherwise, it will say they differ. Note: even if the files match visually they might still differ when compared byte by byte due to difference in the row padding etc.
Q) If my output does not match, how do I figure out where I went wrong?
A) You can do a hexdump of each output and then diff the two files. For example,
thoth $ xxd ./img1.bmp > ./img1.bmp.hex thoth $ xxd ./img1.answer.bmp > ./img1.answer.bmp.hex thoth $ diff ./img1.bmp.hex ./img1.answer.bmp.hex
The hexdump could be empty if you run out of disk quota. See related question above to solve that problem.
Q) My fread() calls work fine on their own but read in wrong data when intermixed with fwrite() calls.
A) This should not be happening on thoth but it may happen on some machines. According to "man fopen":
Reads and writes may be intermixed on read/write streams in any order.
Note that ANSI C requires that a file positioning function intervene
between output and input, unless an input operation encounters end-of-
file. (If this condition is not met, then a read is allowed to return
the result of writes other than the most recent.) Therefore it is good
practice (and indeed sometimes necessary under Linux) to put an
fseek(3) or fgetpos(3) operation between write and read operations on
such a stream. This operation may be an apparent no-op (as in
fseek(..., 0L, SEEK_CUR) called for its synchronizing side effect.
What this is saying is: after you do the fwrite() and before you do the next fread() of the next pixel, you should put a fseek(f, 0, SEEK_CUR);. That fseek looks like a no-op since you are seeking to offset 0 from the current offset. But it has a so-called "synchronizing side-effect". What this is referring to is the fact that whenever you call fwrite() it does not directly update the file and first passes through a buffer. So the changes you make on the buffer may not get immediately reflected up on the file, causing the subsequent fread() to read the wrong data. Fseek() has a side-effect of synchronizing the buffer with the file, removing this problem. Fflush() has a similar effect. Here is the relevant part in the C99 Standard Section 7.19.5.3 Paragraph 6.