XXXX redacted: Difference between revisions
Content added Content deleted
(Added Swift solution) |
(Added C solution) |
||
Line 284: | Line 284: | ||
return redactor's outputText |
return redactor's outputText |
||
end redact</lang> |
end redact</lang> |
||
=={{header|C}}== |
|||
This is a very basic ASCII-only implementation, no Unicode or regular expressions. |
|||
<lang c>#include <ctype.h> |
|||
#include <stdbool.h> |
|||
#include <stdio.h> |
|||
#include <string.h> |
|||
typedef enum { |
|||
whole_word = 1, |
|||
overkill = 2, |
|||
case_insensitive = 4 |
|||
} redact_options; |
|||
bool is_word_char(char ch) { |
|||
return ch == '-' || isalpha((unsigned char)ch); |
|||
} |
|||
// Performs in-place redaction of the target with the specified options. |
|||
void redact(char* text, const char* target, redact_options options) { |
|||
size_t target_length = strlen(target); |
|||
char* start = text; |
|||
char* end = text + strlen(text); |
|||
while (start < end) { |
|||
// NB: strcasestr is a non-standard extension. It's similar to the |
|||
// standard strstr function, but case-insensitive. |
|||
char* str = (options & case_insensitive) ? strcasestr(start, target) |
|||
: strstr(start, target); |
|||
if (str == NULL) |
|||
break; |
|||
char* word_start = str; |
|||
char* word_end = str + target_length; |
|||
if (options & (overkill | whole_word)) { |
|||
while (word_start > start && is_word_char(*(word_start - 1))) |
|||
--word_start; |
|||
while (word_end < end && is_word_char(*word_end)) |
|||
++word_end; |
|||
} |
|||
if (!(options & whole_word) || |
|||
(word_start == str && word_end == str + target_length)) |
|||
memset(word_start, 'X', word_end - word_start); |
|||
start = word_end; |
|||
} |
|||
} |
|||
void do_basic_test(const char* target, redact_options options) { |
|||
char text[] = "Tom? Toms bottom tomato is in his stomach while playing the " |
|||
"\"Tom-tom\" brand tom-toms. That's so tom."; |
|||
redact(text, target, options); |
|||
printf("[%c|%c|%c]: %s\n", (options & whole_word) ? 'w' : 'p', |
|||
(options & case_insensitive) ? 'i' : 's', |
|||
(options & overkill) ? 'o' : 'n', text); |
|||
} |
|||
void do_basic_tests(const char* target) { |
|||
printf("Redact '%s':\n", target); |
|||
do_basic_test(target, whole_word); |
|||
do_basic_test(target, whole_word | case_insensitive); |
|||
do_basic_test(target, 0); |
|||
do_basic_test(target, case_insensitive); |
|||
do_basic_test(target, overkill); |
|||
do_basic_test(target, case_insensitive | overkill); |
|||
} |
|||
int main() { |
|||
do_basic_tests("Tom"); |
|||
printf("\n"); |
|||
do_basic_tests("tom"); |
|||
return 0; |
|||
}</lang> |
|||
{{out}} |
|||
<pre> |
|||
Redact 'Tom': |
|||
[w|s|n]: XXX? Toms bottom tomato is in his stomach while playing the "Tom-tom" brand tom-toms. That's so tom. |
|||
[w|i|n]: XXX? Toms bottom tomato is in his stomach while playing the "Tom-tom" brand tom-toms. That's so XXX. |
|||
[p|s|n]: XXX? XXXs bottom tomato is in his stomach while playing the "XXX-tom" brand tom-toms. That's so tom. |
|||
[p|i|n]: XXX? XXXs botXXX XXXato is in his sXXXach while playing the "XXX-XXX" brand XXX-XXXs. That's so XXX. |
|||
[p|s|o]: XXX? XXXX bottom tomato is in his stomach while playing the "XXXXXXX" brand tom-toms. That's so tom. |
|||
[p|i|o]: XXX? XXXX XXXXXX XXXXXX is in his XXXXXXX while playing the "XXXXXXX" brand XXXXXXXX. That's so XXX. |
|||
Redact 'tom': |
|||
[w|s|n]: Tom? Toms bottom tomato is in his stomach while playing the "Tom-tom" brand tom-toms. That's so XXX. |
|||
[w|i|n]: XXX? Toms bottom tomato is in his stomach while playing the "Tom-tom" brand tom-toms. That's so XXX. |
|||
[p|s|n]: Tom? Toms botXXX XXXato is in his sXXXach while playing the "Tom-XXX" brand XXX-XXXs. That's so XXX. |
|||
[p|i|n]: XXX? XXXs botXXX XXXato is in his sXXXach while playing the "XXX-XXX" brand XXX-XXXs. That's so XXX. |
|||
[p|s|o]: Tom? Toms XXXXXX XXXXXX is in his XXXXXXX while playing the "XXXXXXX" brand XXXXXXXX. That's so XXX. |
|||
[p|i|o]: XXX? XXXX XXXXXX XXXXXX is in his XXXXXXX while playing the "XXXXXXX" brand XXXXXXXX. That's so XXX. |
|||
</pre> |
|||
=={{header|Go}}== |
=={{header|Go}}== |