#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
/* ================================================================
Utility: Trim whitespace from both ends
================================================================ */
char *trim(char *s) {
while (isspace((unsigned char)*s)) s++;
if (*s == 0) return s;
char *end = s + strlen(s) - 1;
while (end > s && isspace((unsigned char)*end)) end--;
end[1] = '\0';
return s;
}
/* ================================================================
Utility: Create lowercase copy of a string
================================================================ */
char *to_lower_copy(const char *s) {
char *out = malloc(strlen(s) + 1);
for (int i = 0; s[i]; i++)
out[i] = tolower((unsigned char)s[i]);
out[strlen(s)] = '\0';
return out;
}
/* ================================================================
Replace all occurrences of delimiter d with sentinel
================================================================ */
void replace_delimiter(char *str, const char *d, char sentinel) {
size_t len = strlen(d);
char *p = strstr(str, d);
while (p) {
memmove(p + 1, p + len, strlen(p + len) + 1);
*p = sentinel;
p = strstr(str, d);
}
}
/* ================================================================
Normalize all delimiters into a single sentinel
================================================================ */
void normalize_delimiters(char *str, const char **delims, int count, char sentinel) {
for (int i = 0; i < count; i++)
replace_delimiter(str, delims[i], sentinel);
}
/* ================================================================
Split string by sentinel into tokens[]
================================================================ */
int split_by_sentinel(char *str, char sentinel, char **tokens, int max_tokens) {
int count = 0;
char *p = strtok(str, &sentinel);
while (p && count < max_tokens) {
tokens[count++] = p;
p = strtok(NULL, &sentinel);
}
return count;
}
/* ================================================================
Check if lowercase key exists in seen[]
================================================================ */
int is_duplicate(char **seen, int seen_count, const char *key) {
for (int i = 0; i < seen_count; i++)
if (strcmp(seen[i], key) == 0)
return 1;
return 0;
}
/* ================================================================
Remove duplicates (case-insensitive)
================================================================ */
int remove_duplicates(char **tokens, int token_count,
char **unique, int max_unique) {
char *seen[256] = { NULL };
int seen_count = 0;
int unique_count = 0;
for (int i = 0; i < token_count; i++) {
char *t = trim(tokens[i]);
if (*t == '\0') continue;
char *lower = to_lower_copy(t);
if (!is_duplicate(seen, seen_count, lower)) {
seen[seen_count++] = lower;
unique[unique_count++] = t;
} else {
free(lower);
}
}
return unique_count;
}
/* ================================================================
Join tokens with a delimiter
================================================================ */
void join_tokens(char **tokens, int count, const char *delim) {
for (int i = 0; i < count; i++) {
if (i > 0) printf("%s", delim);
printf("%s", tokens[i]);
}
printf("\n");
}
/* ================================================================
Main
================================================================ */
int main() {
char s[] =
"AAA | aaa , aAA * aaA | AAa | AAA | BBB | ccc ---- CCC | AAA ; aaa | bbb";
const char *delims[] = { " ", "|", ",", "*", "-", ";" };
int delim_count = sizeof(delims) / sizeof(delims[0]);
char sentinel = '\n';
/* Step 1: Normalize delimiters */
normalize_delimiters(s, delims, delim_count, sentinel);
/* Step 2: Split */
char *tokens[256] = { NULL };
int token_count = split_by_sentinel(s, sentinel, tokens, 256);
/* Step 3: Remove duplicates */
char *unique[256] = { NULL };
int unique_count = remove_duplicates(tokens, token_count, unique, 256);
/* Step 4: Output */
join_tokens(unique, unique_count, " | ");
return 0;
}
/*
run:
AAA | BBB | ccc
*/