#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <wctype.h>
#include <locale.h>
/*
This program removes duplicate words from free text containing Unicode characters.
It uses:
- setlocale() to enable Unicode behavior
- mbstowcs / wcstombs for UTF‑8 ↔ wide conversion
- iswpunct / towlower for Unicode-aware normalization
- dynamic arrays for storing unique words
- O(n) duplicate removal preserving first occurrence order
*/
// Convert UTF‑8 → wide string
wchar_t *utf8_to_wide(const char *input) {
size_t len = mbstowcs(NULL, input, 0);
wchar_t *out = malloc((len + 1) * sizeof(wchar_t));
mbstowcs(out, input, len + 1);
return out;
}
// Convert wide string → UTF‑8
char *wide_to_utf8(const wchar_t *input) {
size_t len = wcstombs(NULL, input, 0);
char *out = malloc(len + 1);
wcstombs(out, input, len + 1);
return out;
}
// Normalize a word: remove punctuation + lowercase
wchar_t *normalize_word(const wchar_t *word) {
size_t len = wcslen(word);
wchar_t *out = malloc((len + 1) * sizeof(wchar_t));
size_t j = 0;
for (size_t i = 0; i < len; i++) {
wchar_t c = word[i];
if (iswpunct(c) || iswspace(c))
continue;
out[j++] = towlower(c);
}
out[j] = L'\0';
return out;
}
// Check if a word already exists
int exists(wchar_t **list, int count, const wchar_t *word) {
for (int i = 0; i < count; i++) {
if (wcscmp(list[i], word) == 0)
return 1;
}
return 0;
}
// Remove duplicates from wide string
wchar_t **remove_duplicates(const wchar_t *input, int *out_count) {
wchar_t *buffer = malloc((wcslen(input) + 1) * sizeof(wchar_t));
wcscpy(buffer, input);
wchar_t **unique = NULL;
int count = 0;
wchar_t *token = wcstok(buffer, L" \t\n\r", &buffer);
while (token) {
wchar_t *norm = normalize_word(token);
if (wcslen(norm) > 0 && !exists(unique, count, norm)) {
unique = realloc(unique, sizeof(wchar_t*) * (count + 1));
unique[count++] = norm;
} else {
free(norm);
}
token = wcstok(NULL, L" \t\n\r", &buffer);
}
*out_count = count;
return unique;
}
int main() {
setlocale(LC_ALL, ""); // enable Unicode behavior
const char *input_utf8 =
"Hello! こんにちは, ,hello こんにちは Bună ziua; Γεια σας Bună ziua *HELLO* Γεια σας";
// Convert to wide string
wchar_t *input = utf8_to_wide(input_utf8);
int count = 0;
wchar_t **unique = remove_duplicates(input, &count);
// Print results in UTF‑8
for (int i = 0; i < count; i++) {
char *utf8 = wide_to_utf8(unique[i]);
printf("%s", utf8);
if (i + 1 < count) printf(" ");
free(utf8);
}
printf("\n");
// Cleanup
for (int i = 0; i < count; i++)
free(unique[i]);
free(unique);
free(input);
return 0;
}
/*
run:
hello こんにちは bună ziua γεια σας
*/