Is it correct to use stringstream with char* [closed] - c++

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I have a vector of string object :
I need to convert it into char* using stringstream and store char* in a vector.
is it right way to do it?
//! strvector contain string objects and newcharvector needs to be populate.
for(int i =0 ; i < strvector.size(); i++)
{
std::string &obj = strvector[i];
std::stringstream ss;
char* str;
ss << obj;
ss >> str;
newcharvector.push_back(str);
}

A char* is a pointer that points to a memory area that contains the string.
In your example: Where is this memory/the string?
Of course, stringstream (which should not be used anymore, use istringstream or ostringstream) internally stores the string, and you could retrieve the string from it, but the moment that the stringstream object is deleted, the internal string is deleted and your char* pointer points to free/unused memory (which will most likely be re-used by the next instance of the stringstream variable).
For storing a char* in a vector you would have to take a tour of the dynamic memory allocation wonderland. Don't (yet).
Why don't you store std::strings in your vector?

Don't use raw pointers!
#include <vector>
#include <string>
#include <iostream>
#include <memory>
int main()
{
std::vector<std::string> strvector{ "foo", "bar", "baz", "qux", "thud" };
std::vector<std::shared_ptr<char[]>> newcharvector;
for (auto const &s : strvector) {
newcharvector.push_back(std::shared_ptr<char[]>(new char[s.length() + 1]));
std::strcpy(newcharvector.back().get(), s.c_str());
}
for (auto const &s : newcharvector)
std::cout << s << '\n';
}

Is it right way to do it?
It's rather roundabout. Better just use c_str() to get the string representation represented as char*, and then use strdup() to persist that string (if that's necessary, because the pointer returned by c_str() is invalid as soon as you modify the std::string or it goes out of scope)
std::vector<std::string> strvector{ "foo", "bar" };
std::vector<char*> pointers;
for (std::string &s : strvector) {
pointers.push_back(_strdup(s.c_str()));
}
for (char* p : pointers) {
printf("string: %s\n", p);
}

Related

How to read uint8_t data that was converted from vector of string?

I need to use a function func(uint8_t* buffer, uint size); supposing I can't change its parameters, I want to pass it a string.
I have a vector<string> that I must convert to uint8_t* and then read it and convert it back to vector<string>.
I tried this code for reading (printing) the vector.data() output but it prints garbage:
#include <cstdint>
#include <string>
#include <vector>
#include <iostream>
int main() {
std::string a1 = {"ath"};
std::cout <<"1: "<< a1<<" end\n";
std::vector<std::string> vec;
vec.push_back(a1);
uint8_t *ptr = reinterpret_cast<uint8_t*>(vec.data());
std::cout <<"2: "<< ptr[0]<<" end\n";
}
output:
1: ath end
2: � end
questions:
why this doesn't work?
I saw in some links that they init a std::string with char* array like this:
char *ptr={'a'};
std::string myStr(ptr);
I suppose this works because of added '\0', is this related to my problem?
why this doesn't work?
This can't work, because a std::string is not just a contiguous piece of memory containing nothing but the characters in the string. You're simply mistaken about what std::string is!
Using a vector here is plain not the right approach. A vector does not contain your string's contents. Just the std::string objects themselves, which are not the string data.
Instead, you want to make one long std::string:
std::string foo {"foo"};
std::string bar {"bar "};
std::string baz {"bazaz"};
std::string complete = foo + bar + baz;
auto* whole_cstring = reinterpret_cast<uint8_t*>(complete.c_str());
// call your C-string-accepting function
func(whole_cstring, complete.length());
If you actually do have a std::vector of std::strings to begin with, the concatenation can be done in a simple loop:
std::vector<std::string> my_vector_of_strings;
// insert strings into the vector
/// … ///
std::string complete;
for(const auto& individual_string : my_vector_of_strings) {
complete += individual_string;
}
auto* whole_cstring = reinterpret_cast<uint8_t*>(complete.c_str());
// call your C-string-accepting function
func(whole_cstring, complete.length());
… missing \0 … I suppose this works because of added '\0', is this related to my problem?
No, that's completely unrelated.
I have a vector that I must convert to uint8_t*
std::vector<std::string> vec;
"Converting" has a relatively strong definition in the C++ (and other languages) world. If I understand what you mean, I'd suggest the following:
#include <string>
#include <vector>
#include <algorithm>
int main(){
std::vector<std::string> vec;
// populate
std::vector<uint8_t*> vec2(vec.size());
std::transform(begin(vec), end(vec), begin(vec2), [](auto& s){ return reinterpret_cast<unsigned char*>(s.data()); });
}
Alternatively, if possible, you can use a std::basic_string<uint8_t> instead of std::string (a/k/a std::basic_string<char>) to avoid reinterpreting its content.

Using a const void* with string [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 10 months ago.
Improve this question
In c++11, I have a function that takes a const void* data and a size_t dataSize, so I have to pass to the function the pointer to a string.
function_test( const void* Data, size_t DataSize)
{
std::string received_data((const char*)Data, DataSize);
if (received_data=="1")
{
//do stuff... I need enter here
}
}
I use:
std::string test1 = "1";
function_test(&test1, sizeof(test1));
I expect that received_data is equal to "1" but it's not, why? How can I fix this?
Why test3 is not "1"?
Because std::string is not an array of char. A pointer to std::string is not a pointer to the buffer that std::string class manages where the content of the string is stored. When you reinterpret a pointer to a std::string object as a pointer to char, you get a meaningless representation of the internals of the std::string object.
I need that test3 is equal to "1"
Then use the copy constructor:
std::string test3(test1);
P.S. Don't use C-style casts. Use C++ style static_cast etc. This will make it easier to understand the program that you are writing.
Assuming you need to pass a const void* to a legacy C-style API, you need to use:
std::string test;
reinterpret_cast<const void*>(test.c_str());
C++ is not C.
What you show is close to the following C snippet:
char test1[] = "1";
const void* test2 = test1; // test1 decays to a pointer
char test3[sizeof(test1)];
strcpy(test3, test2);
But a C++ std::string is a complex container with internal data for housekeeping and an array of characters accessible through the data or c_str method:
std::string test1 = "1";
const void* test2 = test1.c_str();
std::string test3(static_cast<const char*>(test2), sizeof(test1));

Assigning string* to char* c++ [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I need to read a file in c++ and save every line(in a vector) as i will be processing them later.
I also need to save a vector of char* that will point to the first position of each string*.
The problem is that I don't know how to assign the string* to char*.
FYI, i can not use const char*, it has to be char*.
Code:
void ClassA::readFile() {
std::ifstream file("test.txt");
std::string* str = new string();
while (std::getline(file, *str))
{
_aVector.push_back(*str);
char *c = &str[0]; <-- This works if string is not declared as string*
char *c = .... <--What is the equivalent for string*
str = new string();
someFunction(c); <-- This function saves the *c in a vector.
}
}
Though the std::string protocol gives you access to the underlying memory, e.g. by calling member c_str(), these pointers are all const. If you cast it to a non-const pointer, you risk undefined behaviour if a function beyond your control then modifies the content through such a pointer.
Since C++17, the data-method gives you access to a non-const pointer to the underlying data.
Anyway, note that a string-object will - again beyond your control - replace the underlying memory if necessary, and your pointers might become invalid then. So I'd say that it's generally not a good idea to store pointers to the contents of string objects.
The only way to get a char*-pointer to the contents of an std::string I see is to copy the contents of the string, e.g. by using strdup. Thereby you avoid undefined behaviour from unintended modifying access, and you decouple the char* from the memory managed by the string object.
See the following code illustrating this:
int main() {
std::vector<std::string> aVector;
std::ifstream file("test.txt");
std::string str;
while (std::getline(file, str))
{
aVector.push_back(str);
char *c = strdup(str.c_str());
someFunction(c); // <-- This function saves the *c in a vector.
}
}

How to make istringstream more efficient? [duplicate]

This question already has answers here:
Creating an input stream from constant memory
(2 answers)
Closed 6 years ago.
#include <sstream>
using namespace std;
const char* GetHugeString();
int main()
{
const char* p = GetHugeString();
//
// Below will copy the huge string into a std::string object!
//
istringstream sstrm{p};
return {};
}
istringstream doesn't need a copy of the huge string; a null-terminated string pointer is enough. But istringstream's ctor only take std::string, rather than std::string_view(c++1z only), as its argument.
Is there a work-around to make std::istringstream more efficient in such a case?
You can simply assign the buffer used internally in the istringstream:
istringstream stream;
stream.rdbuf()->pubsetbuf(p, strlen(p));
This does not copy the string. Do note that pubsetbuf() wants char* not const char*, but it doesn't actually modify the string, so you might const_cast your C string pointer before passing it.

How to convert std::string to const char*? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Convert std::string to const char* or char*
void Foo::bar(const std::string& foobar) {
// ...
const char* foobar2 = (char*)foobar;
// ...
}
That does not work and I get an error during compilation about invalid casting.
Is there some other way to convert std::string to const char*?
Use foobar.c_str().
You might find this link useful: http://www.cppreference.com/wiki/string/start
std::string::c_str() gets you a const char* pointer to a character array that represents the string (null-terminated).
You should not manipulate the data this pointer points to, so if you need to do that, copy the data.
Double edit - doing it in a more C++ fashion
Since it is nicer to avoid the use of raw pointers and arrays where possible, you can also get the data into an std::vector<char>
#include <string>
#include <vector>
int main()
{
std::string str = "Hello";
std::vector<char> cvec(str.begin(), str.end());
// do stuff
}
edit this is more like C since it uses raw pointers and explicitly allocates mem
#include <string>
#include <cstring>
int main()
{
std::string str = "Hello";
char *cptr = new char[str.size()+1]; // +1 to account for \0 byte
std::strncpy(cptr, str.c_str(), str.size());
// do stuff...
delete [] cptr;
}
You're going to get a lot of kinda incorrect answers about str.c_str() here. :) While c_str() is indeed useful, please keep in mind that this will not actually convert the string into a char*, but rather return the contents of the string as a const char*. And this is a big difference!
What's important here is that the pointer you obtain from c_str() is valid only as long as the given string object exists. So this would be terribly wrong:
class Something {
const char* name;
public:
Something(const std::string& pname) {
this->name = pname.c_str(); /* wrong! the pointer will go wrong as the object from the parameter ceases to exist */
}
};
So if you want to convert, as in: create a new value which will be independent of the original std::string, then you'll want to do something like this:
char* convert(const std::string& str) {
char* result = new char[str.length()+1];
strcpy(result,str.c_str());
return result;
}
But still c_str() will be quite enough for you in most cases. Just try to think in terms of objects' time of life.
const char* foobar2 = foobar.c_str();
Notice the const.
Otherwise you have to copy it to a char buffer.