I'm not sure what the type of the elements in the array is, but let's assume it's some type that C can "natively" compare. Then the conceptually simple solution is to sort the array, and the print it skipping duplicates. Sorting will ensure that the duplicates are adjacent. This approach will perform well in most circumstances.
First, let's set up some helper functions specific to the element type. You could remove the assign function if you only want to deal with char type, but it'll be inlined by the compiler anyway.
#include <stdlib.h>
#include <stdio.h>
// You can adapt the element type per your requirements
typedef char ElementType;
// This function assigns the source value to the destination:
// it does what *dst = *src would do.
static inline void assign(void *dst, const void *src)
{
*(ElementType*)dst = *(const ElementType*)src;
}
// This is the "spaceship" comparison operator (<=> in C++) that
// merges less-than, equal, and more-than comparisons into one.
int compare(const void *l, const void *r)
{
const ElementType *L = l;
const ElementType *R = r;
if (*L < *R) return -1;
if (*L > *R) return 1;
return 0;
}
void print_element(const ElementType *el) { printf("%c", *el); }
Since we plan to sort the array, we need to copy it first - after all, a "printer" for an array shouldn't be modifying it. Such modifications are OK in tiny programs, but are just a bad habit, since if you look at the name of the function like print_unique, nothing hints you that it would modify the data it's supposed to print: that's not how printing normally acts. It'd be unexpected and very error prone.
The copy operation could be skipped if it's OK to modify the source array: its elements would need to be non-const then, and the print_unique function name would need to be changed to something like sort_and_print_unique.
ElementType *copy_array(const ElementType *src, const int count)
{
ElementType *copy = malloc(sizeof(ElementType) * count);
if (!copy) abort;
for (int i = 0; i < count; ++i)
assign(copy + i, src + i);
return copy;
}
And now the unique element printer, and a test with the data you provided:
void print_unique(const ElementType *data, int const count)
{
ElementType *copy = copy_array(data, count);
qsort(copy, count, sizeof(ElementType), compare);
printf("[");
for (int i = 0; i < count; ++i) {
if (i == 0 || compare(copy+i, copy+i-1) != 0) {
if (i != 0) printf(" ");
print_element(copy+i);
}
}
printf("]\n");
}
int main() {
const char array[] = "abcdaabdcc";
print_unique(array, sizeof(array)/sizeof(*array) - 1);
}
Output: [a b c d]
The alternate, modifying implementation I mentioned above would be:
void sort_and_print_unique(ElementType *data, int const count)
{
qsort(data, count, sizeof(ElementType), compare);
printf("[");
for (int i = 0; i < count; ++i) {
if (i == 0 || compare(data+i, data+i-1) != 0) {
if (i != 0) printf(" ");
print_element(data+i);
}
}
printf("]\n");
}
int main() {
char array[] = "abcdaabdcc"; // note absence of const!
sort_and_print_unique(array, sizeof(array)/sizeof(*array) - 1);
}