As mentioned in the comment, you have several issues to correct. Starting with "Why is getline
not working?" getline
takes a FILE *
stream pointer not a file descriptor as its third parameter. Using stdin
instead of 0
will correct the problem. The remaining problems deal with allocation. Those have been discussed in the comments and corrected examples are shown below.
The biggest issue you will run into, is "How will I know how many lines were actually read?" You have hard-coded '5', but what if you read less than 5
?
To answer the question, you need to, at minimum, pass a pointer as a parameter to your array_of_string
function, and update it value with the index
value so that the number of lines read is available back in the calling function (main()
in this case). That way, you always know the number of lines read. For example:
char **array_of_string (size_t *n)
{
...
free (line);
*n = index; /* update n with index, so available in main() */
return array;
}
Your next challenge is "How do I check to make sure I don't read, and try to store, more than 5
lines?" Then, "What do I do if I have more than 5
lines to read?", "Then what?". That is where you either break
from your read loop or, better, use the realloc
function to reallocate array
to increase the number of pointers available. (you can add as many as you want, but a standard approach is to double the current number of pointers you have -- that approach is shown below).
#define MAXLN 5
...
char **array_of_string (size_t *n)
{
...
size_t maxln = MAXLN;
...
while ((rd = getline(&line, &length, stdin)) != -1)
{
...
array[index++] = strdup(line); /* alloc & copy */
if (index == maxln) { /* check limit reached - reallocate */
char **tmp = realloc (array, maxln * sizeof *array * 2);
if (!tmp) {
fprintf (stderr, "error: realloc - memory exhausted.
");
*n = index;
return array;
}
array = tmp; /* set new pointers to NULL */
memset (array + maxln, 0, maxln * sizeof *array);
maxln *= 2;
}
}
...
}
Putting all the pieces together, you could do something like the following, which initially allocate some reasonably anticipate number of pointers to hold the number of lines you expect to read. If you reach that limit before your read is done, you simply realloc
the number of pointers to 2X current. (you realloc
using a tmp
pointer to protect against loss of all existing data in array
if realloc
fails. if realloc
succeeds, you simply assign array = tmp;
)
Take a look at the following and let me know if you have any questions about it:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXLN 5
char **array_of_string (size_t *n);
int main (void) {
char **here = NULL;
size_t i, lines = 0;
/* assign array_of_string to here, check return */
if (!(here = array_of_string (&lines))) {
fprintf (stderr, "error: array_of_string return NULL.
");
return 1;
}
for (i = 0; i < lines; i++) /* print lines */
printf (" line[%3zu] : %s
", i, here[i]);
for (i = 0; i < lines; i++) /* free lines */
if (here[i]) free (here[i]);
free (here); /* free here */
return 0;
}
char **array_of_string (size_t *n)
{
char **array = NULL;
char *line = NULL;
size_t index = 0, length = 0, maxln = MAXLN;
ssize_t rd = 0;
if (!(array = calloc (MAXLN, sizeof *array))) {
fprintf (stderr, "error: virtual memory exhausted.
");
return NULL;
}
while ((rd = getline(&line, &length, stdin)) != -1)
{
while (rd > 0 && (line[rd-1] == '
' || line[rd-1] == '
'))
line[--rd] = 0; /* strip carriage return or newline */
array[index++] = strdup(line); /* alloc & copy */
if (index == maxln) { /* check limit reached - reallocate */
char **tmp = realloc (array, maxln * sizeof *array * 2);
if (!tmp) {
fprintf (stderr, "error: realloc - memory exhausted.
");
*n = index;
return array;
}
array = tmp; /* set new pointers to NULL */
memset (array + maxln, 0, maxln * sizeof *array);
maxln *= 2;
}
}
free(line); /* free memory allocated by getline */
*n = index; /* update n with index, so available in main() */
return array;
}
Compile - with warnings enabled
gcc -Wall -Wextra -o bin/stdintst stdintst.c
(or using similar options for your compiler)
Input File
cat ../dat/damages.txt
Personal injury damage awards are unliquidated
and are not capable of certain measurement; thus, the
jury has broad discretion in assessing the amount of
damages in a personal injury case. Yet, at the same
time, a factual sufficiency review insures that the
evidence supports the jury's award; and, although
difficult, the law requires appellate courts to conduct
factual sufficiency reviews on damage awards in
personal injury cases. Thus, while a jury has latitude in
assessing intangible damages in personal injury cases,
a jury's damage award does not escape the scrutiny of
appellate review.
Because Texas law applies no physical manifestation
rule to restrict wrongful death recoveries, a
trial court in a death case is prudent when it chooses
to submit the issues of mental anguish and loss of
society and companionship. While there is a
presumption of mental anguish for the wrongful death
beneficiary, the Texas Supreme Court has not indicated
that reviewing courts should presume that the mental
anguish is sufficient to support a large award. Testimony
that proves the beneficiary suffered severe mental
anguish or severe grief should be a significant and
sometimes determining factor in a factual sufficiency
analysis of large non-pecuniary damage awards.
Use/Output
$ ./bin/stdintst <../dat/damages.txt
line[ 0] : Personal injury damage awards are unliquidated
line[ 1] : and are not capable of certain measurement; thus, the
line[ 2] : jury has broad discretion in assessing the amount of
line[ 3] : damages in a personal injury case. Yet, at the same
line[ 4] : time, a factual sufficiency review insures that the
line[ 5] : evidence supports the jury's award; and, although
line[ 6] : difficult, the law requires appellate courts to conduct
line[ 7] : factual sufficiency reviews on damage awards in
line[ 8] : personal injury cases. Thus, while a jury has latitude in
line[ 9] : assessing intangible damages in personal injury cases,
line[ 10] : a jury's damage award does not escape the scrutiny of
line[ 11] : appellate review.
line[ 12] :
line[ 13] : Because Texas law applies no physical manifestation
line[ 14] : rule to restrict wrongful death recoveries, a
line[ 15] : trial court in a death case is prudent when it chooses
line[ 16] : to submit the issues of mental anguish and loss of
line[ 17] : society and companionship. While there is a
line[ 18] : presumption of mental anguish for the wrongful death
line[ 19] : beneficiary, the Texas Supreme Court has not indicated
line[ 20] : that reviewing courts should presume that the mental
line[ 21] : anguish is sufficient to support a large award. Testimony
line[ 22] : that proves the beneficiary suffered severe mental
line[ 23] : anguish or severe grief should be a significant and
line[ 24] : sometimes determining factor in a factual sufficiency
line[ 25] : analysis of large non-pecuniary damage awards.
Memory Error Check
In any code your write that dynamically allocates memory, you have 2 responsibilites regarding any block of memory allocated: (1) always preserves a pointer to the starting address for the block of memory so, (2) it can be freed when it is no longer needed.
It is imperative that you use a memory error checking program to insure you haven't written beyond/outside your allocated block of memory, attempted to read or base a jump on an unintitialized value and finally to confirm that you have freed all the memory you have allocated.
For Linux valgrind
is the normal choice. There are many subtle ways to misuse a new block of memory. Using a memory error checker allows you to identify any problems and validate proper use of of the memory you allocate rather than finding out a problem exists through a segfault
. There are similar memory checkers for every platform. They are all simple to use, just run your program through it.
$ valgrind ./bin/stdintst <../dat/damages.txt
==12233== Memcheck, a memory error detector
==12233== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==12233== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==12233== Command: ./bin/stdintst
==12233==
line[ 0] : Personal injury damage awards are unliquidated
line[ 1] : and are not capable of certain measurement; thus, the
<snip>
line[ 24] : sometimes determining factor in a factual sufficiency
line[ 25] : analysis of large non-pecuniary damage awards.
==12233==
==12233== HEAP SUMMARY:
==12233== in use at exit: 0 bytes in 0 blocks
==12233== total heap usage: 31 allocs, 31 frees, 1,989 bytes allocated
==12233==
==12233== All heap blocks were freed -- no leaks are possible
==12233==
==12233== For counts of detected and suppressed errors, rerun with: -v
==12233== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)
Always confirm All heap blocks were freed -- no leaks are possible and equally important ERROR SUMMARY: 0 errors from 0 contexts.
Let me know if you have any further questions.