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.
NOTE: My examples are not checking for NULL returns from malloc()... you really should do that though; you will crash if you try to use a NULL pointer.
First you have to create an array of char pointers, one for each string (char *):
char **array = malloc(totalstrings * sizeof(char *));
Next you need to allocate space for each string:
int i;
for (i = 0; i < totalstrings; ++i) {
array[i] = (char *)malloc(stringsize+1);
}
When you're done using the array, you must remember to free() each of the pointers you've allocated. That is, loop through the array calling free() on each of its elements, and finally free(array) as well.
The common idiom for allocating an N by M array of any type T is
T **a = malloc(N * sizeof *a);
if (a)
for (i = 0; i < N; i++)
a[i] = malloc(M * sizeof *a[i]);
As of the 1989 standard, you don't need to cast the result of malloc, and in fact doing so is considered bad practice (it can suppress a useful diagnostic if you forget to include stdlib.h or otherwise don't have a prototype for malloc in scope). Earlier versions of C had malloc return char *, so the cast was necessary, but the odds of you having to work with a pre-1989 compiler are pretty remote at this point. C++ does require the cast, but if you're writing C++ you should be using the new operator.
Secondly, note that I'm applying the sizeof operator to the object being allocated; the type of the expression *a is T *, and the type of *a[i] is T (where in your case, T == char). This way you don't have to worry about keeping the sizeof expression in sync with the type of the object being allocated. IOW, if you decide to use wchar instead of char, you only need to make that change in one place.
How to dynamically allocate an array and add strings to it? (In C)
c - Dynamically allocate an array of strings - Stack Overflow
c++ - dynamically allocate string literal - Stack Overflow
is this the correct way to store a dynamically allocated array or dynamically allocated strings?
Videos
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
Your allocation is not the best, and printf argument arr[i] expects a char* but you pass it an int (a char if you'd like).
Here is how you should do it, with comments:
Live demo
#include <stdio.h>
#include <stdlib.h> //for malloc
int main(){
int n;
int i;
printf("Give me a number:");
scanf("%d", &n);
//declare a variable of pointer to pointer to char
//allocate memory for the array of pointers to char,
//each one capable of pointing to a char array
char **arr = malloc(n * sizeof *arr);
if(arr == NULL){ //check for allocation errors
perror("malloc");
return EXIT_FAILURE;
}
//allocate memory for each individual char array
for(i = 0; i < n; i++){
arr[i] = malloc(40); //char size is always 1 byte
if(arr == NULL){ //check for allocation errors
perror("malloc");
return EXIT_FAILURE;
}
}
for (i = 0; i < n; i++){
printf("Give me a word: ");
//limit the size of read input to 39 charaters to avoid overflow,
//a nul character will be added by scanf
scanf("%39s", arr[i]);
}
for (i = 0; i < n; i++){
printf("%s\n", arr[i]);
}
for(int i = 0; i < n; i++){ //free the memory for each char array
free(arr[i]);
}
free(arr); //free array of pointers
return 0;
}
You can also do this with less code using a pointer to array of 40 chars, this will simplify the memory allocation and deallocation:
Sample with comments:
Live demo
#include <stdio.h>
#include <stdlib.h> //for malloc
int main(){
int n;
int i;
printf("Give me a number:");
scanf("%d", &n);
//declare a pointer to array of chars and
//allocate memory for all the char arrays
char (*arr)[40] = malloc(n * sizeof *arr);
if(arr == NULL){ //check for allocation errors
perror("malloc");
return EXIT_FAILURE;
}
for (i = 0; i < n; i++){
printf("Give me a word: ");
scanf("%39s", arr[i]);
}
for (i = 0; i < n; i++){
printf("%s\n", arr[i]);
}
free(arr); //free allocated memory
return 0;
}
This:
for(i=0;i<n;i++){
printf("Give me a word: ");
scanf("%s",&arr[i]);
}
is probably not what you want.
You probably want this instead:
for(i=0; i<n; i++){
printf("Give me a word: ");
scanf("%s", arr + i*40);
}
then later:
for(i=0; i<n; i++){
printf("%s", arr + i*40);
}
Remember that a string in C is just an array of characters.
Thus when defining char *arr, you are creating a single string. Had you done char **arr it would have been an array of strings, which is what you want.
However, I find that allocating/freeing arrays of arrays on the heap to be rather inconvenient, and prefer 'flattening' them into a single array.
This is exactly what you were doing with arr = malloc(n*40), but then later you treated this array of characters as an array of strings when you did this:
for(i=0; i<n; i++){
printf("Give me a word: ");
scanf("%s", &arr[i]);
}
Note that this is actually perfectly legal (scanf wanted a char* and you gave it one), but it's a logical error since you are giving it the n-th character when you wanted to give it the n-th array.
And oh yes, don't forget to free(arr) later.
What you can and should do is use std::string and initialize it from a literal like
std::string mystring{"Hello"};
When you do that, mystring is allocated on the stack and its content is initialized from "Hello" (perhaps by copying it, but read about small string optimization, or short string optimization).
When that string is destroyed (e.g. at the end of the containing block), its storage (and perhaps the internal copy, if one was made) will be released.
If you insist for having a pointer to a heap-allocated C string, you could use strdup (then release it with free, not delete); if you want a raw array of char, you could use
char* p = new char[sizeof("Hello")]; // or new char[6]
strcpy(p,"Hello");
but this works only for literal strings like "Hello" and you should use the same literal string "Hello" twice (or use strlen("Hello")+1 instead of sizeof("Hello"), which is 6, because of the terminating zero byte).
Notice that in all cases you never dynamically allocate a string literal. A compiler is permitted to (and often does) put the literal string in the read-only code segment of the produced binary executable. What you can do is allocate in heap a memory zone filled with a copy of that literal string (or use a pointer const char* pc = "hello";)
You can never allocate a literal, dynamically or otherwise. Literals are literals; they are baked-in by definition.
You can certainly dynamically allocate a char and initialise it from a literal, as you've done in your example.
As for your question, though, initialising from string literals is a bit more tricky, because you can only get your own char[N] from string literal initialisation using the normal initialisation syntax:
char[] str = "hello"; // special rules apply here
and it is not possible to initialise a dynamically-allocated array. There's just no way to do it in the new[] syntax.
You could dynamically allocate a pointer to a string literal:
const char** s = new const char*("hello");
but that's totally useless.
The closest I think you can get is:
char* str = new char[5]{'h','e','l','l','o'};
But, honestly, just use a std::string instead:
std::string str("hello");
It was invented specifically to solve these kinds of problems.
I think I'm doing this correctly but I just want to make sure.
int main()
{
char **strings;
char *stringOne = "test1";
char *stringTwo = "test2";
char *stringThree = "test3";
strings = malloc(sizeof(char) * 3);
strings[0] = calloc(5, sizeof(char));
strings[1] = calloc(5, sizeof(char));
strings[2] = calloc(5, sizeof(char));
strings[0] = stringOne;
strings[1] = stringTwo;
strings[2] = stringThree;
printf("%s\n", strings[0]);
printf("%s\n", strings[1]);
printf("%s\n", strings[2]);
free(strings[0]);
free(strings[1]);
free(strings[2]);
free(strings);
}In the code above, everything compiles and runs just fine, but the thing I'm most unsure of is with
strings = malloc(sizeof(char) * 3);
I don't know if I would need to allocate 15 bytes since I have 3 strings of 5 bytes each, or if because strings as a pointer only points to the first char of each of the three strings, I would only need to allocate 3 bytes.
also, I know that strings in memory hold what I believe is called the null terminator character (\0) at the end of every string, and I am unsure if in this part of the code
strings[0] = calloc(5, sizeof(char)); strings[1] = calloc(5, sizeof(char)); strings[2] = calloc(5, sizeof(char));
I would need to request one extra byte of memory for each string to store said null terminator character.
char *s;
s = malloc(1024 * sizeof(char));
The above declares the variable s and assigns to it the address of a dynamically allocated chunk of memory large enough to hold 1024 chars. However, no error checking is performed, so s may be NULL at this point.
scanf("%s", s);
This reads data from the input stream until a whitespace is encountered (or input terminates) and stores it in the allocated chunk of memory whose address is contained in s , appending a '\0' after the data that is read. If there is more than 1023 bytes of data or if the previous malloc returned NULL, undefined behavior occurs. (This is bad.)
s = realloc(s, strlen(s) + 1);
This is an attempt to shrink the amount of memory being used so that s now points to a smaller chunk of memory which is just big enough to hold the string that was read. The +1 is in the 2nd argument to realloc because C stores strings as null terminated arrays, and it takes an extra character to store that terminator. This is possibly a memory leak, since realloc can return NULL, in which case the original memory is lost and the program hasn't stored that value anywhere so cannot free it.
Do not ever use "%s" in a call to scanf. If you have allocated N bytes for an array, use a width modifier of N - 1. Often this means dynamically generating the format string, but often it is as simple as:
char s[32]; scanf("%31s", s);
Always check the value returned by malloc, realloc, and scanf.
An alternative approach to shrinking the memory to the minimum needed for user input would be to allocate a second chunk of memory based on the size of the input, copy the string into it, then free the original.
We're just going to assume malloc and scanf worked as we meant them tto and not error check for the purposes of this answer.
char *s1 = malloc(1024);
scanf("%1023s", s1);
char *s2 = malloc(strlen(s1) + 1);
strcpy(s2, s1);
free(s1);
You might also use strdup.
How does std::string in c++ allocate memory?
as needed, transparently to the user.
i know of the 'new' keyword in c++ and 'malloc' in c but when i try something like this, my program stops working.
char* str = new char[strlen(str) + 1];
cin>>str;
Well ... yeah; strlen counts the consecutive characters at the provided address, until it encounters a zero. In your case, the specified address is not set (it will be set after strlen is evaluated) so you are effectively calling strlen with some random input - there is no way that would work.
I also know of vectors in C++ but not a big fan of using them,
You really really (really really really) should be. They are an extremely thin (read: fast) wrapper over creating dynamic contiguous memory blocks (exactly what you are trying to solve), that provide type safety, memory bounds safety and automatic memory management.
i would like to know if there's a way to dynamically allocate memory without having to allocate a size before
No.
something close but not as sophisticated as the string.h library.
The string.h is not able to allocate memory without knowing the size. It computes the size every time it needs to allocate memory, at a runtime cost (by, for example, using strlen when needed).
How does the string library get unlimited input from user without the programmer specifying buffer size?
It doesn't. What it does (in rough pseudocode) is this:
- compute the size of the input (probably requesting it from the input steam through an API)
- compute the new size the string should have after reading
- allocate memory (depending on new size), if required
- copy data in new memory
- delete old memory and use new instead (if any old memory/value was set)
If you're not a fan of std::vector you may not want to hear this but, by default, it'll work pretty much the same as std::vector.
When a string reads from a stream, it push_back's each character. What it does when it runs out of space is actually defined by the allocator you've used for the string. The default will be to keep doubling as it does with vectors.
You can change this, of course, by changing the allocator but it sounds like that's not really your question. There's no way to pre-allocate an unknown amount of memory. You've only really got 3 options: allocate none, allocate a fixed amount or allocate an initial amount and then dynamically change it as needs be. Strings and vectors do the latter so that they do what you'd expect but with the trade off that you may over allocate memory depending on the exact length of the string.
So lets say i do int x=5; so i create a variable of 4 bytes that stores a value of 5
then i do int *y= malloc(sizeof(int)); here i created a pointer that gave me a memory location in the RAM and i can do *y=5; to store 5 in it. What exactly is the benefit of using dynamic allocation here?
plus in case of strings how do i dynamically allocate just enough memory to store name of some guy in c without knowing it before hand how long the name is?
like char name[4]; means i have an array of 5 char out of which im supposed to use 4. But here i need to make sure name is of length 4 always.
but char *name = malloc(5*sizeof(char)); dynamically allocates the same memory but i still need to make sure length of name stays 4 plus one extra for the null.
how is this implemented to take values of any length?
A number of issues:
memory size is one too small.
while(c!='\n')first testceven though it is uninitialized.string()should pass the address of achar *as instring(char **)Better to use
size_trather thanintwhen working withstrlen().
Minor:
EOF is not detected. Use
int crather thanchar cto aid in detection.Certainly inefficient to
realloc()each loop.Casting of
malloc()/realloc()unnecessary.Good to check for out-of-memory.
Use
int main(void)rather thanint main()for portability.size_t string(char **str) { assert(str); int c; size_t i = 0; size_t size = 0; *str = NULL; printf("Enter String : "); while((c = getc(stdin)) !='\n' && c != EOF) { if (i == size) { size *= 2 + 1; // double the size each time *str = realloc(*str, size); assert(*str); } (*str)[i] = c; // store read character by making pointer point to c i++; } *str = realloc(*str, i+1); // right-size the string assert(*str); (*str)[i] = '\0'; // at the end append null character to mark end printf("\nThe entered string is : %s",*str); return i; }
You need to pass a referejce to a pointer (int string(char **str)) because you're changing the value of str inside the function.
In main you should call string(&str)
C is willing to automatically size, allocate, and initialize arrays for you. With one exception, however, there is no way to automatically initialize a pointer that points to some other array.
Here is automatic sizing and allocation of an array:
int a[] = {1, 2, 3};
The brackets [] are empty -- you don't have to explicitly specify the size -- because the compiler can see from the initializer that the array should have size 3.
Here is another example, using char:
char s1[] = {'H', 'e', 'l', 'l', 'o', 0};
Here is a much more convenient shortcut form:
char s2[] = "world";
Here is the exception I was talking about:
char *s3 = "hidden";
In this case, the compiler allocates a hidden, unnamed array containing the string "hidden", then initializes s3 to point to it. This is just about perfectly equivalent to the more explicit setup
char a2[] = "hidden";
char *s3a = a2;
except for the visibility of the intermediate array a2.
Putting all this together, you can initialize an array of pointers to char like this:
char *strarray[] = { "Hello", "world" };
This is equivalent (again, except for the visibility of the actual arrays holding the strings) to the more explicit
char a3[] = "Hello";
char a4[] = "world";
char *strarray2[] = { a3, a4 };
But you can not directly do anything along the lines of
char **dynstrarray = { ... };
The reason you can't do it is because dynstrarray is fundamentally a pointer, and there's no general mechanism in C to automatically allocate something for a pointer like this to point to. Again, the only time C will automatically allocate something for a pointer to point to is the special case for pointer to char, as demonstrated by s3 above.
So if you want to initialize a pointer like dynstrarray, your only choice is to do it explicitly, yourself. You could initialize it to point to an array of pointers to char that you had already constructed, like this:
char a3[] = "Hello";
char a4[] = "world";
char *strarray2[] = { a3, a4 };
char **dynstrarray[] = strarray2;
Or, more commonly, you would use malloc to dynamically allocate some memory for dynstrarray to point to. In that case (but only in that case) you would also have the option of resizing dynstrarray later, using realloc.
You can create an array of char * as follows:
char *baz[] = {"Hello,", "world!"};
I need a little help with a problem. Just a little guidance in the logic behind solving a problem.
I have to create a program that keeps asking for a string input, and storing it in an array, until a user inputs the string "quit". The only thing I can assume, is that the string will be no longer than 100 chars, but there is no limit on how many strings a user might input.
I think I would have do to this in a while loop to keep asking for an input, and then use strcmp() to see when a person enters "quit" in order to break the loop.
My problem is, I'm not too sure how to dynamically allocate an array.