Is there a way to 'dynamically size' a char variable? - c

I didn't exactly know how to phrase the question title. Is there way to make a char get larger with every char I type? It's kind of hard to understand. Take a look at the code:
char t[100];
scanf("%c", &t);
Is there a way to make the char bigger than 100 indexes if needed?

Yes, but...
You cannot resize a fixed-size array like t in your example. You'll have to use dynamic memory routines such as malloc, calloc, or realloc to allocate and resize the buffer. Here's a typical implementation that starts with a small buffer and doubles its size as necessary:
#include <stdlib.h>
#include <stdio.h>
/**
* getInput
*
* Reads input from the specified stream into a character buffer, extending
* the buffer as necessary.
*
* Inputs:
*
* stream - the input stream
*
* Outputs: none
*
* Returns: pointer to a character buffer containing the input string.
*/
char *getInput( FILE *stream )
{
/**
* Track the physical size of our buffer, which is at least 1 greater
* than the number of characters stored in it. Since we double the
* buffer size on each realloc, this has to start as a non-zero value.
*/
size_t buffer_size = 1;
/**
* Track the number of characters read from the input stream. Once this
* count equals the buffer size, we need to extend the buffer.
*/
size_t characters_read = 0;
/**
* Pointer to our dynamically-allocated buffer.
*/
char *buffer = NULL;
int c;
/**
* Read characters from the input stream until we hit a newline or EOF.
*/
while ( ( c = fgetc( stream ) ) != EOF && c != '\n' )
{
/**
* Update the number of characters read.
*
* If the number of characters read equals the buffer size,
* then we need to extend the buffer. Typically, we double
* the buffer size.
*/
if ( ++characters_read == buffer_size )
{
/**
* Double the size of the buffer (if the buffer pointer is NULL,
* this will allocate the buffer). ALWAYS assign the result of
* realloc to a temporary pointer - if it fails, it will return NULL
* and leave the buffer unchanged. If you assign that NULL to your
* pointer variable, you'll lose your reference to that memory.
*/
char *tmp = realloc( buffer, sizeof *buffer * (buffer_size * 2) );
/**
* If the allocation is unsuccessful, write an error message and
* return the buffer in its current state.
*/
if ( !tmp )
{
fprintf( stderr, "getInput - failed to extend input buffer, returning what we have so far...\n" );
return buffer;
}
/**
* Otherwise, update our buffer pointer (which may have changed
* as a result of the malloc operation) and buffer size:
*/
buffer = tmp;
buffer_size *= 2;
}
/**
* Write the character to the buffer. Remember that arrays are
* 0-indexed, so the first character goes to index 0, second
* character goes to index 1, etc.
*/
buffer[characters_read-1] = c;
}
/**
* Terminate the string. The logic above should make sure that
* characters_read is *always* less than buffer_size, so we shouldn't
* need to check for overflow here.
*/
buffer[characters_read] = 0;
/**
* Some debugging output
*/
fprintf( stderr, "buffer_size = %zu\n", buffer_size );
fprintf( stderr, "characters_read = %zu\n", characters_read );
return buffer;
}
/**
* Simple main program to exercise the code above.
*/
int main( void )
{
printf( "Gimme something: " );
char *input = getInput( stdin );
if ( input )
{
printf( "You typed: \"%s\"\n", input );
free( input );
}
else
{
printf( "error getting input\n" );
}
return 0;
}
Some example runs:
jbode:input john.bode$ ./input
Gimme something: a
buffer_size = 2
characters_read = 1
You typed: "a"
jbode:input john.bode$ ./input
Gimme something: ab
buffer_size = 4
characters_read = 2
You typed: "ab"
jbode:input john.bode$ ./input
Gimme something: abc
buffer_size = 4
characters_read = 3
You typed: "abc"
jbode:input john.bode$ ./input
Gimme something: abcd
buffer_size = 8
characters_read = 4
You typed: "abcd"
Note that the buffer size is always at least 1 larger than the number of characters in the string.
Doubling the size of the buffer each time winds up being a little more runtime efficient in the end than extending it by a fixed amount each time through, because on average you're making fewer realloc calls (which can be an expensive operation). The tradeoff is that you may wind up with a buffer twice as big as you really need. Extending by a fixed amount should result in less wasted space, but see above about runtime. In the end, you may need to do some analysis to determine which way is best for the problem at hand.

Related

The puts() only prints the last element of the text file

I have a text file full of text that i want to store in the form of strings in S
FILE *fp;
char str[200];
char **S = malloc( 200000*sizeof( char ) );
int i=0, j;
fp = fopen("S.txt" , "r");
while( fgets (str, 200, fp)!=NULL )
{
S[i] = str;
i++;
}
for(j=0;j<i;j++)
puts(S[j]);
fclose(fp);
But the problem is that the program only prints the last string of the list. I think that maybe i allocated the memory wrong(the malloc( 200000*sizeof( char ) ) its becouse the file contains up to 1000 strings of up to 200 characters)
FILE *fp;
char str[200];
/* <<<ATTENTION, READ HERE>>>
* Here, the allocation size is incorrect, one of two:
* You should use malloc( 200000 * sizeof (char *)); as you are
* allocating the pointers in the array, not the space for
* the strings
* You express (always safe) malloc( 200000 * sizeof *S ); This is
* a fake expression (not evaluated but to get the sizeof only)
*/
char **S = malloc( 200000 * sizeof *S );
int i=0, j;
fp = fopen("S.txt" , "r");
while( fgets (str, 200, fp)!=NULL )
{
/* <<<ATTENTION, READ HERE>>>
* the strdup(str); allocates memory (calling malloc itself)
* and copies the contents of the string in the allocated memory.
S[i] = strdup(str);
i++;
}
for(j=0;j<i;j++)
puts(S[j]);
fclose(fp);
With those two modifications your program will run safe (considering that you cannot allow files of more than 200000 lines of no more than 200 characters)
Your problem, not strdup()ing the string is that you finally made all strings point to the buffer, so the contents of the buffer after reading all the lines where the contents of the last line read. As all pointers pointed to the same place, you got as many copies of the last line (at double space, as fgets() doesn't take the \n off the string, but puts() does add a \n after printing the string passed.
NOTE
read how to create a minimum, complete and verifiable example, as you can easily eliminate the error if you decide to post just a snippet of code. Also, it makes more difficult for us to verify and check your error, or detect what is a typo from what is an error.
NOTE2
In case you want to return all the memory allocated by your program, you can do the following:
for(j = 0; j < i; j++)
free(S[j]); /* each malloc made inside strdup() */
free(S); /* the malloc you did at the beginning */

How to read a command output with pipe and scanf()?

I need to be able to send the output of the GET command and store it into a variable inside my program, currently I'm doing it like this:
GET google.com | ./myprogram
And receiving it in my program with the following code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main(int argc, char *argv[]){
char *a = (char *) malloc (10000000);
scanf("%[^\n]", a);
printf("%s\n",a);
return 0;
}
The problem I have is that the scanf function stops at a new line, and I need to be able to store the whole paragraph output from GET.
Any help will be appreciated. Thanks.
One possibility: Does GET include the size information in the headers? Could you use that to determine how much space to allocate, and how much data to read? That's fiddly though, and requires reading the data in dribs and drabs.
More simply, consider using POSIX (and Linux) getdelim() (a close relative of getline()) and specify the delimiter as the null byte. That's unlikely to appear in the GET output, so the whole content will be a single 'line', and getdelim() will allocate an appropriate amount of space automatically. It also tells you how long the data was.
#include <stdio.h>
int main(void)
{
char *buffer = 0;
size_t buflen = 0;
int length = getdelim(&buffer, &buflen, '\0', stdin);
if (length > 0)
printf("%*.*s\n", length, length, buffer);
free(buffer);
return 0;
}
scanf documentation says
These functions return the number of input items successfully
matched and assigned, which can be fewer than provided for, or even
zero in the event of an early matching failure. The value EOF is
returned if the end of input is reached before either the first
successful conversion or a matching failure occurs. EOF is also
returned if a read error occurs, in which case the error indicator for
the stream (see ferror(3)) is set, and errno is set indicate the
error.
https://www.freebsd.org/cgi/man.cgi?query=scanf&sektion=3
Have you considered writing a loop that calls scanf, monitors its return value and breaks out if EOF
Consider the following readall() function implemented in standard C:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
char *readall(FILE *source, size_t *length)
{
char *data = NULL;
size_t size = 0;
size_t used = 0;
size_t n;
/* If we have a place to store the length,
we initialize it to zero. */
if (length)
*length = 0;
/* Do not attempt to read the source, if it is
already in end-of-file or error state. */
if (feof(source) || ferror(source))
return NULL;
while (1) {
/* Ensure there is unused chars in data. */
if (used >= size) {
const size_t new_size = (used | 65535) + 65537 - 32;
char *new_data;
new_data = realloc(data, new_size);
if (!new_data) {
/* Although reallocation failed, data is still there. */
free(data);
/* We just fail. */
return NULL;
}
data = new_data;
size = new_size;
}
/* Read more of the source. */
n = fread(data + used, 1, size - used, source);
if (!n)
break;
used += n;
}
/* Read error or other wonkiness? */
if (!feof(source) || ferror(source)) {
free(data);
return NULL;
}
/* Optimize the allocation. For ease of use, we append
at least one nul byte ('\0') at end. */
{
const size_t new_size = (used | 7) + 9;
char *new_data;
new_data = realloc(data, new_size);
if (!new_data) {
if (used >= size) {
/* There is no room for the nul. We fail. */
free(data);
return NULL;
}
/* There is enough room for at least one nul,
so no reason to fail. */
} else {
data = new_data;
size = new_size;
}
}
/* Ensure the buffer is padded with nuls. */
memset(data + used, 0, size - used);
/* Save length, if requested. */
if (length)
*length = used;
return data;
}
It reads everything from the specified file handle (which can be a standard stream like stdin or a pipe opened via popen()) into a dynamically allocated buffer, appends a nul byte (\0), and returns a pointer to the buffer. If not NULL, the actual number of characters read (so, not including the appended nul byte), is stored in the size_t pointed to by the second parameter.
You can use it to read binary data output by programs, say dot -Tpng diagram.dot or image converters, or even wget -O - output (getting data from specific URLs, text or binary).
You can use this for example thus:
int main(void)
{
char *src;
size_t len;
src = readall(stdin, &len);
if (!src) {
fprintf(stderr, "Error reading standard input.\n");
return EXIT_FAILURE;
}
fprintf(stderr, "Read %zu chars.\n", len);
/* As an example, print it to standard output. */
if (len > 0)
fwrite(src, len, 1, stdout);
free(src);
return EXIT_SUCCESS;
}
The readall() function has two quirks: it allocates memory in roughly 131072-byte chunks (but could vary if fread() were to return short reads), and pads the buffer with 7 to 15 nul bytes. (There are reasons why I like doing it this way, but it is all speculative and specific to the C libraries I tend to use, so it is not important.)
Although the ones used above work fine, you can change the size_new calculations if you prefer otherwise. Just make sure that they both are at least used + 1.

Using fgets with realloc()

I'm trying to create a function to read a single line from a file of text using fgets() and store it in a dynamically allocating char* using malloc()but I am unsure as to how to use realloc() since I do not know the length of this single line of text and do not want to just guess a magic number for the maximum size that this line could possibly be.
#include "stdio.h"
#include "stdlib.h"
#define INIT_SIZE 50
void get_line (char* filename)
char* text;
FILE* file = fopen(filename,"r");
text = malloc(sizeof(char) * INIT_SIZE);
fgets(text, INIT_SIZE, file);
//How do I realloc memory here if the text array is full but fgets
//has not reach an EOF or \n yet.
printf(The text was %s\n", text);
free(text);
int main(int argc, char *argv[]) {
get_line(argv[1]);
}
I am planning on doing other things with the line of text but for sake of keeping this simple, I have just printed it and then freed the memory.
Also: The main function is initiated by using the filename as the first command line argument.
The getline function is what you looking for.
Use it like this:
char *line = NULL;
size_t n;
getline(&line, &n, stdin);
If you really want to implement this function yourself, you can write something like this:
#include <stdlib.h>
#include <stdio.h>
char *get_line()
{
int c;
/* what is the buffer current size? */
size_t size = 5;
/* How much is the buffer filled? */
size_t read_size = 0;
/* firs allocation, its result should be tested... */
char *line = malloc(size);
if (!line)
{
perror("malloc");
return line;
}
line[0] = '\0';
c = fgetc(stdin);
while (c != EOF && c!= '\n')
{
line[read_size] = c;
++read_size;
if (read_size == size)
{
size += 5;
char *test = realloc(line, size);
if (!test)
{
perror("realloc");
return line;
}
line = test;
}
c = fgetc(stdin);
}
line[read_size] = '\0';
return line;
}
One possible solution is to use two buffers: One temporary that you use when calling fgets; And one that you reallocate, and append the temporary buffer to.
Perhaps something like this:
char temp[INIT_SIZE]; // Temporary string for fgets call
char *text = NULL; // The actual and full string
size_t length = 0; // Current length of the full string, needed for reallocation
while (fgets(temp, sizeof temp, file) != NULL)
{
// Reallocate
char *t = realloc(text, length + strlen(temp) + 1); // +1 for terminator
if (t == NULL)
{
// TODO: Handle error
break;
}
if (text == NULL)
{
// First allocation, make sure string is properly terminated for concatenation
t[0] = '\0';
}
text = t;
// Append the newly read string
strcat(text, temp);
// Get current length of the string
length = strlen(text);
// If the last character just read is a newline, we have the whole line
if (length > 0 && text[length - 1] == '\n')
{
break;
}
}
[Discalimer: The code above is untested and may contain bugs]
With the declaration of void get_line (char* filename), you can never make use of the line you read and store outside of the get_line function because you do not return a pointer to line and do not pass the address of any pointer than could serve to make any allocation and read visible back in the calling function.
A good model (showing return type and useful parameters) for any function to read an unknown number of characters into a single buffer is always POSIX getline. You can implement your own using either fgetc of fgets and a fixed buffer. Efficiency favors the use of fgets only to the extent it would minimize the number of realloc calls needed. (both functions will share the same low-level input buffer size, e.g. see gcc source IO_BUFSIZ constant -- which if I recall is now LIO_BUFSIZE after a recent name change, but basically boils down to an 8192 byte IO buffer on Linux and 512 bytes on windows)
So long as you dynamically allocate the original buffer (either using malloc, calloc or realloc), you can read continually with a fixed buffer using fgets adding the characters read into the fixed buffer to your allocated line and checking whether the final character is '\n' or EOF to determine when you are done. Simply read a fixed buffer worth of chars with fgets each iteration and realloc your line as you go, appending the new characters to the end.
When reallocating, always realloc using a temporary pointer. That way, if you run out of memory and realloc returns NULL (or fails for any other reason), you won't overwrite the pointer to your currently allocated block with NULL creating a memory leak.
A flexible implementation that sizes the fixed buffer as a VLA using either the defined SZINIT for the buffer size (if the user passes 0) or the size provided by the user to allocate initial storage for line (passed as a pointer to pointer to char) and then reallocating as required, returning the number of characters read on success or -1 on failure (the same as POSIX getline does) could be done like:
/** fgetline, a getline replacement with fgets, using fixed buffer.
* fgetline reads from 'fp' up to including a newline (or EOF)
* allocating for 'line' as required, initially allocating 'n' bytes.
* on success, the number of characters in 'line' is returned, -1
* otherwise
*/
ssize_t fgetline (char **line, size_t *n, FILE *fp)
{
if (!line || !n || !fp) return -1;
#ifdef SZINIT
size_t szinit = SZINIT > 0 ? SZINIT : 120;
#else
size_t szinit = 120;
#endif
size_t idx = 0, /* index for *line */
maxc = *n ? *n : szinit, /* fixed buffer size */
eol = 0, /* end-of-line flag */
nc = 0; /* number of characers read */
char buf[maxc]; /* VLA to use a fixed buffer (or allocate ) */
clearerr (fp); /* prepare fp for reading */
while (fgets (buf, maxc, fp)) { /* continuall read maxc chunks */
nc = strlen (buf); /* number of characters read */
if (idx && *buf == '\n') /* if index & '\n' 1st char */
break;
if (nc && (buf[nc - 1] == '\n')) { /* test '\n' in buf */
buf[--nc] = 0; /* trim and set eol flag */
eol = 1;
}
/* always realloc with a temporary pointer */
void *tmp = realloc (*line, idx + nc + 1);
if (!tmp) /* on failure previous data remains in *line */
return idx ? (ssize_t)idx : -1;
*line = tmp; /* assign realloced block to *line */
memcpy (*line + idx, buf, nc + 1); /* append buf to line */
idx += nc; /* update index */
if (eol) /* if '\n' (eol flag set) done */
break;
}
/* if eol alone, or stream error, return -1, else length of buf */
return (feof (fp) && !nc) || ferror (fp) ? -1 : (ssize_t)idx;
}
(note: since nc already holds the current number of characters in buf, memcpy can be used to append the contents of buf to *line without scanning for the terminating nul-character again) Look it over and let me know if you have further questions.
Essentially you can use it as a drop-in replacement for POSIX getline (though it will not be quite as efficient -- but isn't not bad either)

C Console Input

I can't seem to google this because everything turns up as C++ or C# (Side note: any easy way to search for C specific?). All I'm trying to figure out is how to accept a console string input in such a way that I know it's length so I can return it in reverse order by indexing backwards through it with a for loop. I've had a little C++ experience in the past, but never really used console IO. Any help appreciated, thanks.
Read with fgets().
Cope with a possible trailing \n.
Find length
print in reverse.
char buf[100];
if (fgets(buf, sizeof buf, stdin) == NULL) Handle_EOF();
buf[strcspn(buf, "\n")] = '\0'; // lop off potential trailing \n
size_t len = strlen(buf);
while (len) {
putc(buf[--len], stdout);
}
You can use the fgets function to read from the standard input.
char buf[80];
if (fgets(buf, 80, stdin) != NULL)
/* buf now contains the first 80 chars of the input */
Note: Do NOT use gets because it is dangerous--it can overflow the input buffer.
You'll need to set aside some space to store the input; since you don't know ahead of time how big the input will be, you'll have to get a little creative with the storage.
A common strategy is to use a smallish, fixed-size buffer to read from the input stream, and a dynamic, resizable buffer to store the complete string if it winds up being longer than what the fixed-size buffer can handle. This way you can read an arbitrarily long input line in discrete chunks, and then paste the chunks together, resizing the target buffer as necessary.
You'll read the fixed-size chunks from the console in a loop and store it to the dynamic buffer until you see a newline, at which point you exit the input loop. Ideally, your fixed-size buffer should be large enough to handle most reasonable cases, such that you don't need to extend the dynamic buffer.
Excessively wordy (untested!) example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define INPUT_BUF_SIZE 21 // handle strings up to 20 characters in length
int main( void )
{
/**
* Set aside a fixed-size buffer to store input from the console. This
* buffer cannot be resized after it has been allocated.
*/
char inputBuf[INPUT_BUF_SIZE];
/**
* Dynamically allocate a buffer to store the final string;
* its initial size is the same as the fixed buffer. If necessary,
* this buffer may be extended with the realloc function. We're using
* calloc instead of malloc to make sure the initial array contents
* are set to 0.
*/
char *finalBuf = calloc( INPUT_BUF_SIZE, sizeof *finalBuf );
/**
* finalBufSize tracks the total size of the dynamic buffer; finalBufLen
* tracks the length of the string currently stored in the buffer.
* These are not the same thing.
*/
size_t finalBufSize = INPUT_BUF_SIZE;
size_t finalBufLen = 0; // initially no string stored in the buffer
/**
* Read from standard input into the fixed-size buffer; loop until
* we see EOF or there's an error on input.
*/
while ( fgets( inputBuf, sizeof inputBuf, stdin ) )
{
/**
* If there isn't enough space left in finalBuf to store
* the latest chunk, double the size of finalBuf. This strategy
* minimizes the number of times you have to call realloc (which
* can be expensive).
*/
if ( strlen( inputBuf ) + finalBufLen > finalBufSize )
{
/**
* *Always* assign the result of realloc to a temp variable; if the
* call fails it will return NULL, and if you overwrite the value
* of finalBuf with NULL, you'll lose your only reference to any
* previously allocated memory.
*/
char *tmp = realloc( finalBuf, finalBufSize * 2 );
if ( tmp )
{
finalBuf = tmp;
finalBufSize *= 2;
}
else
{
/**
* We can't extend the buffer anymore, so we'll exit the
* loop and work with what we have.
*/
fprintf( stderr, "Could not extend storage buffer, exiting input loop\n" );
break;
}
}
/**
* Append the input string to the target buffer.
*/
strcat( finalBuf, inputBuf );
finalBufLen = strlen( finalBuf );
/**
* Did we see a newline in the last input chunk? If so,
* remove that newline from the final string (unless you
* want to include that in your reversal) and exit
* the loop.
*/
char *newline = strchr( finalString, '\n' );
if ( newline )
{
*newline = 0; // overwrite the newline character with the string terminator
break;
}
}
At this point, finalBuf contains the input from the console, and you can reverse this string for output. Once you're done with it, release the memory that's been allocated with the free function like so:
free( finalBuf );
Ideally you'd separate all that input handling into its own function, but this is a good enough illustration for now.
This is my solution but with recursion:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 20
void reverseW(char *, int);
int main()
{
char tmp[N], *string;
printf("Type a String:\n");
scanf("%s", tmp);
string=(char*)malloc((strlen(tmp)+1)*sizeof(char));
if (string==NULL)
{
printf("Error !\n");
exit(0);
}
strcpy(string, tmp);
reverseW(string, strlen(string));
printf("\nThe reverse of %s is %s !\n", tmp, string);
free(string);
return 0;
}
void reverseW(char *word, int size)
{
char tmp;
if (size>1)
{
tmp=word[0];
word[0]=word[size-1];
word[size-1]=tmp;
reverseW(word+1, size-2);
}
return;
}
I wrote this function to put input from stdin into a buffer, for a cli project in uni.
It reads stdin char by char, it has no buffer overflow.
/*max line lenght*/
#define CLI_MAX_CMD_LEN 1024
/*get_line copies characters from stdin to buffer pointed by buf, stopping when a
carriage return or newline is encountered. It returns -1 on errors, otherwise strlen count */
int get_line(char *buf) {
int i,c;
for (i=0;i<CLI_MAX_CMD_LEN;i++) {
c = getchar();
switch (c) {
/*if terminating char is found an error has occurred*/
case '\0':
printf("found '\\0' instead of '\\n'\n");
return -1;
case '\t':
/*show possible commands*/
autocomplete(buf);
break;
case EOF:
/* prints the warning to stdout */
printf("End of file reached\n");
/* continue to execute following cases code */
case '\n':
case '\r':
buf[i] = '\0';
return i;
default :
buf[i] = c;
}
}
/*if end of buffer is reached put terminating char on last element
means that an error has occurred*/
buf[CLI_MAX_CMD_LEN] = '\0';
return -1;
}

Dynamic memory allocation of a string

how to dynamically allocate memory for a string?
I want to take a text file as input and want to store the characters of the file to a string.
First I count the number of character in the text file then dynamically allocate the string for this size and then want to the copy the text to the string.
main()
{
int count = 0; /* number of characters seen */
FILE *in_file; /* input file */
/* character or EOF flag from input */
int ch;
in_file = fopen("TMCP.txt", "r");
if (in_file == NULL) {
printf("Cannot open %s\n", "FILE_NAME");
exit(8);
}
while (1)
{
ch = fgetc(in_file);
if (ch == EOF)
break;
++count;
}
printf("Number of characters is %d\n",
count);
char *buffer=(char*)malloc(count*(sizeof(char)));
}
That's a terrible solution. You can determine the size of the file using a load of methods (search for tell file size, and especially for fstat), and you can just mmap your file to memory directly, giving you exactly that buffer.
One option is to read the file a fixed-sized chunk at a time and extend the dynamic buffer as you read the file. Something like the following:
#define CHUNK_SIZE 512
...
char chunk[CHUNK_SIZE];
char *buffer = NULL;
size_t bufSize = 0;
...
while ( fgets( chunk, sizeof chunk, in_file ) )
{
char *tmp = realloc( buffer, bufSize + sizeof chunk );
if ( tmp )
{
buffer = tmp;
buffer[bufSize] = 0; // need to make sure that there is a 0 terminator
// in the buffer for strcat to work properly.
strcat( buffer, chunk );
bufSize += sizeof chunk;
}
else
{
// could not extend the dynamic buffer; handle as necessary
}
}
This snippet reads up to 511 characters from in_file at a time (fgets will zero-terminate the target array). It will allocate and extend buffer for each chunk, then concatenate the input to buffer. In order for strcat to work properly, the destination buffer needs to be 0-terminated. This isn't guaranteed the first time around when the buffer is initially allocated, although it should be on sunsequent iterations.
Another strategy is to double the buffer size each time, which results in fewer realloc calls, but this is probably easier to grasp.

Resources