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
2010-03-24 05:12:57
@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
2010-03-24 05:17:13
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
2010-03-24 05:17:44
Thanks guys, that's correct. I'll update my example... it's been a while since I used straight C :)
Dean Harding
2010-03-24 05:20:52
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
2010-03-24 05:24:34
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
2010-03-24 05:25:24
pritviraj: You can follow it up with a `realloc(buffer, num_read);` call to trim the allocated buffer to the exact size required.
caf
2010-03-24 05:27:04
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
2010-03-24 05:27:31
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
2010-03-24 05:30:59
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
2010-03-24 05:45:31
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
2010-03-24 05:46:50
@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
2010-03-25 02:36:10
@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
2010-03-25 02:38:16
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
2010-03-24 15:57:05
What happens when the address is bigger than the 1k or 4k buffer on the stack?
Gabe
2010-03-24 18:40:02
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
2010-03-25 04:56:27
@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
2010-03-25 18:34:34
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
2010-03-25 19:13:16