tags:

views:

159

answers:

2

Hi all, how to read unlimited characters in to a char* variable without specifying the size. For ex: I want to read the address of an employee it may take multilines also. Thanks in advance.

+5  A: 

You have to start by "guessing" the size that you expect, then allocate a buffer that big using malloc. If that turns out to be too small, you use realloc to resize the buffer to be a bit bigger. Sample code:

char *buffer;
size_t num_read;
size_t buffer_size;

buffer_size = 100;
buffer = malloc(buffer_size);
num_read = 0;

while (!finished_reading()) {
    char c = read_next_byte();
    if (num_read >= buffer_size) {
        char *new_buffer;

        buffer_size *= 2; // try a buffer that's twice as big as before
        new_buffer = realloc(buffer, buffer_size);
        if (new_buffer == NULL) {
            free(buffer);
            /* Abort - out of memory */
        }

        buffer = new_buffer;
    }
    buffer[num_read] = c;
    num_read++;
}

This is just off the top of my head, and might (read: will probably) contain errors, but should give you a good idea.

Dean Harding
@Codeka - you should avoid `x = realloc(x, newsize);` If realloc fails, you lose the original pointer and you'll leak memory. That said, one exception to this rule is it's okay if your policy on an alloc failure is to end the process.
R Samuel Klatchko
But, caution... if the realloc fails you have leaked the previous buffer pointer. One should do something like `void *sav=ptr; if((ptr=realloc(ptr,newsiz))==null) { free(sav); }`
Software Monkey
Thanks guys, that's correct. I'll update my example... it's been a while since I used straight C :)
Dean Harding
if its available, you can keep using asprintf() on the same allocated address to automatically grow while you append what was just read to what's already in the allocated buffer. I'm not posting that as an answer, as it isn't a standard function, but is widely available. It usually 'just handles' problems that would arise from realloc() failing, at least the GNU implementation does.
Tim Post
But still if the user enters only few characters, say you have allocated 100 bytes but the user entered only 10 bytes, remaining will be wasted right.
PrithviRaj
pritviraj: You can follow it up with a `realloc(buffer, num_read);` call to trim the allocated buffer to the exact size required.
caf
Also, mixing declarations in code isn't always portable. As its just an optimization in this case, I suggest moving *new_buffer next to *buffer's declaration. The OP did not indicate a platform or standard.
Tim Post
In general you don't want to abort if user input causes you to run out of memory. Most users want an error message, not losing all their data. Instead of `Abort - out of memory` it should say `return error code`.
Gabe
Is this the below code is proper: if any changes please correct it.'int i = 0; char c; char *str = (char *)malloc(sizeof(char)); while((c = getchar()) != '\n') { str[i++] = c; if(i >= strlen(str)-1) str = (char *)realloc(str, strlen(str) + 2); } str[i] = '\0'; return str;'
PrithviRaj
Sorry for posting the code in wrong format. I am new to this site please can you tell me how to post the code snippet.
PrithviRaj
@Tim Post: The declaration of `new_buffer` is at the start of a compound statement, so it is completely portable to all versions of standard C.
caf
@prithviraj: Code snippets should go within backticks (or in questions, indented by 4 spaces). That code is wrong, BTW - you cannot use `strlen()` for that purpose, you need to use a variable to keep track of the currently allocated size (like the `buffer_size` in this answer).
caf
A: 

How about just putting a 1KB buffer (or 4KB) on the stack, reading into that until you find the end of the address, and then allocate a buffer of the correct size and copy the data to it? Once you return from the function, the stack buffer goes away and you only have a single call to malloc.

tomlogic
What happens when the address is bigger than the 1k or 4k buffer on the stack?
Gabe
@gabe: How do you write a 4KB address on an envelope?
tomlogic
Not knowing the size of an input string and trying to read it into a fixed-size buffer is the source of untold security problems in C code.
Gabe
@gabe: `fgets` has a parameter for buffer size. There are definitely functions in the Standard C Library to avoid (like `gets`). Using length-limited functions and fixed-size buffers seems pretty safe to me.
tomlogic
Fixed-size buffers are safe if you use I/O functions that have parameters for buffer size. The issue is what happens when the data you want doesn't fit in your buffer. The question was "how to read _unlimited_ characters". Will the program fail because part of the address is still left sitting in the input stream?
Gabe