If I was using C gets(), and I was reading a string from the user, but I have no idea how big of a buffer I need, and the input could be very large. Is there a way I can determine how large the string the user inputted was, then allocate memory and then put it in the variable? Or at least a way to accept input without knowing how large it is, with a possibility it won't fit in the buffer i've already allocated.
相关问题
- Multiple sockets for clients to connect to
- What is the best way to do a search in a large fil
- glDrawElements only draws half a quad
- Index of single bit in long integer (in C) [duplic
- Equivalent of std::pair in C
If you're on a Unix platform you should probably use
getline()
which is made exactly for this kind of thing.And if your platform doesn't have
getline()
, here's some public domain code that should let you use it. This post is somewhat long, but that's because the code makes an attempt to actually handle real life errors and situations (and even not-so-real life ones like running out of memory).It's probably not the most performant version nor the most elegant version possible. It picks characters off one-by-one using
fgetc()
, and it puts the null terminator at the end of the data every chance it gets as it's reading characters. But, I believe it to be correct even in the face of errors and large and small sets of data. It performs well enough for my purposes.I'm not particularly fond of the
getline()
interface, but I use it because it's a standard of sorts.The following will compile with GCC (MinGW) and under MSVC (as C++ - it uses declarations mixed with statements, which MSVC still doesn't support when compiling as C. Maybe I'll fix that one day).
The problem you describe with
gets()
- having no way of knowing how big the target buffer needs to be to store the input - is exactly why that library call was deprecated in the 1999 standard, and is expected to be gone completely from the next revision; expect most compilers to follow suit relatively quickly. The mayhem caused by that one library function is scarier than the prospect of breaking 40 years' worth of legacy code.One solution is to read the input piecemeal using
fgets()
and a fixed-length buffer, then appending that into a dynamically-resizable target buffer. For example:The caller will be responsible for freeing the buffer when it's done with the input.
I think use an intermediate buffer which is suitably large, and input the string into it with
fgets
or other function by limiting the string length to the max buffer size. Later when the string is input,. calculate the string length and allocate a buffer of the size of the string and copy it into the newly allocated buffer. The old large buffer can be reused to such inputs.You can do:
fgets (buffer, BUFSIZ, stdin);
or
scanf ("%128[^\n]%*c", buffer);
Here you can specify the buffer length 128 bytes as
%128..
and also include all the blankspace within the string.And then calculate the length and allocate new buffer with:
EDIT
Here is one way i worked out:
You need to fix the code to stop crashing in some cases, but this should answer your question.
Allocate your buffer dynamically and use fgets. If you fill the buffer right up then it wasn't big enough so grow it using realloc and then fgets again (but write to the end of the string to maintain what you've already grabbed). Keep doing that until your buffer is larger than the input:
Not with
gets()
. Usefgets()
instead.You cannot safely get user input with
gets()
.You need to use
fgets()
(orfgetc()
) in a loop.Don't use
gets()
. Usefgets()
, and over approximate how much buffer space you will need.The advantage of
fgets
is that if you go over, it will only write that max number of characters, and it won't clobber the memory of another part of your program.will only read up to 99 characters or until it hits a `'\n'. If there's room, it will read the newline into the array.