These puzzles involve characters and null-terminated strings.
[E-4]
Write a function that determines if two strings
are equal. Two strings are equal if the strings are of equal length and have
the same characters at the same locations. Two empty strings are equal. Here
is a prototype for the function:
int areEqual( char const *left, char const *right );
The function returns 1 if the strings are equal, and zero otherwise. Warning:
usually in C you would use the function strcmp()
to test
for equality of strings. That function returns 0 when strings are equal. Here
is a skeleton of a testing program Finish it by completing the function.
/* Puzzle S11 --are two strings equal? */ #include <stdio.h> #include <stdlib.h> int areEqual( char const *left, char const *right ) { } int main(int argc, char *argv[]) { char *trials[][2] = { {"a", "a"}, {"a", "f"}, {"abc", "abc"}, {"abc", "def"}, {"abcdef", "abcdef"}, {"abcdef", "aaaaaa"}, {"abcdeff", "abcdef"}, {"abcdef", "xabcdef"}, {"xabcdef", "abcdef"}, {"abcdef", "rats"}, {"abbccf", "cc"}, {"abcdefg", "g"}, {"apple", ""}, {"", "apple"}, {"",""}, {"green", "green"}, {"ASBC", "ASBC"}, {" ", " "}, {"12345", "12345"}, {"++-!@#", "++-!@#"}, {"tab\ttab", "tab\ttab"}, }; int j; for ( j=0; j<sizeof(trials)/sizeof(trials[0]); j++ ) { printf("%s\t%s\t", trials[j][0], trials[j][1] ); if ( areEqual( trials[j][0], trials[j][1] ) ) printf("are equal\n"); else printf("are not equal\n"); } system("PAUSE"); // Remove this if you want return 0; }
[E-4]
Write a function stringCompare(char
const *left, char const *right )
that compares two strings. If the strings
are equal, then the function returns 0. If the strings are not equal, return
a negative value if the left string is shorter than or occurs alphabetically
before the right string. Otherwise, return a positive value.
Value of stringCompare( left, right ) | |
left equal to right | 0 |
left less than right | negative |
left greater than right | positive |
The value that is returned is determined by the first character position at which the strings differ. Say that the character at this position in the left string is L and the character at this position in the right string is R. Then the function returns (L-R). Here is a testing program:
/* Puzzle S12 -- string compare*/ #include <stdio.h> #include <stdlib.h> int stringCompare( char const *left, char const *right ) { } int main(int argc, char *argv[]) { char *trials[][2] = { {"a", "a"}, {"a", "f"}, {"abc", "abc"}, {"abc", "def"}, {"abcdef", "abcdef"}, {"abcdef", "aaaaaa"}, {"abcdeff", "abcdef"}, {"abcdef", "xabcdef"}, {"xabcdef", "abcdef"}, {"abcdef", "rats"}, {"abbccf", "cc"}, {"abcdefg", "g"}, {"apple", ""}, {"", "apple"}, {"",""}, {"green", "green"}, {"ASBC", "ASBC"}, {" ", " "}, {"12345", "12345"}, {"++-!@#", "++-!@#"}, {"tab\ttab", "tab\ttab"} }; int j; for ( j=0; j<sizeof(trials)/sizeof(trials[0]); j++ ) { int result = stringCompare( trials[j][0], trials[j][1] ) ; if ( result==0 ) printf("%s\t==\t%s\n", trials[j][0], trials[j][1] ); else if ( result<0) printf("%s\t<\t%s\n", trials[j][0], trials[j][1] ); else printf("%s\t>\t%s\n", trials[j][0], trials[j][1] ); } system("PAUSE"); return 0; }
Write this function by making a single character change to the answer for puzzle S11.
Note: this function is similar to the function strcmp()
described in <string.h>
.
However,
strcmp()
is not required to return any particular positive
or negative value for dissimilar strings.
In professional-level code,
use the standard function rather than your own.
[E-4]
Write a function that determines if one string
starts with all the characters of another. For example, "applecart"
starts with "apple", but "applecart" does not start with
"apples". Every string starts with the null string. Here is a testing
program:
/* Puzzle S13 -- starts with */ #include <stdio.h> #include <stdlib.h> int startsWith( char const *bigString, char const *start ) { } int main(int argc, char *argv[]) { char *trials[][2] = { {"abcdef", "a"}, {"abcdef", "x"}, {"abcdef", "ab"}, {"abcdef", "abx"}, {"abcdef", "abcdef"}, {"abcdef", "f"}, {"abcdef", "abcdefx"}, {"abcdef", "abcdefxyz"}, {"abcdef", "fooey"}, {"abcdef", "rats"}, {"aaaaaa", "a"}, {"abcdefg", "g"}, {"applecart", "apple"}, {"green", "apple"}, {"apple", ""}, {"", "rats"}, {"",""} }; int j; for ( j=0; j<sizeof(trials)/sizeof(trials[0]); j++ ) { int result = startsWith( trials[j][0], trials[j][1] ) ; if ( result ) printf("%s\t starts with\t%s\n", trials[j][0], trials[j][1] ); else printf("%s\t does not start with\t%s\n", trials[j][0], trials[j][1] ); } system("PAUSE"); return 0; }
[H-11]
Write a function that determines if one
string ends with all the characters of another. For example, "applecart"
ends with "cart", but "applecart" does not end with "bart".
Every string ends with the null string. Here is a testing program:
/* Puzzle S14 -- ends with */ #include <stdio.h> #include <stdlib.h> int endsWith( char const *bigString, char const *endString ) { } int main(int argc, char *argv[]) { char *trials[][2] = { {"abcdef", "f"}, {"abcdef", "ef"}, {"abcdef", "def"}, {"abcdef", "cdef"}, {"abcdef", "abcdef"}, {"abcdef", "a"}, {"abcdef", "abc"}, {"abcdef", "xabcdef"}, {"abcdef", "xyzabcdef"}, {"abcdef", "rats"}, {"abbccddeef", "cc"}, {"abcdefg", "g"}, {"applecart", "cart"}, {"green", "apple"}, {"apple", ""}, {"", "rats"}, {"",""} }; int j; for ( j=0; j<sizeof(trials)/sizeof(trials[0]); j++ ) { int result = endsWith( trials[j][0], trials[j][1] ) ; if ( result ) printf("%s\t ends with \t%s\n", trials[j][0], trials[j][1] ); else printf("%s\t does not end with\t%s\n", trials[j][0], trials[j][1] ); } system("PAUSE"); return 0; }
Note: This function is much harder to write than startsWith()
.
One difficulty is that the comparison is made starting at the end of both strings
and working forward, but there is no null byte at the beginning of the strings
that say where they start.
[H-8]
Write function that finds the first occurance
of a substring in another (usually larger) source string. If the substring is
found, a pointer to the beginning of the first occurance in the source string
is returned. If the substring is not found, NULL is returned. Here is a testing
program:
/* Puzzle S15 -- Find Substring */ #include <stdio.h> #include <stdlib.h> int startsWith( char const *bigString, char const *start ) { } char *findSubstring( char const *source, char const *sub ) { } int main(int argc, char *argv[]) { char *trials[][2] = { {"abcdef", "a"}, {"abcdef", "abc"}, {"abcdef", "d"}, {"abcdef", "def"}, {"abcdef", "f"}, {"abcdef", "xyz"}, {"abcdef", "axx"}, {"abcdef", "abcdefg"}, {"abcdef", "rats"}, {"abbccddeef", "cc"}, {"abcdefg", "g"}, {"applecart", "c"}, {"green", "apple"}, {"apple", ""}, {"", "rats"}, {"",""} }; int j; char *loc; for ( j=0; j<sizeof(trials)/sizeof(trials[0]); j++ ) { loc = findSubstring( trials[j][0], trials[j][1] ); if ( loc ) printf("%s : %s : %s\n", trials[j][0], trials[j][1], loc ); else printf("%s : %s : %s\n", trials[j][0], trials[j][1], "not found" ); } system("PAUSE"); return 0;
It will be useful to write this function using your startsWith()
function.
Note: this function is similar to the standard function strstr()
.
[H-5]
Write function that returns a pointer to
the first character in a string that is a member of a second string. Here is
a prototype for the function:
int findCstring( char const *str, char const *set);
The function returns an index to the first character in str
that is
also in set
. For example,
int findCstring( "spaceship", "bcde" )
returns a the value 3, which is the index of the 'c' in the first string. Remember that indexes for strings start at zero. If none of the characters in set are found in the string, return -1. The set can have duplicated characters. If the set is empty, return -1. If the string is empty, return -1. Here is a testing program:
/* Puzzle S16 -- First character in one string that is also in another */ #include <stdio.h> #include <stdlib.h> /* Find the first character in *str that is also in *set. */ /* Return its index */ int findCstring( char const *str, char const *set) { } int main(int argc, char *argv[]) { char *trials[][2] = { {"abcdef", "a"}, {"abcdef", "xyza"}, {"abcdef", "f"}, {"abcdef", "zxyf"}, {"abcdef", "zxfy"}, {"abcdef", "c"}, {"abcdef", "xyzc"}, {"abcdef", "cxyz"}, {"abcdef", "xxcyz"}, {"abbccddeef", "xyzfzz"}, {"abcdefg", "gfedec"}, {"small", "xxxxxxxxxxxxmxxxxxxxxx"}, {"green", "apple"}, {"apple", ""}, {"", "rats"}, {"",""} }; int j, loc ; for ( j=0; j<sizeof(trials)/sizeof(trials[0]); j++ ) { loc = findCstring( trials[j][0], trials[j][1] ); if ( loc != -1 ) printf("Found %c from %s at index %d in %s\n", trials[j][0][loc], trials[j][1], loc, trials[j][0] ); else printf("Found no character from %s in %s\n", trials[j][1], trials[j][0] ); } system("PAUSE"); return 0;
This function is similar to the standard function strcspn()
described
in <strings.h>
.
[H-5]
Write function stringSubset(char *sub,
char *set)
that returns 1 if every character in the string *sub
is also contained in the string *set
; otherwise it returns 0. Every
char in *sub
must also be in *set
, but *set
may have additional characters. Both strings may have repeated characters. If
both strings are empty, or *sub
is empty, return 1. If only *set
is empty, return 0.
Here is a testing program:
/* Puzzle S17 -- Determine if every character in one string is also in another */ #include <stdio.h> #include <stdlib.h> /* return 1 if every character in the string *sub is also contained in the string *set*/ int stringSubset( char const *sub, char const *set) { } int main(int argc, char *argv[]) { char *trials[][2] = { {"a","a"}, {"a","ab"}, {"a","aaa"}, {"ab","ab"}, {"aaa","a"}, {"abc","abc"}, {"a","xyza"}, {"a","xyzaxyz"}, {"x","a"}, {"x","abc"}, {"ababab","abcxyz"}, {"aaabbbcccaaa","abc"}, {"aabbaabbaax","abc"}, {"xaabbaabbaa","abc"}, {"aabbxaabbaa","abc"}, {"aabbxaabbaa","abc"}, {"aabbxaaxbbaa","abc"}, {"empty set",""}, {"","abc"}, {"",""} }; int j, loc ; for ( j=0; j<sizeof(trials)/sizeof(trials[0]); j++ ) { if ( stringSubset( trials[j][0], trials[j][1] ) ) printf("%s \tcontains only characters from %s\n", trials[j][0], trials[j][1] ); else printf("%s \tcontains extra characters than %s\n", trials[j][0], trials[j][1] ); } system("PAUSE"); return 0;
[E-4]
Write a function that replaces every instance
of a particular character in a string with another character. The prototype
of the function is:
void replace( char *str, char old, char new );
Replace every character old
in str
with character
new
. For example,
replace( "applecart", 'a', 'u')
Here is a testing function:
#include <stdio.h> #include <stdlib.h> void replace( char *str, char old, char new ) { } struct test { char str[50]; char old; char new; }; int main(int argc, char *argv[]) { struct test trials[] = { {"aaa", 'a', 'b'}, {"aaa", 'x', 'b'}, {"abc", 'a', 'b'}, {"bca", 'a', 'b'}, {"bca", 'a', 'a'}, {"aaabbbaaa", 'a', 'b'}, {"xaxaxa", 'a', 'b'}, {"XAAxaa", 'a', '*'}, {"applecart", 'a', 'u'}, {"blue berry", 'e', 'o'} }; int j; for ( j=0; j < sizeof(trials)/sizeof(struct test); j++ ) { printf( "%s\t", trials[j].str ); replace( trials[j].str, trials[j].old, trials[j].new ); printf( "%c\t%c\t%s\n", trials[j].old, trials[j].new, trials[j].str ); } system("PAUSE"); return 0; }
[M-10]
Write function that shortens a string by
removing its first N characters. Do this by sliding the characters starting
at position N left by N positions.
When N is bigger than the length of the string, make the string the empty string. If N is negative or zero, do nothing. Here is a testing function:
#include <stdio.h> #include <stdlib.h> void deleteFirstN( char *str, int N ) { } struct test { char str[50]; char N; }; int main(int argc, char *argv[]) { struct test trials[] = { {"blue berry", 5}, {"123456789", 0}, {"123456789", 1}, {"123456789", 2}, {"123456789", 3}, {"123456789", 4}, {"123456789", 7}, {"123456789", 8}, {"123456789", 9}, {"123456789", -1}, {"123456789", -8}, {"1234", 3}, {"123", 3}, {"12", 3}, {"1", 3}, {"", 3}, }; int j; for ( j=0; j < sizeof(trials)/sizeof(struct test); j++ ) { printf( "\"%s\" - %d =\t", trials[j].str, trials[j].N ); deleteFirstN( trials[j].str, trials[j].N ); printf( "\"%s\"\n", trials[j].str ); } system("PAUSE"); return 0; }
[H-10]
Write function that shortens a string by
removing all instances of a particular character from a string. The null that
terminates the string is placed after its new last character. The prototype
of the function is:
void deleteCh( char *str, char ch );
Remove every ch
from str
.
For example , deleteCh( "applecart", 'a')
changes "applecart" into
"pplecrt". Here is a testing function:
#include <stdio.h> #include <stdlib.h> void deleteCh( char *str, char ch ) { } struct test { char str[50]; char ch; }; int main(int argc, char *argv[]) { struct test trials[] = { {"aXX", 'a'}, {"XXa", 'a'}, {"aXX", 'x'}, {"a", 'a'}, {"aa", 'a'}, {"aaa", 'a'}, {"bca", 'a'}, {"bcaa", 'a'}, {"aaabbbaaa", 'a'}, {"xaxaxa", 'a'}, {"XAAxaa", 'a'}, {"applecart", 'a'}, {"blue berry", 'e'} }; int j; for ( j=0; j<sizeof(trials)/sizeof(struct test); j++ ) { printf( "%s\t", trials[j].str ); deleteCh( trials[j].str, trials[j].ch ); printf( "%c\t%s\n", trials[j].ch, trials[j].str ); } system("PAUSE"); return 0; }
Attempt to write this function without using a second string as a buffer or
by using malloc()
to get a buffer.