Reputation: 1
guys I was trying to put several different strings like these:
cap
to
cat
card
two
too
up
boat
boot
into a char* array like this:
char* result[9]
and after assigning every one of those strings into the array with a for loop, I found that all the elements in the array is the same, which is "boot".
My code and result are down here:
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int main()
{
char* result[9];
for(int counter=0;counter<9;counter++)
{
string temp;
getline(cin,temp);
result[counter]=(char*) temp.c_str();
cout<<result[counter]<<endl;//correct
}
cout<<endl;
cout<<endl;
for(int counter=0;counter<9;counter++)
cout<<result[counter]<<endl;//false
}
This line works well,
cout<<result[counter]<<endl;//correct
and it prints all the different words like:
cap
to
cat
card
two
too
up
boat
boot
but somehow, this line
cout<<result[counter]<<endl;//false
it only prints "boot" nine times. I really can't see the reason here and I am hoping you guys can give me a hand, thx!
Upvotes: 0
Views: 341
Reputation: 7482
There is a problem with your code and specifically with this line:
result[counter]=(char*) temp.c_str();
Since temp
lives within the for loop and c_str()
returns an address that will be invalid once temp is destructed, your code suffers from UB.
The address is invalid because c_str()
:
Returns a pointer to the underlying array serving as character storage.
Once temp is out of scope, that underlying array is gone, but you now have a reference to it outside its scope!
You should allocate new memory for each of the string in result
maybe using strdup
as in the following:
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int main()
{
char* result[9];
for(int counter=0;counter<9;counter++)
{
string temp;
getline(cin,temp);
result[counter]=strdup(temp.c_str()); //now it is correct!
cout<<result[counter]<<endl;
}
cout<<endl;
cout<<endl;
for(int counter=0;counter<9;counter++)
cout<<result[counter]<<endl;
}
Do not forget that strdup
will allocate memory that needs to be deallocated manually.
Upvotes: 0
Reputation: 952
Better yet use std::vector<string>
std::vector<std::string> result;
for(int counter=0;counter<9;counter++) {
std::string temp;
std::getline(std::cin, temp);
result.push_back(temp);
}
If you want to use pointers, you need to copy the contents of str.c_str() as it is a temp that is destroyed after each iteration.
Upvotes: 1
Reputation: 422
In following loop you are declaring temp string and using it again and again. so in each iteration of the loop, same pointer is being edited. hence the last value stays and rest are overwritten.
for(int counter=0;counter<9;counter++)
{
string temp;
getline(cin,temp);
result[counter]=(char*) temp.c_str();
cout<<result[counter]<<endl;//correct
}
Instead declare your temp string outside as a string array with capacity of 9.
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int main()
{
char* result[9];
string temp[9];
for(int counter=0;counter<9;counter++)
{
getline(cin,temp[counter]);
result[counter]=(char*) temp[counter].c_str();
cout<<result[counter]<<endl;//correct
}
cout<<endl;
cout<<endl;
for(int counter=0;counter<9;counter++)
cout<<result[counter]<<endl;//false
}
Upvotes: 0
Reputation: 85767
{
string temp;
getline(cin,temp);
result[counter]=(char*) temp.c_str(); /* 1 */
cout<<result[counter]<<endl;//correct
} /* 2 */
In the line marked 1
, you're storing a pointer to the underlying string data of temp
in result[counter]
. None of the string contents are copied; you're just storing the address of the existing data in temp
. (By the way, what is the (char*)
cast for? .c_str()
already returns a pointer to char
.)
In the line marked 2
, temp
is destroyed (it was a local variable in this block). Now result[counter]
contains an invalid pointer: The object it was pointing to doesn't exist anymore.
Any attempt to use the contents of result
after this result in undefined behavior.
One way you could fix this is to use an array of strings instead of an array of pointers:
string result[9];
for(int counter=0;counter<9;counter++)
{
getline(cin,result[counter]);
cout<<result[counter]<<'\n';
}
(I've also removed endl
because there is no need to explicitly flush the stream after every single string.)
This also simplifies the code a bit because you no longer need a temp
variable: You can just getline
directly into the array.
Upvotes: 3