IT-Berater Forum

IT-Berater: Theo Gottwald (IT-Consultant) => AI / ChatGPT / Claude AI / LM Studio / AGI => Topic started by: Stan Duraham on June 06, 2026, 11:04:43 PM

Title: DeepSeek do C right
Post by: Stan Duraham on June 06, 2026, 11:04:43 PM
Built a dynamic long long array that grows and shrinks as needed. Supports quick sort and binary search, insert and delete. To/From file.

All from one script.
The hardest part; it built a complete test application.

Then had it convert that file to all; integer, unsigned inter and floating-point type arrays. Along with test apps.

Then had it build a dynamic string array from one script, along with complete test app. Still need to add split and join, and to/from text file.

All sort and binary search operations can use a custom or default callback.

This is just with the free online version, do have to open an account. Did have to feed a few errors back in, particularly on the floats. Ony takes a few seconds. Took a long time to build the scripts.

Goal, make C more BASIC like. String manipulation is going to be tough.

/*
 * StrArr.h - Dynamic 8-bit string array
 *
 * This header provides a complete implementation of a dynamic array
 * that stores pointers to null-terminated strings.
 *
 * Design:
 * - Uses long long for indices and counts
 * - Stores allocated strings in data array
 * - Empty strings ("") are stored as NULL pointer (0)
 * - All functions begin with 'StrArr' prefix to avoid conflicts
 */

#ifndef STRARR_H
#define STRARR_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

/* Default compare callback - ASCII case sensitive */
int StrArrDefaultCompare(const char* a, const char* b);

/* Case insensitive compare callback */
int StrArrCaseInsensitiveCompare(const char* a, const char* b);

typedef struct {
    char** data;        /* Array of string pointers */
    long long count;    /* Number of strings currently stored */
    long long capacity; /* Allocated capacity of data array */
} StrArrT;

/* Helper function declarations */
static int StrArrCompareWrapper(const void* a, const void* b);

/* Compare callback type */
typedef int (*StrArrCompareFunc)(const char*, const char*);

/* Global callback for qsort */
static StrArrCompareFunc g_compare_callback = NULL;

/* Wrapper for qsort */
static int StrArrCompareWrapper(const void* a, const void* b) {
    const char* str_a = *(const char**)a;
    const char* str_b = *(const char**)b;

    /* Handle NULL pointers (empty strings) */
    if (str_a == NULL) str_a = "";
    if (str_b == NULL) str_b = "";

    if (g_compare_callback) {
        return g_compare_callback(str_a, str_b);
    }
    return StrArrDefaultCompare(str_a, str_b);
}

/* Initialize a string array structure */
void StrArrInit(StrArrT* arr) {
    if (arr == NULL) return;
    arr->data = NULL;
    arr->count = 0;
    arr->capacity = 0;
}

/* Free all memory used by the array and reset structure */
void StrArrFinal(StrArrT* arr) {
    long long i;

    if (arr == NULL) return;

    /* Free each allocated string */
    if (arr->data != NULL) {
        for (i = 0; i < arr->count; i++) {
            if (arr->data[i] != NULL) {
                free(arr->data[i]);
            }
        }
        free(arr->data);
    }

    arr->data = NULL;
    arr->count = 0;
    arr->capacity = 0;
}

/* Cleanup callback for when StrArrT is stored as handle in other structures */
void StrArrFinalCB(void* arr_ptr) {
    StrArrT* arr = (StrArrT*)arr_ptr;
    if (arr == NULL) return;

    /* Free internal data but not the structure itself */
    if (arr->data != NULL) {
        long long i;
        for (i = 0; i < arr->count; i++) {
            if (arr->data[i] != NULL) {
                free(arr->data[i]);
            }
        }
        free(arr->data);
    }

    arr->data = NULL;
    arr->count = 0;
    arr->capacity = 0;
}

/* Clear all strings from array (same as StrArrFinal) */
void StrArrClear(StrArrT* arr) {
    StrArrFinal(arr);
}

/* Ensure enough capacity for additional items */
int StrArrGrow(StrArrT* arr, long long items) {
    long long new_capacity;
    char** new_data;

    if (arr == NULL) return 0;

    if (arr->capacity >= arr->count + items) {
        return 1; /* Already enough room */
    }

    /* Calculate new capacity: double the required size or at least 2*(count+items) */
    new_capacity = 2 * (arr->count + items);
    if (new_capacity < 4) new_capacity = 4;

    new_data = (char**)realloc(arr->data, new_capacity * sizeof(char*));
    if (new_data == NULL) return 0;

    arr->data = new_data;
    arr->capacity = new_capacity;
    return 1;
}

/* Shrink array to exactly fit current count */
void StrArrShrink(StrArrT* arr) {
    char** new_data;

    if (arr == NULL || arr->data == NULL) return;
    if (arr->capacity <= arr->count) return;

    if (arr->count == 0) {
        free(arr->data);
        arr->data = NULL;
        arr->capacity = 0;
        return;
    }

    new_data = (char**)realloc(arr->data, arr->count * sizeof(char*));
    if (new_data != NULL) {
        arr->data = new_data;
        arr->capacity = arr->count;
    }
}

/* Return current number of strings */
long long StrArrGetCount(StrArrT* arr) {
    if (arr == NULL) return 0;
    return arr->count;
}

/* Set array size, growing or shrinking as needed */
int StrArrSetCount(StrArrT* arr, long long items) {
    long long i;

    if (arr == NULL) return 0;
    if (items < 0) return 0;

    if (items > arr->capacity) {
        if (!StrArrGrow(arr, items - arr->count)) {
            return 0;
        }
    }

    /* If shrinking, free removed strings */
    if (items < arr->count) {
        for (i = items; i < arr->count; i++) {
            if (arr->data[i] != NULL) {
                free(arr->data[i]);
            }
        }
    }

    /* Initialize new elements to NULL */
    for (i = arr->count; i < items; i++) {
        arr->data[i] = NULL;
    }

    arr->count = items;
    return 1;
}

/* Get string at index - always returns a valid string (never NULL) */
const char* StrArrGet(StrArrT* arr, long long index) {
    if (arr == NULL) return "";
    if (index < 0 || index >= arr->count) return "";
    if (arr->data[index] == NULL) return "";
    return arr->data[index];
}

/* Set string at index, freeing old string */
int StrArrSet(StrArrT* arr, long long index, const char* value) {
    char* new_str;

    if (arr == NULL) return 0;
    if (index < 0 || index >= arr->count) return 0;

    /* Free existing string if any */
    if (arr->data[index] != NULL) {
        free(arr->data[index]);
    }

    /* Store empty string as NULL */
    if (value == NULL || value[0] == '\0') {
        arr->data[index] = NULL;
        return 1;
    }

    /* Allocate and copy the new string */
    new_str = (char*)malloc((strlen(value) + 1) * sizeof(char));
    if (new_str == NULL) return 0;

    strcpy(new_str, value);
    arr->data[index] = new_str;
    return 1;
}

/* Add string to the end of the array */
int StrArrAdd(StrArrT* arr, const char* value) {
    if (arr == NULL) return 0;

    if (!StrArrGrow(arr, 1)) return 0;

    arr->data[arr->count] = NULL;
    arr->count++;

    return StrArrSet(arr, arr->count - 1, value);
}

/* Insert string at specified index, shifting elements up */
int StrArrInsert(StrArrT* arr, long long index, const char* value) {
    long long i;

    if (arr == NULL) return 0;
    if (index < 0 || index > arr->count) return 0;

    if (!StrArrGrow(arr, 1)) return 0;

    /* Shift elements up */
    for (i = arr->count; i > index; i--) {
        arr->data[i] = arr->data[i - 1];
    }

    arr->data[index] = NULL;
    arr->count++;

    return StrArrSet(arr, index, value);
}

/* Delete string at index, shifting elements down */
int StrArrDelete(StrArrT* arr, long long index) {
    long long i;

    if (arr == NULL) return 0;
    if (index < 0 || index >= arr->count) return 0;

    /* Free the string at index */
    if (arr->data[index] != NULL) {
        free(arr->data[index]);
    }

    /* Shift elements down */
    for (i = index; i < arr->count - 1; i++) {
        arr->data[i] = arr->data[i + 1];
    }

    arr->count--;

    /* Shrink if capacity is more than double the count */
    if (arr->capacity > 2 * arr->count) {
        StrArrShrink(arr);
    }

    return 1;
}

/* Fast delete: swap with last element before deleting */
int StrArrFastDelete(StrArrT* arr, long long index) {
    if (arr == NULL) return 0;
    if (index < 0 || index >= arr->count) return 0;

    /* Free the string at index */
    if (arr->data[index] != NULL) {
        free(arr->data[index]);
    }

    /* If not deleting the last element, copy last element to this position */
    if (index != arr->count - 1) {
        arr->data[index] = arr->data[arr->count - 1];
    }

    arr->count--;

    /* Shrink if capacity is more than double the count */
    if (arr->capacity > 2 * arr->count) {
        StrArrShrink(arr);
    }

    return 1;
}

/* Push string onto stack (same as Add) */
int StrArrPush(StrArrT* arr, const char* value) {
    return StrArrAdd(arr, value);
}

/* Peek at top string without removing */
const char* StrArrPeek(StrArrT* arr) {
    if (arr == NULL) return "";
    if (arr->count == 0) return "";
    return StrArrGet(arr, arr->count - 1);
}

/* Pop string from stack (remove and return) */
/* IMPORTANT: Returns allocated memory that caller must free */
/* Returns NULL if error or empty */
char* StrArrPop(StrArrT* arr) {
    char* result;
    const char* str;

    if (arr == NULL) return NULL;
    if (arr->count == 0) return NULL;

    str = StrArrGet(arr, arr->count - 1);

    /* Make a copy of the result */
    result = (char*)malloc((strlen(str) + 1) * sizeof(char));
    if (result == NULL) return NULL;

    strcpy(result, str);

    /* Delete the last element */
    if (arr->data[arr->count - 1] != NULL) {
        free(arr->data[arr->count - 1]);
    }
    arr->count--;

    /* Shrink if needed */
    if (arr->capacity > 2 * arr->count) {
        StrArrShrink(arr);
    }

    return result;
}

/* Swap two elements in the array */
int StrArrSwap(StrArrT* arr, long long a, long long b) {
    char* temp;

    if (arr == NULL) return 0;
    if (a < 0 || a >= arr->count) return 0;
    if (b < 0 || b >= arr->count) return 0;
    if (a == b) return 1;

    temp = arr->data[a];
    arr->data[a] = arr->data[b];
    arr->data[b] = temp;

    return 1;
}

/* Sort the array using quicksort with callback */
int StrArrSort(StrArrT* arr, StrArrCompareFunc callback) {
    if (arr == NULL) return 0;
    if (arr->count <= 1) return 1;

    g_compare_callback = callback;
    qsort(arr->data, arr->count, sizeof(char*), StrArrCompareWrapper);

    return 1;
}

/* Random sort - shuffles the array */
int StrArrRandomSort(StrArrT* arr) {
    long long i, j;

    if (arr == NULL) return 0;
    if (arr->count <= 1) return 1;

    srand((unsigned int)time(NULL));

    /* Fisher-Yates shuffle */
    for (i = arr->count - 1; i > 0; i--) {
        j = rand() % (i + 1);
        StrArrSwap(arr, i, j);
    }

    return 1;
}

/* Binary search for value in sorted array */
long long StrArrBinarySearch(StrArrT* arr, const char* value, StrArrCompareFunc callback) {
    long long left = 0, right, mid;
    int cmp;

    if (arr == NULL) return -1;
    if (arr->count == 0) return -1;
    if (value == NULL) value = "";

    right = arr->count - 1;

    while (left <= right) {
        mid = left + (right - left) / 2;

        if (callback) {
            cmp = callback(StrArrGet(arr, mid), value);
        } else {
            cmp = StrArrDefaultCompare(StrArrGet(arr, mid), value);
        }

        if (cmp < 0) {
            left = mid + 1;
        } else if (cmp > 0) {
            right = mid - 1;
        } else {
            return mid; /* Found */
        }
    }

    return -1; /* Not found */
}

/* Insert value at sorted position */
int StrArrBinaryInsert(StrArrT* arr, const char* value, StrArrCompareFunc callback) {
    long long left = 0, right, mid;
    int cmp;
    long long insert_pos = 0;

    if (arr == NULL) return 0;
    if (value == NULL) value = "";

    /* If empty, just add */
    if (arr->count == 0) {
        return StrArrAdd(arr, value);
    }

    /* Binary search for insertion position */
    right = arr->count - 1;

    while (left <= right) {
        mid = left + (right - left) / 2;

        if (callback) {
            cmp = callback(StrArrGet(arr, mid), value);
        } else {
            cmp = StrArrDefaultCompare(StrArrGet(arr, mid), value);
        }

        if (cmp < 0) {
            left = mid + 1;
            insert_pos = left;
        } else if (cmp > 0) {
            right = mid - 1;
            insert_pos = mid;
        } else {
            /* Equal values - insert after existing one */
            insert_pos = mid + 1;
            break;
        }
    }

    return StrArrInsert(arr, insert_pos, value);
}

/* Binary search and delete value */
int StrArrBinaryDelete(StrArrT* arr, const char* value, StrArrCompareFunc callback) {
    long long index;

    if (arr == NULL) return 0;
    if (value == NULL) value = "";

    index = StrArrBinarySearch(arr, value, callback);
    if (index == -1) return 1; /* Not found - not an error */

    return StrArrDelete(arr, index);
}

/* Remove duplicates (array remains sorted) */
int StrArrUnique(StrArrT* arr, StrArrCompareFunc callback) {
    long long i;

    if (arr == NULL) return 0;
    if (arr->count <= 1) return 1;

    /* Sort first */
    if (!StrArrSort(arr, callback)) return 0;

    /* Remove duplicates from back to front */
    for (i = arr->count - 1; i > 0; i--) {
        int cmp;
        if (callback) {
            cmp = callback(StrArrGet(arr, i), StrArrGet(arr, i - 1));
        } else {
            cmp = StrArrDefaultCompare(StrArrGet(arr, i), StrArrGet(arr, i - 1));
        }

        if (cmp == 0) {
            if (!StrArrDelete(arr, i)) return 0;
        }
    }

    return 1;
}

/* Fast remove duplicates (array may not be sorted after) */
int StrArrFastUnique(StrArrT* arr, StrArrCompareFunc callback) {
    long long i;

    if (arr == NULL) return 0;
    if (arr->count <= 1) return 1;

    /* Sort first */
    if (!StrArrSort(arr, callback)) return 0;

    /* Remove duplicates from back to front using fast delete */
    for (i = arr->count - 1; i > 0; i--) {
        int cmp;
        if (callback) {
            cmp = callback(StrArrGet(arr, i), StrArrGet(arr, i - 1));
        } else {
            cmp = StrArrDefaultCompare(StrArrGet(arr, i), StrArrGet(arr, i - 1));
        }

        if (cmp == 0) {
            if (!StrArrFastDelete(arr, i)) return 0;
        }
    }

    return 1;
}

/* Reverse the array */
int StrArrReverse(StrArrT* arr) {
    long long i, j;

    if (arr == NULL) return 0;

    for (i = 0, j = arr->count - 1; i < j; i++, j--) {
        StrArrSwap(arr, i, j);
    }

    return 1;
}

/* Store array to binary file */
int StrArrFileStore(StrArrT* arr, const char* filename) {
    FILE* file;
    long long i;
    size_t len;

    if (arr == NULL) return 0;
    if (filename == NULL) return 0;

    file = fopen(filename, "wb");
    if (file == NULL) return 0;

    /* Write count */
    if (fwrite(&arr->count, sizeof(long long), 1, file) != 1) {
        fclose(file);
        return 0;
    }

    /* Write each string */
    for (i = 0; i < arr->count; i++) {
        const char* str = StrArrGet(arr, i);
        len = strlen(str) + 1; /* Include null terminator */

        if (fwrite(&len, sizeof(size_t), 1, file) != 1) {
            fclose(file);
            return 0;
        }

        if (fwrite(str, sizeof(char), len, file) != len) {
            fclose(file);
            return 0;
        }
    }

    fclose(file);
    return 1;
}

/* Restore array from binary file */
int StrArrFileRestore(StrArrT* arr, const char* filename) {
    FILE* file;
    long long i, count;
    size_t len;
    char* buffer;

    if (arr == NULL) return 0;
    if (filename == NULL) return 0;

    /* Clear existing data */
    StrArrFinal(arr);

    file = fopen(filename, "rb");
    if (file == NULL) return 0;

    /* Read count */
    if (fread(&count, sizeof(long long), 1, file) != 1) {
        fclose(file);
        return 0;
    }

    /* Set count (allocate space) */
    if (!StrArrSetCount(arr, count)) {
        fclose(file);
        return 0;
    }

    /* Read each string */
    for (i = 0; i < count; i++) {
        if (fread(&len, sizeof(size_t), 1, file) != 1) {
            StrArrFinal(arr);
            fclose(file);
            return 0;
        }

        buffer = (char*)malloc(len * sizeof(char));
        if (buffer == NULL) {
            StrArrFinal(arr);
            fclose(file);
            return 0;
        }

        if (fread(buffer, sizeof(char), len, file) != len) {
            free(buffer);
            StrArrFinal(arr);
            fclose(file);
            return 0;
        }

        /* Store string */
        if (len == 1 && buffer[0] == '\0') {
            free(buffer);
            arr->data[i] = NULL;
        } else {
            arr->data[i] = buffer;
        }
    }

    fclose(file);
    return 1;
}

/* Default compare function - ASCII case sensitive */
int StrArrDefaultCompare(const char* a, const char* b) {
    if (a == NULL) a = "";
    if (b == NULL) b = "";
    return strcmp(a, b);
}

/* Case insensitive compare function */
int StrArrCaseInsensitiveCompare(const char* a, const char* b) {
    if (a == NULL) a = "";
    if (b == NULL) b = "";
    return _stricmp(a, b); /* MSVC specific, use strcasecmp on other platforms */
}

#endif /* STRARR_H */

Title: Re: DeepSeek do C right
Post by: Theo Gottwald on June 07, 2026, 07:50:58 AM
Deepseek is the cheapest KI, yet even  "V4 Flash" can do any coding task and is 1/10 th of the price from the big prooviders.
In my tests it even beats Minimax M3 and is much cheaper.

In short: Deepseek is not the best but especially "V4 Flash" API is so cheap that this alone can put pressure on all other providers.

Imagine you have 2 Taxi's - one very compfortable and you pay $100 and a competition one with a hard seat and you pay $5.

The point is:
BOTH bring you from A to B. Which will most people take?