how to take input a string of length 10^6 in c++? - c++

we have to take input of a string such as :
1<=|S| <=10^6 (length of string)
and perform some operation , let's leave operation , I want to only know how to take input of such a long string like 10^6 ?
Can we take like this char S[1000001];
or which would be other better way?
Kindly, help

Forget about using a c-style string and use a std::string instead. A std::string can hold std::string::max_size characters. On most implementations today that should be 4294967294 characters.
The benefit with use a std::string is that it automatically grows to accommodate the size you need. Since the memory is dynamically allocated you don't have to worry about running out of stack space as well. You could run out of memory on the heap as you would need about 4 GB of RAM to hold a max size string thought.

Can we take like this char S[1000001];
You can... but if S is an automatic variable, you'll spend most of your stack-space on that one array and you'll probably run out (depending on available stack space and how much the rest of your program needs).
Large arrays like these should be allocated dynamically. Unfortunately, it's not easy to say how big arrays/objects should be allocated dynamically. It depends on a few things such as:
Amount of total stack space which depends on the platform and may be configurable at run- or linktime.
Amount of stack space needed by the rest of your program. This depends on how deep nested function calls do you have and how much memory your functions need.
I use a few kilobytes as a rule of thumb to decide if I'll need dynamic memory. Or a few dozen bytes inside a recursive function that is expected to go deep.
or which would be other better way?
std::string allocates it's buffer dynamically, provides ways to manipulate the string, makes sure that you don't forget the zero terminator and takes care of mamory management (which would be an issue if you did dynamic allocation manually). I highly recommend you use it.

it depends if the string characters are unicode or not
you could use:
char *txt = new char[1000000]
wchar_t *txt = new wchar_t[1000000];
also you can try using std::string or std::wstring like NathanOliver said

Use std::string.
Alternatively, if your data isn't being resized, you could opt to use a simple char array. Due to the size of the char array, I would suggest you allocate it with new and free it with delete. Otherwise, you may exhaust your stack size and cause a stack overflow.

Related

Is dynamic memory deletion also possible in arrays?

Supposingly I've declared a character array and take a string from the user as follows:
char s[100000];
std::cin>>s;
Now say the user has entered the string "Program". My character array will be as as follows:
'P''r''o''g''r''a''m''\0'......(99992 remaining indices with no/junk values)
Is there a way to free the space occupied those 99992 indices? Similarly if I've an integer array of size say 100000 and I'm using only first 10 indices during run time, is there a way to resize my array during the run time of my program. I know we can use vectors for this purpose but is the thing possible somehow using arrays? For integer arrays, I know we may declare arrays dynamically and then declare size as per our requirement but say I have array of 10 integers as follows:
1 2 3 4 5 6 7 8 9 10
Now, I want to use only first 9 indices and wnat to kind of delete the 10th index. In other words, along with dynamic allocation, is dynamic deletion also possible with arrays?
EDIT:
I know the thing is possible using STLs but I want to know if we can do the same thing in arrays?
No.
If you have arrays defined with a fixed size, you cannot release part of those arrays at run-time. Use a dynamically allocated array of some sort — probably a string or vector<int> for your two example arrays respectively, though a vector<char> might also work sufficiently well for you.
When you write:
char s[100000];
You are telling the compiler to stack 100000 bytes in the program stack.
However when you reserve memory dynamically:
char * = new char[100000];
You are asking the system to reserve 100000 bytes in the heap so you can handle that asked memory as you want, even tell the system to free it as a resource.
You can't free memory at the stack until your local context is finished. For example, exiting the function you where you declared char s[100000].
Check this question:
What and where are the stack and heap?
std::string is implemented using dynamic memory allocation at the heap and that is why it allows you to reduce its size.
that is not possible.
you may wrap your user input capturing in a subroutine that allocates stack space and allocates heap memory at the actual required length.
You are confused over when to use static allocation and when to use dynamic allocation.
Static allocation is used when the maximum number of items is known in advance, at compile-time.
Dynamic allocation is used when the number of items is unknown until run-time.
There exists no other case than the two above. You cannot mix them and it wouldn't make sense to do so.
The only case where you should allocate a static array char s[100000]; is the case where you know, at some point, that there will be 100000 items that the program needs to handle.
You designed your program to handle the worst case of 100000 items. It must still be able to handle that many. If the program needs to have an array of variable, unknown size, you should have used dynamic allocation.
If we ignore that C++ exists, then what you would have done in C is this:
char* s = malloc(sizeof(*s) * 100000);
...
s = realloc(s, some_strlenght);
Please note that huge static arrays allocated on the stack is bad practice in many operative systems. So you might have to declare the 100000 array on the heap anyway, even though you won't resize it. Simply because there is likely not enough stack space in your process to declare large, bulky variables like that.
(Also, because of the way C++ is designed, std::string and std::vector etc are always implemented with dynamic memory internally, even if you only use them with one fixed size.)

How do strings allocate memory in c++?

I know that dynamic memory has advantages over setting a fixed size array and and using a portion of it. But in dynamic memory you have to enter the amount data that you want to store in the array. When using strings you can type as many letters as you want(you can even use strings for numbers and then use a function to convert them). This fact makes me think that dynamic memory for character arrays is obsolete compared to strings.
So i wanna know what are the advantages and disadvantages when using strings? When is the space occupied by strings freed? Is maybe the option to free your dynamically allocated memory with delete an advantage over strings? Please explain.
The short answer is "no, there is no drawbacks, only advantages" with std::string over character arrays.
Of course, strings do USE dynamic memory, it just hides the fact behind the scenes so you don't have to worry about it.
In answer to you question: When is the space occupied by strings freed? this post may be helpful. Basically, std::strings are freed once they go out of scope. Often the compiler can decide when to allocate and release the memory.
std::string usually contains an internal dynamically allocated buffer. When you assign data, or if you push back new data, and the current buffer size is not sufficient, a new buffer is allocated with an increased size and the old data is copied or moved to the new buffer. The old buffer is then deallocated.
The main buffer is deallocated when the string goes out of scope. If the string object is a local variable in a function (on the stack), it will deallocate at the end of the current code block. If it's a function parameter, when the function exits. If it's a class member, whenever the class is destroyed.
The advantage of strings is flexibility (increases in size automatically) and safety (harder to go over the bounds of an array). A fixed-size char array on the stack is faster as no dynamic allocation is required. But you should worry about that if you have a performance problem, and not before.
well, your question got me thinking, and then i understood that you are talking about syntax differences, because both ways are dynamic allocating char arrays. the only difference is in the need:
if you need to create a string containing a sentence then you can, and
that's fine, not to use malloc
if you want an array and to "play" with it, meaning change or set the cells cording to some method, or changing it's size, then initiating it with malloc would be the appropriate way
the only reason i see to a static allocating char a[17] (for example) is for a single purpose string that you need, meaning only when you know the exact size you'll need and it won't change
and one important point the i found:
In dynamic memory allocation, if the memory is being continually allocated but the one allocated for objects that are not in use, is not released, then it can lead to stack overflow condition or memory leak which is a big disadvantage.

Size of memory allocated on heap

Can you check the size memory allocated on heap if the buffer contains '0' characters?
char *c = new char[6]; //random size memory
memset(c, 0, 6);
There's no reliable way to do that - you have to store that information yourself.
operator new[]() function can be implemented (and replaced by you) in whatever way so you just can't know the size unless you know the exact implementation in details.
In Visual C++ the default implementation for built-in types is to just forward calls to malloc() - then you could try _msize(), but again it's unportable and maybe even unreliable.
No, in general1 you can't. You have to store this information separately.
If you need to use that memory as a string or as an array, my advice is to use a std::string or std::vector, which do all this bookkeeping by themselves.
1. i.e. "as far as the standard is concerned"
I see that your question is MSVC++-specific; in that case, some heap-debugging helpers are provided, but they work only when the project is compiled in debug mode; I think there's some other compiler-specific function to get the allocated size, but it wouldn't work if custom allocators are used.
On the other hand, APIs like LocalAlloc let you know how big is the allocated chunk of memory (see e.g. LocalSize).
But again, I think that it's a cleaner design to keep track of this information by yourself.
No. You need to store the amount of allocated memory as a separate variable, and you need to take it with you whenever you want to do something with your allocated structure. This is cumbersome, but may be fast. As a safe and comfortable replacement use std::vector, boost::array, etc.

How to allocate more memory for a buffer in C++?

I have pointer str:
char* str = new char[10];
I use the memory block str points to to store data.
How can I allocate more bytes for the buffer pointed to by str and not lose old data stored in the buffer?
Use std::string instead. It will do what you need without you worrying about allocation, copy etc. You can still access the raw memory via the c_str() function.
Even std::vector<char> will work well for you.
new[] another buffer, copy the data there (use memcpy() for that), then delete[] the old one, assign the new buffer address to the pointer originally holding the old buffer address.
You cannot using the new construction. For that you need to use the good old malloc, realloc, and free (do not mix malloc/realloc/free and new/delete).
The realloc function is what you are searching for. You had to use malloc/free instead of new/delete to use it
If you are really using C++, the most correct solution would be to use std::vector. I assume that you are not using that information as a standard string, in that case you should use std::string (which is an specialization of std::vector, so no big deal). You are creating at least 10 chars. This gives me the hint that you are probably quite sure that you'll need 10 chars, but maybe you'll nedd more. Maybe you are worried about the performance problems involved in allocating and deallocating memory. In that case, you can create your string and then reserve the estimated capacity that you expect you'll need, so there won't be any reallocation at least until you get to that limit.
int main()
{
std::string s;
s.reserve( 10 );
// do whatever with s
}
As others have already pointed out, the use of std::string or std::Vector will get you the benefit of forgetting about copy, resizing or deleting the reserved memory.
You have to allocate a different, bigger string array, and copy over the data from str to that new string array.
Allocation is a bit like finding a parking place.
You're asking here if it's possible to add a trailer on your car that has been parked for a fews days.
The answer is, in C there exists something called realloc that allows you to do following thing.
If I have already enough place to add my trailer, do so. If not park in another place big enough for your trailer and your car, which is equivalent to copying your data.
In other words you'll get strong and random performance hits.
So what would you do in the real world? If you knew you might need to add some trailers to your car you'd probably park in a bigger place than required. And when exceeding the size required for the place, you'd move your car and your trailers to a place with a nice margin for future trailers.
That's precisely what the STL's string and vector is doing for you. You can even give them a hint of the size of your futures trailer by calling "reserve". Using std::string is probably the best answer to your problem.
You can use realloc: http://www.cplusplus.com/reference/clibrary/cstdlib/realloc/
I would add that this approach is not the favored c++ approach (depending on your needs you could use std::vector<char> for instance).

Way to increase memory allocated on free store

Is it possible to incrementally increase the amount of allocated memory on a free store that a pointer points to? For example, I know that this is possible.
char* p = new char; // allocates one char to free store
char* p = new char[10]; // allocates 10 chars to free store
but what if I wanted to do something like increase the amount of memory that a pointer points to. Something like...
char input;
char*p = 0;
while(cin >> input) // store input chars into an array in the free store
char* p = new char(input);
obviously this will just make p point to the new input allocated, but hopefully you understand that the objective is to add a new char allocation to the address that p points to, and store the latest input there. Is this possible? Or am I just stuck with allocating a set number.
The C solution is to use malloc instead of new -- this makes realloc available. The C++ solution is to use std::vector and other nice containers that take care of these low-level problems and let you work at a much higher, much nicer level of abstraction!-)
You can do this using the function realloc(), though that may only work for memory allocated with malloc() rather than "new"
having said that, you probably don't want to allocate more memory a byte at a time. For efficiency's sake you should allocate in blocks substantially larger than a single byte and keep track of how much you've actually used.
realloc
You appear to be using C++. While you can use realloc, C++ makes it possible to avoid explict memory management, which is safer, easier, and likely more efficient than doing it yourself.
In your example, you want to use std::vector as a container class for chars. std::vector will automatically grow as needed.
In fact, in your case you could use a std::istreambuf_iterator and std:push_back to std::copy the input into a std::vector.