stack-overflow in string decleration [duplicate] - c++

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Very large array on the heap (Visual C++)
i need to declare 10 strings each of length 100000 characters long.
int main(void)
{
long t;
cin>>t;
string str[10][100000];
for(long i=0;i<=t;i++)
{
getline(cin,str[i][100000]);
}
for(long i=1;i<=t;i++)
{
getStringSize(str[i][100000]);
}
system("PAUSE");
}
i wrote the code in VC++ but as soon as i compile the code i have a stack overflow.
if i keep the size of the string to str[10][10000] then the code works great. what do i need to make to code work?

This is not how you declare ten strings of 10,000 characters each - you declared a 2D array of strings, 10x10000.
This is how you do it the C++ way if you want each string to have 10,000 characters:
vector<string> str(10, string(100000, ' '));
Note that you need to specify the character that you want repeated 10,000 times. Since std::string is designed to grow dynamically, you can skip the 10,000 part altogether: the library will allocate as much memory as it needs.
vector<string> str(10);
You can also use array in C++11.

You need to allocate the memory dynamically: the stack in your case is not big enough to hold that much data
const size_t len = 10;
string* str[len];
for(long i=0; i<len; ++i) {
str[i] = new string[100000];
}
Note: Don't forget to delete the allocated memory when you no longer need it.
Note: To make life easier, use an appropriate container (e.g. vector<>) that does the memory management for you automatically
Update: your code has some other problems too:
for(long i=0;i<=t;i++) // t could be lager than 9
{
getline(cin,str[i][100000]); // you are accessing a non-existent element
}
Try instead:
long t;
cin>>t;
vector<string> str; // declare an auto-resizing container of strings
for(long i=0; i<t; i++)
{
string tmp; // this string will be able to store a lot of characters by itself
getline(cin, tmp); // read in the next line
str.push_back(tmp); // add the line to our container
}
for(long i=0; i<t; i++)
{
// do something with str[i] // values str[0]..str[t-1] are guaranteed to be valid
}

You need to allocate memory in heap. Like this..
string *str[10];
for(int i = 0; i < 10; i++)
str[i] = new string[100000];

If you use std::string then it's not fixed length - that's the whole point. what you maybe want is:
char str[10][100000];
which would give you 10 x char[100000]. As it stands you've got a matrix of 10 x 100000 strings.

Related

Dynamic resizing array code not working in C++?

I am trying to create an array, which doubles every time it is completely filled.
#include <iostream>
using namespace std;
int* array_doubler(int* array, int size){
int *new_array = new int[size*2];
for(int i = 0; i < size; i++){
new_array[i] = array[i];
}
delete[] array;
return new_array;
}
int main()
{
int N = 10; // Size of array to be created
int *array = new int[0];
for(int i = 0; i < N; i++)
{
if(array[i] == '\0')
array = array_doubler(array, i);
array[i] = i*2;
}
//Printing array elemensts
for(int i = 0; i < N; i++)
cout << array[i] << '\t';
cout << '\n';
return 0;
}
Problem is when I create dynamic memory with new, all the spots have the null character \0 value in them (not just the last spot). i.e. If i write:
int* p = new int[5];
then all the 5 blocks in memory p[0],p[1],p[2],p[3],p[4],p[5] have \0 in them, not just the p[5]. So the if(array[i] == '\0') in my main() calls array_doubler for every single iteration of for loop. I want it to fill the available spots in the array first and when it reaches the last element, then call array_doubler.
Problem is when I create dynamic memory with new, all the spots have the null character \0 value in them (not just the last spot).
Actually they have undefined values in them. 0 is a valid value for them to have, but tomorrow the compiler might suddenly decide that they should all have 1 instead of 0.
If you want to detect the end of an array, then you have to remember how big the array is. C++ doesn't do it for you. Actually, it does do it for you if you use std::vector, but I suppose that's not the point of this exercise.
I'm not sure why you'd want to do this, as std::vector offer this kind of feature, and are more idiomatic of c++ (see isocpp faq on why C-style array are evil).
One of the issue of C-style array is the fact that they donĀ“t know their own size, and that they don't have default value, thus stay uninitialized.
If for some reason you need to not use std::vector, the next best solution would be to wrap the array with it's size in a structure or a class (which is kinda what std::vector is doing), or to initialize your array using std::memset (which is the C function you would use if you were in C).
Do keep in mind that this is not considered as good practices, and that the STL offer plenty of solution when you need containers.

Find Number of Palindrome Strings in Array Program Errors

I am writing code that finds the number of palindrome strings in a given array of strings. I think I have the right idea, but I am getting weird errors when I run it. What exactly am I doing wrong?
int countPalindromes(string s) {
int size = s.size();
int counter = 0;
string forwardSum = "";
string backwardSum = "";
for(int i = 0; i < size; i++){
for(int j = i; j < size; i++){
forwardSum.push_back(s[j]);
backwardSum.push_back(s[(n - 1)-j]);
if(forwardSum == backwardSum){
counter++;
}
}
}
return counter;
}
string forwardSum[] = {};
This is an array of zero size (which I don't believe is legal but we'll let that pass)
forwardSum[i] = forwardSum[i] + s[j];
This is an attempt to access the ith element of an array which has zero size.
That's bad.
I'm not really following your code (it's late at night), but I think you probably want forwardSum and backwardSum to be strings not arrays of strings. And you probably want to use push_back to add characters from s to those strings. I.e.
string forwardSum;
...
forwardSum.push_back(s[j]); // add s[j] to forwardSum
But if you really do want forwardSum to be an array, then the sensible thing to do would be to use a vector instead.
vector<string> forwardSum(size); // a vector of strings with the given size
Now that should at least not crash with the rest of your code.

Not able to input strings using getline() .It is reading only one string

char* name[4];
int j=0;
while(cin.getline(name[j],80))//input given:you(ent)me(ent)he(ent)she
cout<<name[j++];
this code is reading only one string upto one newline.should'nt it read all 4 strings and print them ?and is this a good way to input string using getline?
Problem: You are not allocating the memory properly. You are declaring an array of pointers not an array of c style strings.
Possible Solutions: You need to read about pointers and memory allocation first. You can either allocate memory first to each of the four pointers that you declared name[0], name[1], name[2], and name[3] using the following code:
char* name[4];
for (int i = 0; i < 4; i++)
{
name[i] = new char[80];
}
OR you can use a 2D array for which the code is posted below:
char name[4][80];
int j=0;
while(j<4 && cin.getline(name[j],80))
{
cout<<name[j++];
}
I made a bit of correction. And it works on my computer.
char* name[4];
for (int i = 0; i < 4; i++)
name[i] = new char[80];
int j = 0;
while (j < 4)
{
cin.getline(name[j], 80); //input given:you(ent)me(ent)he(ent)she
cout << name[j++] << endl;
}
You need to read some more about pointers, arrays and memory management in C++ i guess. You try to operate on C array of strings, but you didn't initialize it properly. You need to allocate memory before you use such pointers. Currently your program results in UB so you are actually really lucky that it did anything same at all.
Another issue is that, when you reach the end of your input, when j=4, you will still attempt to perform cin(getline(name[j], 80) but you are passing the name[4] as a parameter, which may be a cause of another UB, even if you allocate the memory correctly beforehand.
Other then that you are writing in C++, so use C++ string and vector instead of C arrays.
This is easily done with strings and std::getline:
#include <iostream>
#include <vector>
using namespace std;
int main(){
vector<string> names;
string name;
while(getline(cin, name)){
names.push_back(name);
cout<<name<<endl;
}
return 0;
}

dynamic memory allocation of strings in cpp

so here's the thing I've been working on a code for 5 hours now and logic looks good the program seems to do it's job, the only thing that keeps bugging me is dynamic memory allocation of strings. The question does not specify the initial number of strings user has to enter. Here's what I've been trying to do to dynamically take the strings :
int t;
cin>>t //number of strings user wishes enter
char *s1[1000009]; //1000009 is the maximum number of digits each string can have
for(i=0;i<t;i++)
{
s1[i]=(char *)malloc(1000009)
cin>>s1[i];
}
not sure if it is the right way or not. A way through which i could store a 2D character array would also do if not dynamic strings.
Thanking you,
gaurav
Use a vector of strings instead of using malloc/new.
int t;
std::cin >> t;
std::vector<std::string> strings(t); //Create t strings
for(int i = 0; i < t; i++)
std::cin >> strings[i]; //Read into each string
Since you tagged this question as C++ I would do it like this:
std::vector<std::string> s1(1000009);
That's all - no need to use malloc, no need to take care about destruction.
If you are using C++ use the Tools you have available.
i would do it like this :
int i = 0;
char **s1;
s1 = (char **)malloc(t * sizeof(char *));
while (i < t)
{
s1[i] = (char *)malloc(1000009 * sizeof(char));
i++;
}
the first malloc create you t line.
The second one fill alloc 100000009charactere for each lines

why char array's size is same using sizeof()

I meet a problem with the char array size. I pass an char array into the function and after run the function, I still want to use sizeof to check the size of the array, it won't give me the new size of the array, but the old size? I would like to know why? Thank you very much!
#include<iostream>
using namespace std;
void replacement(char* arr, int len){
int count=0;
for(int i=0; i<len; i++){
if(arr[i]==' '){
count++;
}
}
int newlen=count*2+len;
//arr[newlen]='\0';
int k=newlen-1;
for(int i=len-1; i>=0; i--){
if(arr[i]!=' '){
arr[k--]=arr[i];
}
else{
arr[k--]='0';
arr[k--]='2';
arr[k--]='%';
}
}
}
int main(){
char arr[]="ab c d e g ";
cout<<sizeof(arr)<<endl;
replacement(arr, sizeof(arr));
int i=0;
while(arr[i]!=NULL) cout<<arr[i];
}
You can't change an array's size. If you want to know the length of the string in the array, use strlen() -- this counts the number of characters before the null terminator.
Even better would be to use C++ std::string class.
Right, so you are trying to replace spaces with "%20", right?
Since C++ (or C) doesn't allow an existing array to be resized, you will either need to have enough space in the first place, or use an array allocated on the heap. Then allocate a new "replacement" string in the replacement function and return that.
The proper C++ method of doing this is of course to use std::string, in which case you could just pass it in as a reference, and do the replacement in the existing variable:
void replacement(std::string* str, int len){
std::string perc20 = "%20";
std::string space = " ";
while((pos = str.find(space, pos)) != std::string::npos)
{
str.replace(pos, space.length(), perc20);
pos += perc20.length();
}
}
Much easier...
You can use sizeof() to find the size of only static arrays when the size is known at compile time. Hence it will always return the size of the array as determined at compile time.
Your program technically has Undefined Behavior because your use of sizeof returns the size in bytes of your char array. But a char implicitly contains a null byte \0. That means the for loop is iterating 1 past the length of the array.
It's recommended that you use std::string along with its size member function instead.