Read one character at a time (using getc(stdin)) and grow the string (realloc) as you go.
Here's a function I wrote some time ago. Note it's intended only for text input.
char *getln()
{
char *line = NULL, *tmp = NULL;
size_t size = 0, index = 0;
int ch = EOF;
while (ch) {
ch = getc(stdin);
/* Check if we need to stop. */
if (ch == EOF || ch == '\n')
ch = 0;
/* Check if we need to expand. */
if (size <= index) {
size += CHUNK;
tmp = realloc(line, size);
if (!tmp) {
free(line);
line = NULL;
break;
}
line = tmp;
}
/* Actually store the thing. */
line[index++] = ch;
}
return line;
}
Answer from cnicutar on Stack OverflowRead one character at a time (using getc(stdin)) and grow the string (realloc) as you go.
Here's a function I wrote some time ago. Note it's intended only for text input.
char *getln()
{
char *line = NULL, *tmp = NULL;
size_t size = 0, index = 0;
int ch = EOF;
while (ch) {
ch = getc(stdin);
/* Check if we need to stop. */
if (ch == EOF || ch == '\n')
ch = 0;
/* Check if we need to expand. */
if (size <= index) {
size += CHUNK;
tmp = realloc(line, size);
if (!tmp) {
free(line);
line = NULL;
break;
}
line = tmp;
}
/* Actually store the thing. */
line[index++] = ch;
}
return line;
}
You could have an array that starts out with 10 elements. Read input character by character. If it goes over, realloc another 5 more. Not the best, but then you can free the other space later.
How to read input of a string with an indefinite size using Dynamic Memory Allocation?
Dynamic Strings in C - Code Review Stack Exchange
How to dynamically allocate an array and add strings to it? (In C)
what is the point of dynamic allocation in c? (plus dont get triggered. please explain why im wrong)
Videos
Im trying to create a program that takes a users commands and with them creates an HTML file.So for example the input could be newPar [text].And the command will be saved in a string called cmd that has a max of 10 characters.But how can I save the input that is the text of the paragraph in a string that I dont know the length of until the user has typed it?
Edit:Thank you all for the help!!Every suggestion was extremely helpful!Sorry for not answering to all of the comments and taking a while to answer or upvote the comments Unfortunately I didnt manage to finish the program before the deadline I needed to due to other problems I had with making it and not having enough time.But again thank you for helping me overcome the problem I very much appreciate it! :)
The code is generally nice, so my comments are really just picking up crumbs.
I'm not comfortable with your use of asserts to catch errors that could legitimately occur at runtime. I consider asserts to be for asserting logical impossibilities, not for catching runtime errors.
Function expand is equivalent to expand_by_at_least(ds, 1)
Long parameter names destination and source could be abbreviated dst and
src with no loss.
Is giving the user a read-write (ie. non-const) pointer to the private string a good idea (functions returning char*)? And is the position returned consistent (think not - sometimes the new end of string sometimes the old).
In ds_compare (ds_compare_n), why not just return the strcmp (strncmp)
of the two strings?
I don't like the loop in ds_append_cstring. A simple loop copying and
checking for destination full, expanding as necessary would be simpler.
Edit: Do you mind giving me an example of what assert errors could legitimately occur at runtime?
In the context of your code, I have no problem with asserting non-null
pointers, but asserting for non-zero string length seems unsafe. There are
many times when a string could have a zero length but the assert says that
users of your code must guarantee that it is always a design fault in their
code for a nul string to pass into your functions. Not only is this
unreasonable, it is is unnecessary as you can easily handle such cases. BTW
don't assume that mallocing 0 is equivalent to free (it isn't) - handle a
zero request by allocating at least 1 byte.
As an example of testing a logical impossibilty consider some code that does:
expected length = calculate expected length of string
allocate memory
real length = create string in memory
assert(real length = expected length)
The assert tells you whether your algorithms are consistent/correct
Overall
Your header doesn't include any function declarations so I'm not sure what your "public interface" will be but only few of your functions are static so I have to assume you intend to make all others available in which case I have to say I don't like the interface into your structure.
From the looks of it your Dynamic_String should only be manipulated through the appropriate ds_ functions yet your return the pointer to the internal storage from various functions which has the potential for the programmer screwing it up easily.
So consider carefully defining the interface into your structure and how you intend it to be used. Most of you functions should either return Dynamic_String * or an int result indicating whether or not the operation was successfully executed. When dealing with memory allocation you should always check the result.
I'd probably even go as far as making Dynamic_String opaque. Suggested interface in your header file:
typedef struct Dynamic_String Dynamic_String;
Dynamic_String* ds_allocate(size_t initial_size);
int ds_resize(Dynamic_String* ds, size_t new_size);
int ds_reserve(Dynamic_String* ds, size_t amount);
int ds_shrink(Dynamic_String* ds, size_t amount);
void ds_free(Dynamic_String* ds);
int ds_compare(const Dynamic_String* first, const Dynamic_String* second);
int ds_compare_cstr(const Dynamic_String* first, const char* second);
int ds_copy(Dynamic_String* destination, const Dynamic_String* source);
int ds_copy_cstr(Dynamic_String* destination, const char *src);
Dynamic_String* ds_duplicate(const Dynamic_String* ds);
Dynamic_String* ds_from_cstr(const char *str);
int ds_append(Dynamic_String* destination, const Dynamic_String* source);
int ds_append_cstr(Dynamic_String* destination, const char* source);
... // etc. other useful manipulation functions
const char* ds_getcontent(Dynamic_String* ds);
char* ds_getcontent_unsafe(Dynamic_String* ds); // all bets are of
... // query function like capacity, current size, is_empty/full etc.
Technical Details
ds_allocatedoes not check if there is already memory allocated and will simply leak if you pass in a structure which already has storage allocated. It thinkds_allocateshould simply allocate the structure and return it. Otherwise the programmer has to allocate theDynamic_Stringstructure and then call this init function which seems redundant. As user I'd prefer something along these lines:Dynamic_String* ds_allocate(size_t initial_size) { Dynamic_String *result = malloc(sizeof(Dynamic_string)); if (result == NULL) { return NULL; } ... }Basically return
NULLif any of the memory allocations fail orinitial_size < 1. Provide ads_allocate_default()if you want to give the programmer an option to just allocate an object with default size (I personally don't like these implicit "pass 0 or negative to obtain a default size allocation" implementations but YMMV).Technically the result of a pointer subtraction is
ptrdiff_tand notsize_t. The former is signed while the latter is unsigned. You should probably store the result of the subtraction in a local variable of typeptrdiff_tand check that it's not negative before returning it assize_t. If it's negative you apparently have hit a bug in the implementation.ds_append_cstringcan be greatly simplified by usingmemcpyrather than copying each byte individually. It will also be much faster.
Okay so basically I have a function that takes in a string and counts the lowercase tokens in it. I need to make a function that then returns an array of the lowercase tokens. I would need to use malloc to allocate enough memory for such array but I don’t know how to go about doing so.
Once the array is allocated how would I put the token strings into the array?
Any help is appreciated thank you