|
Solution for Labsheet 3: 1-dimensional Arrays, Strings, and Structures
This page provides some sample solutions and discussion
on some of the tasks of Labsheet-3.
Tasks
-
Write a function named my_strlen() that calculates and returns the length of a string.
Your function should take one argument, a character array that represents the string, and return an integer - the length of the string.
The calling function (the main() function) should print
the integer returned by your my_strlen() function.
Test your function with some string constants and by passing to it some command-line arguments.
#include <stdio.h>
#include <stdlib.h>
int my_strlen(char str[])
{
int length = 0;
// EXAMINE EACH CHARACTER OF THE ARRAY PARAMETER str
while( str[length] != '\0' ) { // is it the NULL-byte?
++length; // advance our way along str[]
}
return length;
}
int main(int argc, char *argv[])
{
// LOOP OVER EACH OF THE COMMAND-LINE ARGUMENTS
for(int a=1 ; a < argc ; ++a) {
printf("%i\n", my_strlen( argv[a] ));
}
// ALSO TEST my_strlen() WITH SOME STRING CONSTANTS
printf("%i\n", my_strlen( "moose" ));
printf("%i\n", my_strlen( "A short sentence." ));
printf("%i\n", my_strlen( "" )); // the empty string
}
-
A computer password is often consider "safe" (i.e. hard to guess) if it contains a mixture of uppercase and lowercase characters and digits.
Write a function named isSafe() to determine if a potential password (a string) has at least two uppercase characters, two lowercase characters, and two digits.
Your function should take a single character array as its argument and return a Boolean value to indicate whether the password is considered safe or not.
See the online documentation (man pages) for help with the
isalpha(), islower(), and isupper() functions.
Include the appropriate header file <ctype.h> into your program.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <ctype.h>
bool isSafe(char password[])
{
int i = 0;
int nUppers = 0;
int nLowers = 0;
int nDigits = 0;
// EXAMINE EACH CHARACTER OF THE ARRAY PARAMETER password
while( password[i] != '\0' ) { // is it the NULL-byte?
if(isupper(password[i]) != 0) {
++nUppers;
}
else if(islower(password[i]) != 0) {
++nLowers;
}
else if(isdigit(password[i]) != 0) {
++nDigits;
}
++i; // advance our way along password[]
}
return (nUppers >= 2 && nLowers >= 2 && nDigits >= 2);
}
🌶
More experienced C programmers adopt
the C idiom that the integer value of 0 is equivalent to false,
and that any other value is equivalent to true.
For this reason, we often see code written without explicit tests
against the constant value of 0, and it's often easier to read aloud:
if(isupper( password[i] )) {
....
}
-
Write a function named my_strcmp() to determine if one string is (lexicographically, or alphabetically) less than, equal to, or greater than another string.
Your function should accept the two character arrays as its
arguments, and return either: -1 if the first string is less than the
second string, 0 if the two strings are equal, or 1 if the first string is greater than the second string.
#include <stdio.h>
#include <stdlib.h>
int my_strcmp(char str1[], char str2[])
{
int i = 0;
// TRAVERSE BOTH STRINGS WHILE THEIR CHARACTERS ARE EQUAL
while(str1[i] != '\0' && str2[i] != '\0' && str1[i] == str2[i]) {
++i; // advance our way along both strings
}
// NOTICE THAT THE DIFFERENCE BETWEEN TWO CHARACTERS IS AN integer
int difference = (str1[i] - str2[i]);
int result = 0;
if(difference < 0) {
result = -1;
}
else if(difference > 0) {
result = 1;
}
return result;
}
-
Variable-length-array version of haversine2.c .... to come.
-
A palindrome is a word that reads the same forwards as it does backwards.
For example, the words noon and madam are palindromes.
Write a function named isPalindrome() which determines if a string, supplied as the single character array argument to the function, is a palindrome or not, returning a Boolean.
Use the strlen() function to determine the length of the argument string.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
bool isPalindrome(char word[])
{
int left_index = 0; // index of the first character
int right_index = strlen(word) - 1; // index of the final character
// TRAVERSE word UNTIL THE INDICIES CROSS, OR CHARACTERS ARE DIFFERENT
while( left_index <= right_index && word[left_index] == word[right_index] ) {
++left_index;
--right_index;
}
// THE RESULT DEPENDS ON WHETHER THE CHARACTERS ARE STILL THE SAME
return (word[left_index] == word[right_index]);
}
-
Each call to the standard C11 function rand() returns a
different random integer.
Running the same program multiple times results in exactly the
same sequence of random integers.
While this is generally unexpected ("hey, they are not random"!),
it is very helpful for debugging programs without the randomness.
We can provide each execution with a more random sequence of random numbers
by seeding the random number generator with the C statement
srand( time(NULL) );
- Write a simple program to fill an array of 10 integers
with random numbers from rand().
Run the program several times, printing the contents of the array.
#include <stdlib.h>
int array[10];
for(int i=0 ; i<10 ; ++i) {
array[i] = rand();
}
for(int i=0 ; i<10 ; ++i) {
printf("%i ", array[i]);
}
printf("\n");
- Now, use srand() to seed the generation of random numbers.
Run the program several times, printing the contents of the array.
#include <stdlib.h>
#include <time.h>
// ADD A CALL TO srand( time(NULL) ); BEFORE THE ARRAY DEFINITION
- Extend your program by passing the initialised array to another
function which finds and prints the largest value in the array.
void find_largest(int size, int array[])
{
int largest = array[0];
for(int i=1 ; i<size ; ++i) {
if(array[i] > largest) {
largest = array[i];
}
}
printf("largest is %i\n", largest);
}
- Finally, extend the program's function to place the array's
largest value into the array's first element (index position 0),
"pushing" all other values down in the array
(0→1, 1→2, 2→3, and so on).
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void print_array(int size, int array[])
{
for(int i=0 ; i<size ; ++i) {
printf("%i ", array[i]);
}
printf("\n");
}
int find_largest(int size, int array[])
{
int position = 0;
int largest = array[position];
// FIND THE LARGEST ELEMENT AND ITS POSITION
for(int i=1 ; i<size ; ++i) {
if(array[i] > largest) {
position = i;
largest = array[position];
}
}
// SHUFFLE ELEMENTS LEFT OF THE LARGEST ONE POSITION RIGHT
for(int i=position ; i > 0 ; --i) { // right-to-left
array[i] = array[i-1];
}
// STORE THE LARGEST ELEMENT AT FRONT OF ARRAY
array[0] = largest;
return largest;
}
#define N 10
int main(int argc, char *argv[])
{
srand( time(NULL) );
int array[N];
for(int i=0 ; i<N ; ++i) {
array[i] = rand() % 100; // deal with smaller numbers
}
print_array(N, array);
printf("largest is %i\n", find_largest(N, array));
print_array(N, array);
return 0;
}
-
🌶
Write a function named replace() that replaces all instances of one string for another string in a third string.
For example:
prompt> ./replace red blue aredrobin
abluerobin
prompt> ./replace cat bison catocathartic
bisonobisonhartic
Ensure you have terminated your string correctly.
A reasonable prototype for the function is:
void replace( char oldword[], char newword[], char sentence[] );
Sample solution: replace.c
-
🌶
.... applications can determine information about a file's attributes using
the stat() system-call and the
struct stat structure.
Write a program which accepts a number of filenames on the command-line,
and prints (just as an integer)
the modification-time of each file.
Now, extend the program to also print each file's size (in bytes)
and the (more useful string)
modification-time of each file,
using the ctime() function.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
void attributes(char filename[])
{
.....
}
-
🌶
🌶
🌶
If you had to write some code that iterated through all the
possibilities for three variables in the range 0 to 10,
you would probably write code similar to:
for(int a = 0; a < 10; a=a+1) {
for(int b = 0; b < 10; b=b+1) {
for(int c = 0; c < 10; c=c+1) {
loop-body using a, b, and c;
}
}
}
But what if you had to extend this to 4, 5, or even 10+ "nested" loops?
Instead of further nesting more loops, it is possible to write
a function that acts as a "superloop", performing the equivalent
of n nested loops with just one loop.....
Two similar solutions:
nested1.c
and
nested2.c.
|