In this Lab, you will practise:
Create a new directory for this lab called lab07
by typing:
mkdir lab07Change to this directory by typing:
cd lab07
Some of the exercises in the labs require you to read characters using the getchar function.
getchar reads the next character from standard input and returns it.
If getchar is unable to read a character it return the special value EOF
.
When input is coming from a file, getchar will return EOF
after the last character in the file is read.
When input is coming from a (Linux/OSX) terminal, you can indicate no more characters
can be read by typing Ctrl+D.
This will cause getchar to return EOF
In some of this week's lab exercises you will find it convenient to put the test input in a file, rather than type it every time you want to test the program.
You can use a < character to indicate to the shell that you want to run a program taking its input from a file.
So for example you might create the file input.txt
with gedit and
then run a.out
takes its input from the file rather the terminal:
gedit input.txt & $ ./a.out <input.txt
strlen.c
which reads characters from stdin and prints the number of characters in that string. Most of the program is complete for you, you simply need to complete the strlength function.// Author: Hayden Smith 2019 #include#define MAXLINE 1024 int strlength(char *); int main(void) { char line[MAXLINE]; fgets(line, MAXLINE, stdin); printf("Strlen is %d\n", strlength(line)); } int strlength(char *s) { // TODO return 0; }
$ ./strlen cs1911 6
$ 1911 autotest lab07 strlen.c
strlen.c
// Author: Hayden Smith 2019 #include <stdio.h> #define MAXLINE 1024 int strlength(char *); int main(void) { char line[MAXLINE]; fgets(line, MAXLINE, stdin); printf("Strlen is %d\n", strlength(line)); } int strlength(char *s) { int i = 0; while (s[i] != '\0') { i++; } return i - 1; }
devowel.c
which reads characters from its input
and writes the same charcters to its output, except it does not write lower case vowels ('a', 'e','i', 'o', 'u').
Your program should stop only at the end of input.
For example:
$ ./devowel The quick brown fox jumped over the lazy dog. Th qck brwn fx jmpd vr th lzy dg. It was the best of times. It was the worst of times. It ws th bst f tms. It ws th wrst f tms.
The only functions you are allowed to use are getchar
and putchar
.
Don't use printf
, scanf
or fgets
.
As usual autotest is available to test your program.
$ 1911 autotest lab07 devowel.c
devowel.c
#include <stdio.h> int main(void) { int c; // getchar returns an int which will contain either // the ASCII code of the character read or EOF c = getchar(); while (c != EOF) { // test if ch is not a vowel if (c != 'a' && c != 'e' && c != 'i' && c != 'o' && c != 'u') { putchar(c); } c = getchar(); } return 0; }
Write a program, palindrome.c
, which reads a string and tests if
it is a palindrome.
For example:
$ ./palindrome Enter a string: kayak String is a palindrome $ ./palindrome Enter a string: canoe String is not a palindrome
Don't use scanf
- use fgets
to read the string.
Note, your program needs to read only one string - it doesn't have to read until the end of input.
You can assume lines contain at most 4096 characters.
As usual autotest is available to test your program.
$ 1911 autotest lab07 palindrome.c
palindrome.c
// // Read a string and then indicate if it is a palindrome // written by Andrew Taylor andrewt@cse.unsw.edu.au // April 2014 as a COMP1911 lab exercise // #include <stdio.h> #define MAXLINE 4094 int isPalindrome(char line[]); int findRightMostIndex(char line[]); int main(int argc, char *args[]) { char line[MAXLINE]; printf("Enter a string: "); fgets(line, MAXLINE, stdin); if(isPalindrome(line)){ printf("String is a palindrome\n"); } else { printf("String is not a palindrome\n"); } return 0; } //Returns 1 if the line is a palindrome and 0 otherwise int isPalindrome(char line[]){ int left = 0; int right = findRightMostIndex(line); //The empty string is a palindrome if(right == -1) { return 1; } while (left < right) { if (line[left] != line[right]) { return 0; } left = left + 1; right = right - 1; } return 1; } //Finds right most index of string or that last character // up to the first newline //returns -1 if there are no characters or if it starts with a newline int findRightMostIndex(char line[]){ int right = 0; while (line[right] != '\0' && line[right] != '\n') { right = right + 1; } right = right - 1; return right; }
one.c
, which reads in one string from the user and writes out the characters
one per line to a new file in the same directory called data.txt.
The output from your program should look like this:
$ ./one Enter a string: HelloThen when you try and print the file out you expect this:
H e l l o
Don't use scanf
use fgets
to read the string.
Note, your program needs to read only one string - it doesn't have to read until the end of input.
You can assume lines contain at most 4096 characters.
one.c
#include <stdio.h> #define MAXLINE 4094 int main(void) { char line[MAXLINE]; int i; FILE *stream; printf("Enter a string: "); fgets(line, MAXLINE, stdin); i = 0; stream = fopen("data.txt", "w"); while (line[i] != '\n' && line[i] != '\0') { fprintf(stream, "%c\n", line[i]); i = i + 1; } return 0; }
palindrome1.c
) so characters which are not letters
are ignored and difference between upper case and
lower case are ignored.
For example:
$ ./palindrome1 Enter a string: Do geese see God? String is a palindrome $ ./palindrome1 Enter a string: Do ducks see God? String is not a palindrome $ ./palindrome1 Enter a string: Madam, I'm Adam String is a palindrome $ ./palindrome1 Enter a string: Madam, I'm Andrew String is not a palindrome
Hint: if you #include <ctype.h>
you can use a C library function named tolower
to convert a character to lower case.
$ 1911 autotest lab07 palindrome1.c
palindrome1.c
// // Read a string and then indicate if it is a palindrome // only lower case alphabetic letters are considered // written by Andrew Taylor andrewt@cse.unsw.edu.au // April 2014 as a COMP1911 lab exercise // #include <stdio.h> #include <ctype.h> #define MAXLINE 4094 int isPalindrome(char line[]); int findRightMostIndex(char line[]); int main(int argc, char *args[]) { char line[MAXLINE]; int left, right ; printf("Enter a string: "); fgets(line, MAXLINE, stdin); if(isPalindrome(line)){ printf("String is a palindrome\n"); } else { printf("String is not a palindrome\n"); } return 0; } //Finds right most index of string or that last character // up to the first newline //returns -1 if there are no characters or if it starts with a newline int findRightMostIndex(char line[]){ int right = 0; while (line[right] != '\0' && line[right] != '\n') { right = right + 1; } right = right - 1; return right; } //Returns 1 if the line is a palindrome and 0 otherwise int isPalindrome(char line[]){ int left = 0; int right = findRightMostIndex(line); //The empty string is a palindrome if(right == -1) { return 1; } while (left < right) { line[left] = tolower(line[left]); line[right] = tolower(line[right]); if (line[left] < 'a' || line[left] > 'z') { left = left + 1; } else if (line[right] < 'a' || line[right] > 'z') { right = right - 1; } else if (line[left] != line[right]) { return 0; } else { left = left + 1; right = right - 1; } } return 1; }
black.c
from the course account to your
directory by typing:
cp ~cs1911/public_html/23T2/code/black.c chessboard.cCompile it, run it and then type
display black.bmp
At the moment all you should see is a 512x512 completely black bitmap image.
Modify the file so it generates a chessboard image consisting of 16x16 black and white squares. The name of the bmp file it generates should be chessboard.bmp
Hint: You should only need to modify the generateData function and change the name of the BMP_FILE. Hint: Look at the example code (Wee7 lecture code) to create different colours and a digaonal bmpDemo.c.
chessboard.c
// An advanced example // To compile, run and view the finished product type // dcc -o chessboard chessboard.c // ./black // display chessboard.bmp // An example of creating a bitmap file with code. // We generate the bytes using a while loop. // The bitmap is 512 x 512. // The bitmap file has a header, with data that includes // the size of the file and other things we do not need to worry about. // After the header, there are data bytes that represent the pixels. // Each pixel is represented by 3 bytes. // One for blue, one for green and one for red. // The first 3 bytes in the pixel data represent // the bottom left corner of the file. // Created by Richard Buckland on 14/04/11, edited 5/4/14 // Edited by Angela Finlayson on 30/04/2017 #include <stdio.h> #include <stdlib.h> #include <assert.h> #define BYTES_PER_PIXEL 3 #define BITS_PER_PIXEL (BYTES_PER_PIXEL*8) #define NUMBER_PLANES 1 #define PIX_PER_METRE 2835 #define MAGIC_NUMBER 0x4d42 #define NO_COMPRESSION 0 #define OFFSET 54 #define DIB_HEADER_SIZE 40 #define NUM_COLORS 0 #define SIZE 512 #define BMP_FILE "chessboard.bmp" #define SQUARE_SIZE 16 void writeHeader (FILE *file); void generateData(FILE *file); void writePixel(unsigned char b, unsigned char r, unsigned char g, FILE * f); int main (void) { FILE *outputFile; outputFile = fopen(BMP_FILE, "wb"); if ( outputFile == NULL ){ fprintf(stderr,"Could not open file\n"); } writeHeader(outputFile); generateData(outputFile); fclose(outputFile); return EXIT_SUCCESS; } // Change this function to create different images! // Alternating between black and white in a chessboard pattern, every SQUARE_SIZE pixels void generateData(FILE * f){ unsigned char blue = 0; unsigned char green = 0; unsigned char red = 0; int row = 0; int col = 0; while (row < SIZE) { col = 0; while(col < SIZE){ writePixel(blue,green,red,f); col++; if( col % SQUARE_SIZE == 0){ if(blue == 255 ){ blue = 0; green = 0; red = 0; } else { blue = 255; green = 255; red = 255; } } } row++; if( row % SQUARE_SIZE == 0){ if(blue == 255 ){ blue = 000; green = 0; red = 0; } else { blue = 255; green = 255; red = 255; } } } } // The colour of each pixel is determined by its // blue, green and red values. // So each pixel needs 3 bytes of data written to the file void writePixel(unsigned char b, unsigned char g, unsigned char r, FILE * f){ fwrite (&b, sizeof (unsigned char), 1, f); fwrite (&g, sizeof (unsigned char), 1, f); fwrite (&r, sizeof (unsigned char), 1, f); } // Do not worry if you do not understand this code and what all the // values are for. It is just writing a header in the bmp and follows // the standard format For more info if you are interested see // https://en.wikipedia.org/wiki/BMP_file_format void writeHeader (FILE *file) { unsigned short magicNumber = MAGIC_NUMBER; fwrite (&magicNumber, sizeof magicNumber, 1, file); unsigned int fileSize = OFFSET + (SIZE * SIZE * BYTES_PER_PIXEL); fwrite (&fileSize, sizeof fileSize, 1, file); unsigned int reserved = 0; fwrite (&reserved, sizeof reserved, 1, file); unsigned int offset = OFFSET; fwrite (&offset, sizeof offset, 1, file); unsigned int dibHeaderSize = DIB_HEADER_SIZE; fwrite (&dibHeaderSize, sizeof dibHeaderSize, 1, file); unsigned int width = SIZE; fwrite (&width, sizeof width, 1, file); unsigned int height = SIZE; fwrite (&height, sizeof height, 1, file); unsigned short planes = NUMBER_PLANES; fwrite (&planes, sizeof planes, 1, file); unsigned short bitsPerPixel = BITS_PER_PIXEL; fwrite (&bitsPerPixel, sizeof bitsPerPixel, 1, file); unsigned int compression = NO_COMPRESSION; fwrite (&compression, sizeof compression, 1, file); unsigned int imageSize = (SIZE * SIZE * BYTES_PER_PIXEL); fwrite (&imageSize, sizeof imageSize, 1, file); unsigned int hResolution = PIX_PER_METRE; fwrite (&hResolution, sizeof hResolution, 1, file); unsigned int vResolution = PIX_PER_METRE; fwrite (&vResolution, sizeof vResolution, 1, file); unsigned int numColors = NUM_COLORS; fwrite (&numColors, sizeof numColors, 1, file); unsigned int importantColors = NUM_COLORS; fwrite (&importantColors, sizeof importantColors, 1, file); }
lab07
directory):
give cs1911 lab07 strlen.c devowel.c one.c palindrome.c palindrome1.c chessboard.cSubmit advanced exercises only if you attempt the advanced exercise.
Remember the lab assessment guidelines - if you don't finish the exercises
you can finish them in your own time, submit them
by 19:59:59 Sunday using give
and ask ask tutor to assess them at the start of
the following lab.
You can also just run the autotests without submitting by typing
1911 autotest lab07