Click to See Complete Forum and Search --> : c + reading an unkown size string


youssefe2k
05-26-2004, 05:31 AM
hi all,

is there a way of reading an unkown sized string from stdin?
char *temp;

scanf("%s", &temp);
this deosnt work unless i do char temp[whatever]; who come?

also sprintf(char *, "%d", 1) also doesnt work unless string size is mentioned is there a way around this?

thanx

Morphine Drip
05-26-2004, 07:00 AM
your short answer is 'you need a buffer that will contain the length of the string entered'.

i would recommend reading the chapter on pointers in your c/c++ book.....or googling on pointers in c.

your second example with the sprintf would never work. for the first parameter you're giving it a variable type...when it's looking for a char buffer.

read up on pointers, all your questions will be answered there.

blingbling!!
05-26-2004, 09:03 AM
Check out malloc() and calloc() - I seem to remember these have something to do with allocating memory space at run time.

hth
--Robin

youssefe2k
05-26-2004, 06:28 PM
buffers have to have a specific size right? so there is no way that i could read an unkown sized string? some could would help... thanx alot

bwkaz
05-26-2004, 06:52 PM
No, buffers are simply memory areas. They don't have to be fixed-size:

char *read_all_input()
{
char *buf = malloc(1);
char *ptr = buf;
int ch;
int charcount = 1;

while((ch = fgetc(stdin)) != EOF) {
*ptr = (char)ch;

buf = realloc(buf, ++charcount);
ptr = buf + charcount - 1;
}

*ptr = '\0'; /* string termination char */

return buf;
} Yes, this is horribly inefficient (it reads one byte at a time, and reallocates one byte at a time), but it's safe. The caller has to free() the return value or they'll have a memory leak, but that's not too hard. You might be able to figure out some way of getting at a chunk of input at a time (for example, with the read() syscall instead of using the stream I/O functions), which would improve efficiency quite a bit.

dboyer
05-26-2004, 06:53 PM
you can always use a STL string... then you can just go
cin >> string1;

and it will load any length string.

dchidelf
05-27-2004, 12:40 PM
Originally posted by bwkaz
char *read_all_input()
{
char *buf = malloc(1);
char *ptr = buf;
int ch;
int charcount = 1;

while((ch = fgetc(stdin)) != EOF) {
*ptr = (char)ch;

buf = realloc(buf, ++charcount);
ptr = buf + charcount - 1;
}

*ptr = '\0'; /* string termination char */

return buf;
}


Be careful with realloc.
If realloc fails it returns NULL, which would overwrite buf, leaving no way to free the memory allocated (memory leak).
A realize this is just quick demo code, but remember to check return values.

bwkaz
05-27-2004, 06:38 PM
Yes, that would be safer. However, when realloc() fails and returns NULL, ptr will point at 0+charcount, which is almost always un-writable, so you'll get a segfault right away anyway. Once your process dies, the unfreed memory doesn't matter too much.

Not that that's a good way to fix the problem, but still... ;)

Of course, you should also check the return value of malloc(), in case that fails for whatever reason. And to be perfectly correct, charcount should be either a size_t or a long (since the only guarantee about ints across architectures is that they're "at least 16 bits wide"). I don't know the minimum width of a size_t, but a size_t is more correct for any variable indicating a size.

maccorin
05-31-2004, 01:39 PM
if you don't mind using a GNU-Extension, you could use the getline func (man 3)

it will allocate the character array for you.

If you wanna be portable though, you'd be better of w/ a solution like bkwaz's, of course, breaking that into chunks would of course be better