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