-1

I want to write a function that adds an Entry to the first free slot of an array list (if there is a slot free) and a function that merges all those entries to one "String" (I know there are no strings) separated by ', '. Example list contains: "Anna", "Alex", "Anton" in this order Output:"Anna,Alex,Anton".

This is the .c file (only the toDo's should be done)

/** The function adds an entry name to the array list at the
 * first free position, if such a position exists.
 * If there is no free space, ie no NULL entry,
 * the array remains unchanged. When inserting a name,
 * First, the same amount of memory is allocated on the heap using malloc
 * (note space for a final \ 0). After that
 * we use strncpy to convert the string name into the allocated
 * Memory area copied.
 * @param list: Array of \0 terminated strings
 * @param listsize: size of array
 * @param name: \0 terminated string that should be copied into the array
*/
void addNameToList(char **list, size_t listsize, char *name) {
//toDo
}


/** The function adds all entries in the list array to one separated by ','
 * zero-terminated string that is stored in destbuffer.
 * Entries with the value NULL are not added.
 * So that chained calls are possible, the function returns the
 * Pointer destbuffer as return value.
 * Example: The list contains the names "Anna", "Alex", "Anton" in this
 * Sequence. The function returns "Anna, Alex, Anton".
 * @param list: array of \0 terminated strings
 * @param listsize: size of array
 * @param destbuffer: destinationbuffer
 * @param buffersize: size of destbuffer
 * @return destbuffer
*/
char *printListToString(char **list, size_t listsize, char *destbuffer, size_t buffersize) {
//toDo
    return destbuffer;
}

void freeList(char **list, size_t listsize) {
    size_t index = 0;
    for (index = 0; index < listsize; index++)
        if (list[index] != NULL)
            free(list[index]);
    free(list);
}

char **initList(size_t size) {
    return calloc(size, sizeof(char *));
}

This is the given Main (not to change):

int main(void) {

    char **names;
    char outputbuffer[100];
    names = initList(LIST_SIZE);

    addNameToList(names, LIST_SIZE, "Alice");
    addNameToList(names, LIST_SIZE, "Bob");
    addNameToList(names, LIST_SIZE, "Carla");
    addNameToList(names, LIST_SIZE, "Dana");
    addNameToList(names, LIST_SIZE, "Eve");
    printListToString(names, LIST_SIZE, outputbuffer, 100);
    printf("%s\n", outputbuffer); //Output: Alice,Bob,Carla,Dana,Eve
    freeList(names,LIST_SIZE);
}

What I have tried so far (not working):

char *printListToString(char **list, size_t listsize, char *destbuffer, size_t buffersize) {
    int k = 1;
    for(int i = 0; i < listsize; i++) {
        if(list != NULL) {
            strcpy_s(destbuffer, sizeof list, list);
        }
        if(list == '\0') {
            destbuffer[i] =',';
            destbuffer[k] = ' ';
        }
        k++;
    }
    return destbuffer;
}

The code above:

  • k is always one step ahead of i, so it can add a space right after the ',' (which is added at i)
  • I iterate thru the list and check whether an entry is NULL or not if its not NULL it should copy the name from the list into the destbuffer
  • Since the names end with \0 I thought I can just add , and a space right after I copied the name
void addNameToList(char **list, size_t listsize, char *name) {
    malloc(sizeof name);
    if(sizeof list != listsize) {
        for(int i = 0; i < listsize; i++) {
            if(list[i] == NULL) {
                list[i] = name;
            }
        }
    }
}

the code above:

  • saving memory for the name
  • check if list is full
  • if not I add the name at the first place thats null

(Note that I dont have any experience in C, only Python and Java. The "code above" section is what the code meant to do, not what its actually doing)

  • For *one* of the problems in the code you show: The `sizeof` of a pointer will always be the size of the pointer itself, not whatever it might point to. – Some programmer dude Jun 25 '21 at 08:00
  • Yea I should rather use ```strlen()``` I guess? – Sentenza_IV Jun 25 '21 at 08:05
  • Please note that the comments before `addNameToList` explicitly mention `strncpy`, while your attempt (incorrectly) uses `list[i] = name;`. You may not be already aware of the differences between [shallow copy and deep copy in C](https://stackoverflow.com/questions/15278194/shallow-copy-and-deep-copy-in-c). Also note that `printListToString` is definitely *not* iterating through the array list. – Bob__ Jun 25 '21 at 08:56
  • through what am I iterating than? I thought by going over the length of it I would go over every element that could possibly be in there. And could you explain to me, how I would use ```list[i] = name;``` correct? And no, I have not been aware of the copy differences. – Sentenza_IV Jun 25 '21 at 11:24

1 Answers1

0

Let's consider the last snippet

void addNameToList(char **list, size_t listsize, char *name) {
//                                               ^^^^^^^^^^
// 'name' is a POINTER. Not an array, nor a C-string (NULL-terminated array
// of char). It may point to the first element of one of those, though.

    malloc(sizeof name);
    //     ^^^^^^^^^^^    This returns the size, in bytes, of a POINTER to char.
    // Maybe 8, but surely not the number of characters up to the first '\0'
    // from the one pointed by 'name'. To get that, you need
    //     strlen(name)

    // Besides, 'malloc' RETURNS a pointer and you NEED it, because the whole
    // point of that function call is to allocate enough memory to store
    // your object and you better know WHERE this space is. If only to later
    // release that resorce and avoid any leak.

    if(sizeof list != listsize) {
    // ^^^^^^^^^^^  Again, it's the size of a pointer to a pointer to char...
    // Unfortunately, it's also probably different from listsize, so that
    // it's harder to catch this error. Also, You don't need this check...
        for(int i = 0; i < listsize; i++) {
        //             ^^^^^^^^^^^^ ... Because there already is this. 
            if(list[i] == NULL) {
                
                list[i] = name; 
                //      ^ This is a shallow copy, only the value OF the pointer
                // (let's say the memory address) is copied, NOT all the elements
                // of the string.

                // Here is where the memory should be allocated, something like
                //     size_t size = strlen(name);
                //     list[i] = malloc(size);
                //     if ( list[i] == NULL ) { 
                           /* malloc may fail... */
                //     }
                // Then, the array must be copied. Your teacher mentioned
                //  'strncpy'.
            }
        }
    }
}

The other function, printListToString is broken too, perhaps even worse than the previous one.

k is always one step ahead of i, so it can add a space right after the ',' (which is added at i)

To do that, i + 1 could be enough, but that's not the point. There should be two different indices, one to itarate over list and one for destbuffer.

I iterate thru the list and check whether an entry is NULL or not if its not NULL it should copy the name from the list into the destbuffer

Unfortunately, in all its occurrences, list is written without an [i], so that no name in the list is actually accessed.

Since the names end with \0 I thought I can just add , and a space right after I copied the name

I'd do something like

char *printListToString( char **list, size_t listsize
                       , char *destbuffer, size_t buffersize) {
    size_t j = 0;
    for (size_t i = 0; i < listsize; ++i) {
        if ( list[i] != NULL ) {
            // Add ", ", but only if it's not the first name.
            if ( j != 0 ) {
                if ( j + 2 > buffersize )
                    break;
                destbuffer[j++] = ',';
                destbuffer[j++] = ' ';
            }
            // Copy the name. Feel free to use a library function instead.
            for ( size_t k = 0; list[i][k] != '\0'  &&  j < buffersize; ++k, ++j ) {
                destbuffer[j] = list[i][k]; 
            }
        }
    }
    destbuffer[j] = '\0';
    return destbuffer;
}
Bob__
  • 12,361
  • 3
  • 28
  • 42