admin822
admin822

Reputation: 1

How to assign several different strings to a char* array

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

Answers (4)

Davide Spataro
Davide Spataro

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

A. H.
A. H.

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

VikasPushkar
VikasPushkar

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

melpomene
melpomene

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

Related Questions