Home > OS >  Creation of Dynamic Array of Strings in C
Creation of Dynamic Array of Strings in C

Time:09-17

So I am pretty much trying to create an array that functions as following: 1)I enter a string (in a temporary array like char temp[...] for example) 2)I create a while loop that ends when the first character of temp is \x0 3)Inside the loop I use the malloc function to create space for each string 4)I print the strings

Problem is that whenever i try to run my program it crushes and the compiler isn't helping me much.

Here is the code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LINE 80

int main(){
    char **pin;
    char temp[LINE];
    int index = 0;
    puts("Gimme Books' Titles:");
    gets(temp);
    while(temp[0] != '\x0'){
        pin[index] = (char*)malloc(strlen(temp) 1);
        strcpy(pin[index], temp);
        index  ;
        gets(temp);
    }
    puts("\nBooks' List:");
    for(int k = 0; k < index; k  ){
        puts(pin[k]);
    }
}

Anyone here who can help me find out what I am doing wrong?

CodePudding user response:

The link in the comments above [mostly] assumes that we know the number of elements before we allocate the array.

Thus, it's not as useful when we can only get the number of elements by reading the input file. For TTY input from stdin this won't work too well because we can't rewind the file.

A dynamic array is generally useful. So, I've created one that allows arbitrarily sized array elements. And, it can grow/expand as we add new elements.

And, for demo purposes here, I've created a "book" structure that stores Author's name and book title.

Here is the code. It is annotated:

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

// general dynamic array control
typedef struct {
    void *arr_base;                         // pointer to data
    size_t arr_size;                        // bytes / element
    size_t arr_count;                       // number of elements in use
    size_t arr_capacity;                    // number of elements allocated
} arr_t;

// book control
typedef struct {
    char *book_last;                        // author's last name
    char *book_first;                       // author's first name
    char *book_title;                       // book title
} book_t;

// arrnew -- allocate new array
arr_t *
arrnew(size_t siz)
{
    arr_t *arr = calloc(1,sizeof(*arr));

    // store the number of bytes in each element
    arr->arr_size = siz;

    return arr;
}

// arrappend -- get new element in array
// RETURNS: pointer to element
void *
arrappend(arr_t *arr)
{
    size_t index;
    void *ptr;

    // get index of element to store into and increase the in use count
    index = arr->arr_count  ;

    do {
        // we have enough space for the new element already
        if (arr->arr_count < arr->arr_capacity)
            break;

        // increase allocated amount
        // NOTE: the increment is arbitrary
        arr->arr_capacity  = 10;

        // grow the array
        arr->arr_base = realloc(arr->arr_base,
            arr->arr_capacity * arr->arr_size);

        // got the larger array
        if (arr->arr_base != NULL)
            break;

        perror("arrappend");
        exit(1);
    } while (0);

    // point to element we can store into
    ptr = arr->arr_base;
    ptr  = index * arr->arr_size;

    return ptr;
}

// arrtrim -- trim array to number of elements actually used
void
arrtrim(arr_t *arr)
{

    arr->arr_capacity = arr->arr_count;
    arr->arr_base = realloc(arr->arr_base,arr->arr_capacity * arr->arr_size);

    if (arr->arr_base == NULL) {
        perror("arrtrim");
        exit(1);
    }
}

// arrfree -- free up array storage
void
arrfree(arr_t *arr)
{

    free(arr->arr_base);
    free(arr);
}

int
main(void)
{
    char buf[300];
    char *cp;
    book_t *book;

    // echo line if input is _not_ a tty [mostly for demo]
    struct termios tio;
    int echo = tcgetattr(fileno(stdin),&tio) < 0;

    // get new array
    arr_t *arr = arrnew(sizeof(book_t));

    printf("Gimme Books's Titles:\n");

    while (1) {
        // get next line -- stop on EOF
        char *cp = fgets(buf,sizeof(buf),stdin);
        if (cp == NULL)
            break;

        // echo line if input is _not_ a tty
        if (echo)
            fputs(buf,stdout);

        // strip newline
        buf[strcspn(buf,"\n")] = 0;

        // stop on blank line
        if (buf[0] == 0)
            break;

        // get new book struct
        book = arrappend(arr);

        // get author's last name
        char *tok = strtok(buf," \t");
        book->book_last = strdup(tok);

        // get author's first name
        tok = strtok(NULL," \t");
        book->book_first = strdup(tok);

        // get the book title
        tok  = strlen(tok);
          tok;
        for (;  *tok != 0;    tok) {
            if (*tok != ' ')
                break;
        }
        book->book_title = strdup(tok);
    }

    arrtrim(arr);

    // show all the books
    book = arr->arr_base;
    for (size_t idx = 0;  idx < arr->arr_count;    idx,   book)
        printf("Last: %s First: %s Title: %s\n",
            book->book_last,book->book_first,book->book_title);

    // release storage for each book
    book = arr->arr_base;
    for (size_t idx = 0;  idx < arr->arr_count;    idx,   book) {
        free(book->book_last);
        free(book->book_first);
        free(book->book_title);
    }

    // release array storage
    arrfree(arr);

    return 0;
}

Here is the program input:

Lambstewer Abel A Tale of Two Cities
Smith John      A baker's tale
Jones Fred      Never On Sunday

Here is the program output:

Gimme Books's Titles:
Lambstewer Abel A Tale of Two Cities
Smith John      A baker's tale
Jones Fred      Never On Sunday
Last: Lambstewer First: Abel Title: A Tale of Two Cities
Last: Smith First: John Title: A baker's tale
Last: Jones First: Fred Title: Never On Sunday
  • Related