0

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?

4
  • pin is uninitialized. You need to allocate space for the pointers you allocate in the loop. If you don't have a fixed size then you will also need to keep track of how many slots you've allocated and realloc if you need more space. Commented Sep 15, 2022 at 18:44
  • Worth a read and a switch to fgets: Why is the gets function so dangerous that it should not be used? Commented Sep 15, 2022 at 18:45
  • @RetiredNinja I am actually so confused right now. You mean that I have to allocate space for the size of the array and the size of the strings as well? If i got that correctly would you be kind enough to help me? Commented Sep 15, 2022 at 18:47
  • Dynamically create an array of strings with malloc has some examples. Commented Sep 15, 2022 at 18:51

1 Answer 1

1

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
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.