I've implemented a dynamic array data structure in C; and i'm now looking for a proper way to fill up my arrays from stdin. Using scanf()
or fgets()
seems not to be a good idea, since their buffer size is fixed at compilation time i would lose the dynamicity of my structure. So i'm using getline()
and allocating the memory dynamically for every char i want to put in my array.
I wrote this function to fill up two arrays from stdin:
//input arrays from keyboard
void use_input_array(){
char *line = NULL;
size_t len = 0;
ssize_t read;
puts("Enter your first ARRAY : ");
struct dynarray *first;
create_dynarray(&first, 1);
while((read = getline(&line, &len, stdin)) != -1){
if(read > 0){
add_elem(first, line);
}
}
free(line);
char *sline = NULL;
size_t slen = 0;
ssize_t sread;
puts("Enter your second ARRAY :");
struct dynarray *second;
create_dynarray(&second, 1);
while((sread = getline(&sline, &slen, stdin)) != -1){
if(sread > 0){
add_elem(second, sline);
}
free(sline);
}
puts("END");
}
When i execute the function i'm able to insert the first string with no problem, but when it comes to second the execution goes directly to the end. I have no idea why this is happening. Here's a small compilable example to better show my problem:
#include<stdio.h>
#include<stdlib.h>
typedef struct dynarray
{
void **memory;
size_t allocated;
size_t used;
int index;
} dynarray;
void create_dynarray(dynarray **array, size_t size)
{
*array = calloc(size, sizeof **array);
(*array)->memory = NULL;
(*array)->allocated = 0;
(*array)->used = 0;
(*array)->index = -1;
}
//adds a new element at the bottom of dynarray
void add_elem(dynarray *array, void *data)
{
size_t toallocate;
size_t size = sizeof(void *);
if ((array->allocated - array->used) < size){
toallocate = array->allocated == 0 ? size : (array->allocated * 2);
array->memory = realloc(array->memory, toallocate);
array->allocated = toallocate;
}
array->memory[++array->index] = data;
array->used = array->used + size;
}
//input arrays from keyboard
void use_input_array(){
char *line = NULL;
size_t len = 0;
ssize_t read;
puts("Enter your first ARRAY : ");
struct dynarray *first;
create_dynarray(&first, 1);
while((read = getline(&line, &len, stdin)) != -1){
if(read > 0){
add_elem(first, line);
}
}
free(line);
char *sline = NULL;
size_t slen = 0;
ssize_t sread;
puts("Enter your second ARRAY :");
struct dynarray *second;
create_dynarray(&second, 1);
while((sread = getline(&sline, &slen, stdin)) != -1){
if(sread > 0){
add_elem(second, sline);
}
free(sline);
}
puts("END");
}
int main(){
use_input_array();
}
Another problem is related to the fact that my input string is an array of char
but my structure is built to be typeless so it expects a void pointer. I could create an array of int
,double
etc. to perform the conversion but this would also mean to have a fixed size.I was thinking about implementing my own coversion function and calling it before inserting the element in the array. But i really don't know where to start... Any suggestions? Thanks.
Something like this could work.
Only one pointer is needed for getline
. Since the pointer is assigned array->memory[++array->index] = data;
more memory needs to be allocated for each iteration. Set line
to NULL and len
to zero.
Consider breaking out of the loop when an empty line is entered. '\n' == line[0]
.
Free line
at the very end.
char *line = NULL;
size_t len = 0;
ssize_t read;
puts("Enter your first ARRAY : ");
struct dynarray *first;
create_dynarray(&first, 1);
while((read = getline(&line, &len, stdin)) != -1){
if ( '\n' == line[0]) {
break;
}
if(read > 0){
add_elem(first, line);
line = NULL;
len = 0;
}
}
puts("Enter your second ARRAY :");
struct dynarray *second;
create_dynarray(&second, 1);
while((read = getline(&line, &len, stdin)) != -1){
if ( '\n' == line[0]) {
break;
}
if(read > 0){
add_elem(second, line);
line = NULL;
len = 0;
}
}
free(line);