Your tutor has asked a lab pair to present their week 6 work.
Discuss the good, the bad and the ugly aspects of their code.
Please be gentle in any criticism - we are all learning!
int is_monochrome(int height, int width, int pixels[height][width]);
Your function should return 1 to indicate all elements of the array are 1 or 0. It should return 0 otherwise.
// return 1 iff image array contains only 1s and 0s, 0 otherwise int is_monochrome(int height, int width, int pixels[height][width]) { int column, row; row = 0; while (row < height) { column = 0; while (column < width) { if (pixels[column][row] != 1 && pixels[column][row] != 0) { return 0; } column = column + 1; } row = row + 1; } return 1; }
density = pixel_count / (height * width);to calculate an attribute suggested in the assignment spec. When they test their code they find that density is always 0.
They are mystified becaused they are calculating pixel_count, height and width correctly. What is happening?
density
is a double variable, the division of 2 ints will be truncated to an integer.
Here is one way to avoid the problem.
density = pixelCount / (double)(height * width);
Modern operating systems do not use a character to mark the end of files. They track the length of files separately.
C library functions such as getchar return a special value (EOF) when no input is available.
A special key sequence can be used in Unix-like terminals, typically cntrl-d to indicate no more input is available. This is a signal to the operating system and is not passed to the program as a character.
Any for loop can be re-written as a while loop.
When are for loops preferable?
For example, instead of this while loop:
i = 0; while (i < N) { // .... i = i + 1; }
Most experienced programmers would instead write this for loop:
for (i = 0; i < N; i = i + 1 ) { // .... }
#include <stdio.h> #define MAX_LINE 4096 int main(void) { char line[MAX_LINE]; int i; while (fgets(line, MAX_LINE, stdin) != NULL) { i = MAX_LINE; while (line[i] != '\n') { i = i - 1; } printf("line %d characters long\n", i); } return 0; }
line[MAX_LINE]
which is an illegal array index
line[-1]
).
line_length.c
which reads lines from its input and prints
how many characters each line contains.
The only functions you can use are fgets
and printf
.
You can assume lines contain at most 4096 characters.
For example:
./line_length Andrew Rocks line 12 characters long A very long line. line 17 characters long short line 5 characters long line 0 characters long
line_length.c
#include <stdio.h> #define MAX_LINE 4096 int main(void) { char line[MAX_LINE]; int i; while (fgets(line, MAX_LINE, stdin) != NULL) { i = 0; while (line[i] != '\n' && line[i] != '\0') { i = i + 1; } printf("line %d characters long\n", i); } return 0; }Heavily commented sample solution.
// reads lines from its input // and prints how many characters each line contains // only use fgets and printf #include <stdio.h> #include <stdlib.h> #define MAX 4096 // max number of characters in a line int main (int argc, char* argv[]) { int numC; // counter for number of characters in line char line[MAX]; // array to store the input // keep on reading until EOF or error while (fgets(line, MAX, stdin) != NULL) { // count the number of characters numC = 0; // each elt in the array line is a character (alphanumeric or whitespace) // unless the elt. is a newline or null terminating character // in which case the line has stopped // so numC is also the index for your line array while (line[numC] != '\n' && line[numC] != '\0') { // this is a character numC++; // now go test the next one } // print your result printf("line %d characters long\n", numC); } return EXIT_SUCCESS; }
strip_comments.c
which reads lines from its input and prints
them after removing any C // style comments. In another words if the line contains //
it does not print the // or anything after it.
The only functions you can use are fgets
and printf
.
You can assume lines contain at most 4096 characters.
For example:
./strip_comments x = x + 1; // This means add one to the variable x x = x + 1;Also - is that a good comment to add to a C program?
What if the input contains printf("//");
?
strip_comments.c
#include <stdio.h> #define MAX_LINE 4096 int main(void) { char line[MAX_LINE]; int i; while (fgets(line, MAX_LINE, stdin) != NULL) { // strip // style comments from input i = 0; while (line[i] != '\n' && line[i] != '\0') { // safe to look at line[i+1] because // we know here line[i] != '\0' if (line[i] == '/' && line[i + 1] == '/') { // replace // with end of -line line[i] = '\n'; line[i + 1] = '\0'; // could break here but loop will stop anyway } i = i + 1; } // write possibly-modified line printf("%s", line); } return 0; }Heavily commented sample solution.
// reads lines from its input // prints them after removing an // style comments // so DOES NOT PRINT // and everything after it #include <stdio.h> #include <stdlib.h> #define MAX 4096 int main (int argc, char* argv[]) { char line[MAX]; // to store input int i; // counter to iterate through each line you read in // get input until EOF or error while (fgets(line, MAX, stdin) != NULL) { // iterate through line and see if there is a comment, action appropriately // comments start with '/' and are followed by '/' // note the "base case" for the input for line is a 1 elt. array with '\n' // i.e. when you just hit enter // so lines arrays have at least 1 elt. initialized i = 0; while (line[i] != '\n' && line[i] != '\0') { // check if this is a comment // first elt. not newline or null character, so we have at least one other char. // i.e. line[i + 1] is legal if (line[i] == '/' && line[i+1] == '/') { // we have the start of a comment // printf stops printing strings at a null-terminating character '\0' // so "remove" comment and everything after by changing to '\0' line[i] = '\n'; // helps the user so lines print on a new line, // could go without this line as long as you print later like this // printf("%s\n", line); // this is the necessary one to stop printing line[i + 1] = '\0'; // break; // or loop will stop on next iteration since line[i] == '\n' } i++; } // write line (modified if it has comments) printf("%s", line); } return EXIT_SUCCESS; }
filter_empty_lines.c
which reads lines from its input and prints
them only if they contain a non-white-space-character.
In another words remove lines are empty or contain only white-space.
The only functions you can use are fgets
and printf
.
You can assume lines contain at most 4096 characters.
You can assume there are only 3 white space characters, space, tab & new-line.
For example:
./filter_empty_lines full line full line another no-empty line another no-empty line
filter_empty_lines.c
#include <stdio.h> #define MAX_LINE 4096 int main(void) { char line[MAX_LINE]; int i; int whiteSpaceCount; while (fgets(line, MAX_LINE, stdin) != NULL) { // print lines iff they contain a non white-space character i = 0; whiteSpaceCount = 0; while (line[i] != '\0') { // test for white space (isspace would be better here) if (line[i] != ' ' && line[i] != '\t' && line[i] != '\n') { whiteSpaceCount = whiteSpaceCount + 1; // could break here } i = i + 1; } if (whiteSpaceCount > 0) { printf("%s", line); } } return 0; }Heavily commented sample solution.
// reads lines from input // prints ONLY IF they contain a non-whitespace character // i.e. remove lines that are empty or contain ONLY whitespace #include <stdio.h> #include <stdlib.h> #define MAX 4096 #define TRUE 1 #define FALSE 0 int main (int argc, char* argv[]) { char line[MAX]; // to store input int i; // counter for the line int notWhite; // counter for number of notwhitespace characters we have // read until EOF or error while (fgets(line, MAX, stdin) != NULL) { // now iterate through line to see if it has whitespace // strings are terminated by a null terminating character i = 0; notWhite = 0; // assume this is an empty line, prove false while (line[i] != '\0') { // test for whitespace if (line[i] != ' ' && line[i] != '\t' && line[i] != '\n') { // this character isn't whitespace notWhite++; // increment number of non-whitespace break; // can do this without a break // would just go count all the non-whitespace chars // but really now you have all the info you need, slight optimization } i++; } // print line only if no whitespace if (notWhite > 0) { // found non-whitespace characters printf("%s", line); } } return EXIT_SUCCESS; }
reverse.c
which reads lines and writes them out
with the characters of each line in reverse order.
It should stop when it reaches the end of input.
For example:
./reverse The quick brown fox jumped over the lazy dog. .god yzal eht revo depmuj xof nworb kciuq ehT It was the best of times. It was the worst of times. .semit fo tsrow eht saw tI .semit fo tseb eht saw tI This is the last line. .enil tsal eht si sihT <control-d>
reverse.c
#include <stdio.h> #define MAX_LINE 4096 int main(void) { char line[MAX_LINE]; int i; while (fgets(line, MAX_LINE, stdin) != NULL) { i = 0; while (line[i] != '\n' && line[i] != '\0') { i = i + 1; } i = i - 1; while (i >= 0) { printf("%c", line[i]); i = i - 1; } printf("\n"); } return 0; }Heavily commented sample solution.
// reads lines and writes them out // with the chars of each line in reverse ordder #include <stdio.h> #include <stdlib.h> #define MAX 4096 int main (int argc, char* argv[]) { char line[MAX]; int i; while (fgets(line, MAX, stdin) != NULL) { // now print the line in reverse order // so first figure out what your HIGHEST index // that's been initialized is i = 0; while (line[i] != '\n' && line[i] != '\0') { // this char isn't the last one i++; } // when you exit, i is one greater than the last char // since line[i] == '\n' or line[i] == '\0' i--; // so minus one to get to the index of the last char // now print char by char until the first element at index 0 while (i >= 0) { printf("%c", line[i]); i--; } // end this line printf("\n"); } return EXIT_SUCCESS; }
Your tutor may still choose to cover some of the questions time permitting.
double get_density(int height, int width, int pixels[height][width]);
void rotate_array(int height, int width, int pixels[height][width], int rotation);
int scrabble(char letters[], int num_letters, char *string);