As I criticised three of the other solutions up there I thought I'd stick my money where my mouth was and write one of me own:
int is_capital_letter( char to_test )
{
return to_test <= 'Z' && to_test >= 'A';
}
unsigned capital_letter_to_index( char letter )
{
return letter - 'A';
}
void mark_letter_to_be_eliminated(
char elimination_table[ 26 ],
char letter_to_eliminate )
{
elimination_table[ capital_letter_to_index( letter_to_eliminate ) ] = 1;
}
int is_letter_to_be_kept( const char elimination_table[ 26 ], char letter_to_test )
{
return !elimination_table[ capital_letter_to_index( letter_to_test ) ];
}
void build_elimination_table(
const char *to_eliminate,
char elimination_table[26] )
{
for( ; *to_eliminate; to_eliminate++ )
{
if( is_capital_letter( *to_eliminate ) )
{
mark_letter_to_be_eliminated( elimination_table, *to_eliminate );
}
}
}
void remove_duplicates_using_elimination_table(
const char *source,
const char elimination_table[26],
char *destination,
const char *end_of_destination )
{
while( *source && destination < end_of_destination )
{
if( is_capital_letter( *source ) )
{
if( is_letter_to_be_kept( elimination_table, *source ) )
{
*destination++ = *source;
}
source++;
}
}
*destination = 0;
}
void remove_duplicates(
const char *source,
const char *to_eliminate,
char *destination,
const char *end_of_destination )
{
char elimination_table[26] = { 0 };
build_elimination_table( to_eliminate, elimination_table );
remove_duplicates_using_elimination_table(
source,
elimination_table,
destination,
end_of_destination );
}
This lot works by creating a table of letters that are to be eliminated from the source string as it's copied to the destination string. The functions are all pretty safe and won't crash with invalid input they'll just not copy characters that aren't capital letters. And it'll still work if the source and destination are aliased.
Unlike some of the approaches above which have a complexity of O(n*m) where n is the size of the elimination string and m is the size of the string to be copied, this approach has a complexity of O(n+m).
Anyway you'd call it something like this:
char source[] = "HELLO";
char to_eliminate[] = "OPEN";
remove_duplicates( source, to_eliminate, source, source + sizeof source );
which will show it still works when source and destination refer to the same memory.
Final points: it's broken up into so many functions because...
- I have trouble reading functions with more than one loop or one conditional
- It's easier to unit test small functions