0

I am trying to implement a data structure where I have a list of char* values and an array that stores the number of occurrences for each unique char* value from cmd line. It's a bit messy, but I thought I had it figured it out until I tried testing it (each test does not have to be compiled differently, I just renamed each run to make the test names different).

Test cmd inputs:

test1 a b c d e f g
test2 a a b b c d d e f f g g
test3 a a a a a a a a a a a
test4 a a a a a a a a a a a b c c
test5 a j i q y z n f o p m a
test6 a a b b c d d e f f g
test7 a j k q e s l i h i a
test8 a j i q y z n f o p m

Based on these inputs, the table lengths for each should look like:

test1 table->length = 7    <- works
test2 table->length = 7    <- works
test3 table->length = 1    <- works
test4 table->length = 3    <- works
test5 table->length = 11   <- works
test6 table->length = 7    <- no work
test7 table->length = 9    <- no work
test8 table->length = 11   <- no work

Based on these results, I don't believe it's the length of argc (as tests 1, 2, 3 works) nor is it the number of unique *chars (as per tests 2, 3, 4,5). When running the code below, it either works and I get to the end of main(...), or, depending on the input, it will fail after displaying:

...
ptr address: 00DF04F4
ptr value: 00DF0510

test.c:


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

typedef struct node {
    char *path;
    int index;
    struct node *next;
} node;

typedef struct lookup {
    struct node *head;
    struct node *ptr;
    int length;
    int array[];
} lookup;

void add(lookup *table, char *path);
void search(lookup *table, char *path, int *i);

void add(lookup *table, char *path) {
    int i = 0;
    search(table, path, &i);
    if(table->ptr == NULL) {
        node *new_node = malloc(sizeof(node));
        if (table->head == NULL) {
            table->head = new_node;
            table->head->next = NULL;
            table->head->path = path;
            table->array[0] = 1;
            table->head->index = 0;
            table->length = 1;
        } else {
            new_node->path = path;
            new_node->next = table->head;
            table->head = new_node;
            table->array[i] = 1;
            table->head->index = i;
            table->length += 1;
        }
    } else {
        table->array[table->ptr->index] += 1;
    }
}

void search(lookup *table, char *path, int *i) {
    if(table->head == NULL) {
        table->ptr = NULL;
        return;
    }
    table->ptr = table->head;
    (*i) = 0;
    while(table->ptr != NULL) {
        printf("ptr address: %p\n", &(table->ptr));
        printf("ptr value: %p\n", (table->ptr));
        /* FAILURE POINT */
        printf("%s\n", table->ptr->path);
        printf("comparing ptr string: '%s' with given '%s'\n", table->ptr->path, path);
        if(strcmp(table->ptr->path, path) == 0) {
            printf("found match!\n");
            return;
        }
        table->ptr = table->ptr->next;
        (*i) += 1;
    }
    printf("could not find '%s' in table\n", path);
}

int main(int argc, char **argv) {
    lookup *table = malloc(sizeof(lookup) + argc);
    table->head = NULL;
    int i = 1;
    for(i; i < argc; i++) {
        printf("\n\ntry adding: %s\n", argv[i]);
        add(table, argv[i]);
    }
    printf("\n\n############\nfinished adding\n");
    printf("table length: %d\n", table->length);

    return 0;
}

I know the pointer isn't null (as I print it's address and value right before) yet I'm not sure why it stops execution where it does with seemingly normal input. Expected output (based on current code) should show each char* that is attempted to be added, the address and value of the pointer as search(...) searches the table, the current *char ptr is pointing to, what two *chars are being compared, whether or not a match was found, or if search(...) could not find the *char.

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
Josh Brown
  • 47
  • 1
  • 9
  • 1
    `lookup *table = malloc(sizeof(lookup) + argc);` does not allocate enough memory (malloc argument is a size in bytes) – M.M Feb 09 '20 at 22:20
  • I think you're onto something. I don't know how much space I need until runtime so I thought I could get around it by doing that according to [link](https://stackoverflow.com/questions/2060974/how-to-include-a-dynamic-array-inside-a-struct-in-c). I'm guessing if I know the entire char length of `argv`, I'd add that instead of argc? – Josh Brown Feb 09 '20 at 22:25
  • Try multiplying `argc` by `sizeof(int)` , since you try to store that many `int` objects – M.M Feb 09 '20 at 22:26
  • 1
    Okay multiplying it by `sizeof(int)` worked! I guess in the case in the link, they just added 50 (in their case) because `sizeof(char)` is 1. Had I read a little further, they discussed a case when using int and they did indeed multiply by `sizeof(int)`. – Josh Brown Feb 09 '20 at 22:35

0 Answers0