Puzzles S11 ... S21

Part S — String and Character Problems

These puzzles involve characters and null-terminated strings.


Puzzle S11 — Are two strings equal?

[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;
}


Puzzle S12 — String compare

[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.


Puzzle S13 — Starts with

[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;
}


Puzzle S14 — Ends with

[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.


Puzzle S15 — Find first substring

[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().


Puzzle S16 — Find the first character in one string that is also in another

[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> .


Puzzle S17 — Determine if every character in one string is also in another

[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;


Puzzle S18 — Replace every instance of one character with another

[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') changes "applecart" into "upplecurt".

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;
}


Puzzle S19 — Delete the first N characters from a string

[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;
}


Puzzle S20 — Delete each instance of a particular character from a string

[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.


— Return to the main contents page