Week 08 Tutorial Sample Answers
1. How are you going with assignment 1?
Please remind students that the assignment is due at the end of this week.
2. Consider the program below:
#include <stdio.h> int main(void) { char str[10]; str[0] = 'H'; str[1] = 'i'; printf("%s", str); return 0; }
-
What will happen when the above program is compiled and executed?
The above program will compile without errors.
printf
, like many C library functions, expects strings to be null-terminated.In other words,
printf
expects the arraystr
to contain an element with value '\0' which marks the end of the sequence of characters to be printed.printf
will printstr[0]
('H'),str[1]
then examinestr[2]
.Code produced by
dcc --valgrind
will then stop with an error becausestr[2]
is uninitialized.The code with gcc will keep executing and printing elements from
str
until it encounters one containing '\0'. Oftenstr[2]
will by chance contain '\0' and the program will work correctly.Another common behavior will be that the program prints some extra "random" characters.
It is also possible the program will index outside the array, which would result in it stopping with an error if it was compiled with
dcc
.If the program was compiled with gcc and uses indices well outside the array, it may be terminated by the operating system because of an illegal memory access.
-
How do you correct the program?
#include <stdio.h> int main(void) { char str[10]; str[0] = 'H'; str[1] = 'i'; str[2] = '\0'; printf("%s", str); return 0; }
3. Name 3 errors in this program:
#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("the line is %d characters long\n", i); } return 0; }
- On the first execution of the inner while loop, it accesses
line[MAX_LINE]
, which is an illegal array index. - It accesses uninitialized array elements - fgets only assigns to the array elements necessary to hold the characters of a line plus a '\0'.
- There may not be a '\n' in the array. fgets won't put a '\n' in the array if the line is too long to fit in the array. If there is no '\n' in the array, the code will access a non-existent array element (
line[-1]
).
4. Write a program 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];
while (fgets(line, MAX_LINE, stdin) != NULL) {
int i = 0;
while (line[i] != '\n' && line[i] != '\0') {
i = i + 1;
}
printf("line %d characters long\n", i);
}
return 0;
}
line_length.c
// COMP1511 W9 tutorial question 5
#include <stdio.h>
#include <stdlib.h>
#define MAX 4096
// prototype, returns an integers and takes in a string called line
int count(char *line);
int main(void) {
char line[MAX]; // holder for each line
while (fgets(line, MAX, stdin) != NULL) {
// so read in successfully
printf("line %d characters long\n", count(line));
}
return 0;
}
int count(char *line) {
int i = 0;
while (line[i] != '\n' && line[i] != '\0') {
i = i + 1;
}
return i;
}
5. Write a program strip_comments.c
which reads lines from its input and prints them after removing any C // style comments.
In other 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?
strip_comments.c
#include <stdio.h>
#define MAX_LINE 4096
int main(void) {
char line[MAX_LINE];
int i;
// reads lines and print them after
// removing // style comments
while (fgets(line, MAX_LINE, stdin) != NULL) {
// iterate through line and see if we encounter a '/' then '/'
// everything after is a comment, so stop the string there
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 a newline and null-terminator
line[i] = '\n';
line[i + 1] = '\0';
// could break here but loop will stop anyway
// because after i = i + 1, line[i] == '\0'
}
i = i + 1;
}
// write possibly-modified line
printf("%s", line);
}
return 0;
}
6. Write a program filter_empty_lines.c
which reads lines from its input and prints them only if they contain a non-white-space character.
In other words, remove lines that 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, and newline.
For example:
./filter_empty_lines full line full line another non-empty line another non-empty line
filter_empty_lines.c
#include <stdio.h>
#include <stdlib.h>
#define MAX 4096
int main(void) {
char line[MAX];
while (fgets(line, MAX, stdin) != NULL) {
// count non-whitespace characaters on this line
int non_whitespace_count = 0;
int i = 0;
while (line[i] != '\n' && line[i] != '\0') {
// test for non white space
// !isspace(line[i]) would be better (from ctype.h)
if ((line[i] != ' ') && (line[i] != '\t') && (line[i] != '\n')) {
// this is a non-whitespace character
non_whitespace_count = non_whitespace_count + 1;
// could break here
}
i = i + 1;
}
// print the line if it has non-whitespace character
if (non_whitespace_count > 0) {
printf("%s", line);
}
}
return 0;
}
7. Write a C program 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 the 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
reverse.c
#include <stdio.h>
#define MAX_LINE 4096
int main(void) {
char line[MAX_LINE];
while (fgets(line, MAX_LINE, stdin) != NULL) {
// find the length of this line
int i = 0;
while (line[i] != '\n' && line[i] != '\0') {
i = i + 1;
}
// when we exit, i is the index of either
// newline character or null terminator
// so go back one position
i = i - 1;
// now print line in reverse
while (i >= 0) {
printf("%c", line[i]);
i = i - 1;
}
printf("\n");
}
return 0;
}
8. Strlen is a function that returns the length of a string. Write your own C function to do the same.
int myStrlen(char *string);
int myStrlen(char *string) {
int i = 0;
while (string[i] != '\n' && string[i] != '\0') {
i = i + 1;
}
return i;
}