I am trying to solve a problem and in the process I am entering the strings using getline as follows( part of my main function)
size_t n1=0,n2=0;
char *a=0, *b=0;
getline(&a,&n1,stdin);
getline(&b,&n2,stdin);
but no matter what input I give the value of n1 and n2 always stored as 120 . How can I overcome this problem to store the exact size of string I input
CodePudding user response:
How can I overcome this problem to store the exact size of string I input
First, you should stop regarding this as a problem and regard it as normal behavior of getline
. You should adapt to getline
and not expect it to adapt to you.
getline
allocates a reasonable amount of spaces to work with. Allocating a smaller amount of space could require getline
to reallocate space more frequently as continuing input required larger and larger allocations. This would waste resources including energy and time.
The n1
or n2
passed to getline
by way of the second parameter is set to the size of the allocated space, not the length of the input read, and there is no way for you to alter this short of changing the implementation of getline
. getline
does not put the length of the input in n1
or n2
.
To get the length of the input that was read, save the return value of getline
:
size_t l1 = getline(&a, &n1, stdin);
size_t l2 = getline(&b, &n2, stdin);
If the allocated space is a great concern, use realloc
to inform the memory management software that the excess space is not needed:
char *temp = realloc(a, n1 = l1 1);
if (!temp) a = temp;
temp = realloc(b, n2 = l2 1);
if (!temp) b = temp;
Some realloc
implementations are likely to ignore attempts to reduce the allocated space, especially when the allocated size is small.
CodePudding user response:
getline
needs a pointer to a buffer pointer and a pointer to a size. Both of these values may be modified by getline
, which is why they are indirect (pointer) arguments.
There are two ways to call getline
:
Let it allocate a buffer for you. The buffer pointer pointed to by the first argument is
NULL
, and the value pointed to by the second argument is irrelevant. (I usually initialise it to 0 but this is not required.)getline
will then allocate a buffer big enough for the input, and let you know how big that buffer is. (Often, you don't actually need this information.) The number of characters actually stored in the buffer is the return value; since the string read is guaranteed to be null-terminated, the allocated buffer size will always be larger than the return value. You should always save the return value so that you know if EOF was encountered; it also saves you the expense of callingstrlen
.Once you are finished with the buffer, it is your responsibility to
free()
it. But you could also reuse it for the next call togetline()
.Give it an already allocated buffer, which it will expand if necessary. In this case, the buffer must have been allocated by
malloc
or equivalent (including a previous call togetline()
), and the size is expected to be the size of the allocation. If the buffer is big enough,getline()
just stores the line read; otherwise, it frees the buffer you gave it, allocates a new one big enough to hold the input, and updates both the buffer address and the size.This lets you minimise buffer allocations in the case where you don't need to keep the line read. You can just keep reusing a single allocation (which will be reallocated only if necessary) and
free()
it when you're done.
Most of the time, you will start with NULL
; there is very little point trying to guess the correct buffer size unless you have a really good way of doing so. If you need to keep the data read for later, you can do so (and remember to free()
it when done); in that case the next call to getline()
will again be NULL
and you probably don't need to worry about the buffer size.
So two common idioms:
char* line1 = NULL;
char* line2 = NULL;
size_t len; /* not actually used */
ssize_t read1 = -1, read2 = -1;
read1 = getline(&line1, &len, infile);
if (read1 != -1) read2 = getline(&line2, &len, infile);
if (read2 != -1) {
/* Do whatever needs to be done */
}
/* clean up */
free(line1);
free(line2);
close(infile);
/* Second scenario: repeated use of buffer */
char* line = NULL;
size_t line_size = 0;
ssize_t nread;
while ((nread = getline(&line, &line_size, infile)) != -1) {
/* Handle line without keeping the pointer */
}
free(line);
close(infile);