Welcome to collectivesolver - Programming & Software Q&A with code examples. A website with trusted programming answers. All programs are tested and work.

Contact: aviboots(AT)netvision.net.il

Semrush - keyword research tool

Turn ChatGPT, Claude, Gemini, And CoPilot Into Your Personal Assistant, Business Coach, Content Creator, And More

AFFILIATE MARKETING Your all-in-one performance engine Manage affiliates, creators, and customer referrals in one unified platform—turning every partnership into measurable growth
Secure & Reliable Web Hosting, Free Domain, Free SSL, 1-Click WordPress Install, Expert 24/7 Support

Boost your online presence with premium web hosting and servers

Disclosure: My content contains affiliate links.

42,690 questions

55,449 answers

573 users

How to remove duplicate case‑insensitive words separated by multiple delimiters from a string in C

2 Answers

0 votes
#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

*/

 



answered Aug 1 by avibootz
edited Aug 1 by avibootz
0 votes
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

/* ================================================================
   Dynamic array of char* (tokens)
   ================================================================ */
typedef struct {
    char **items;
    int count;
    int capacity;
} TokenArray;

/* Initialize dynamic array */
void ta_init(TokenArray *ta) {
    ta->count = 0;
    ta->capacity = 8;
    ta->items = malloc(sizeof(char*) * ta->capacity);
}

/* Push string pointer into dynamic array */
void ta_push(TokenArray *ta, char *s) {
    if (ta->count == ta->capacity) {
        ta->capacity *= 2;
        ta->items = realloc(ta->items, sizeof(char*) * ta->capacity);
    }
    ta->items[ta->count++] = s;
}

/* Free dynamic array (not strings inside) */
void ta_free(TokenArray *ta) {
    free(ta->items);
}

/* ================================================================
   Trim whitespace
   ================================================================ */
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;
}

/* ================================================================
   Lowercase copy
   ================================================================ */
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 delimiter 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
   ================================================================ */
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 by sentinel into dynamic array
   ================================================================ */
void split_by_sentinel(char *str, char sentinel, TokenArray *tokens) {
    ta_init(tokens);

    char *p = strtok(str, &sentinel);
    while (p) {
        ta_push(tokens, p);
        p = strtok(NULL, &sentinel);
    }
}

/* ================================================================
   Check duplicate (case-insensitive)
   ================================================================ */
int is_duplicate(TokenArray *seen, const char *key) {
    for (int i = 0; i < seen->count; i++)
        if (strcmp(seen->items[i], key) == 0)
            return 1;
            
    return 0;
}

/* ================================================================
   Remove duplicates using dynamic arrays
   ================================================================ */
void remove_duplicates(TokenArray *tokens, TokenArray *unique) {
    TokenArray seen;
    ta_init(&seen);
    ta_init(unique);

    for (int i = 0; i < tokens->count; i++) {
        char *t = trim(tokens->items[i]);
        if (*t == '\0') continue;

        char *lower = to_lower_copy(t);

        if (!is_duplicate(&seen, lower)) {
            ta_push(&seen, lower);
            ta_push(unique, t);
        } else {
            free(lower);
        }
    }
}

/* ================================================================
   Join tokens
   ================================================================ */
void join_tokens(TokenArray *tokens, const char *delim) {
    for (int i = 0; i < tokens->count; i++) {
        if (i > 0) printf("%s", delim);
        printf("%s", tokens->items[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';

    normalize_delimiters(s, delims, delim_count, sentinel);

    TokenArray tokens;
    split_by_sentinel(s, sentinel, &tokens);

    TokenArray unique;
    remove_duplicates(&tokens, &unique);

    join_tokens(&unique, " | ");

    ta_free(&tokens);
    ta_free(&unique);

    return 0;
}


/*
run:

AAA | BBB | ccc

*/

 



answered Aug 1 by avibootz

Related questions

...