Using c.str to convert from string to cstring - c++

I am practicing some work with cstring and string.
Going from string to cstring using c_str() I get an incompatible data type compile error.
For example this is the code that gives said error:
string str = "StackOverFlow";
char inCstring[20]{};
inCstring = str.c_str();
Any ideas?

The problem is that str.c_str() returns a const char*, and you are trying to pass it to a char*. Use strcpy to get your expected result:
#include <iostream>
#include <cstring>
#include <string>
using namespace std;
int main()
{
string str = "StackOverFlow";
char inCstring[20];
strcpy(inCstring, str.c_str());
cout << "str: " << str << endl;
cout << "inCstring: " << inCstring << endl;
return 0;
}

So I have figured out two ways to accomplish this.
First, it is important to remember that you can't assign to a whole array, meaning it is necessary to specify the element of the array to assign to. Attempting to assign a string to char array simply will not work for this reason. That being said, by specifying the element it would be possible to assign a character in a specific element of a char array. Below are two methods that accomplish a string to cstring(string to char array) "conversion". Please see answer by Vincent for complete code. I have found Method B better since I would like to have max size on my character array.
Method A:
string str = "StackOverFlow";
const char* inCstring;
inCstring = str.c_str();
Method B:
string str = "StackOverFlow";
char inCstring[20]{};
Then use strcpy
strcpy(inCstring, str.c_str());

Related

Can you safely get a pointer to a string from its c_str() const char*?

I have a const char pointer which I know for sure came from a string. For example:
std::string myString = "Hello World!";
const char* myCstring = myString.c_str();
In my case I know myCstring came from a string, but I no longer have access to that string (I received the const char* from a function call, and I cannot modify the function's argument list).
Given that I know myCstring points to contents of an existing string, is there any way to safely access the pointer of the parent string from which it originated? For example, could I do something like this?
std::string* hackyStringPointer = myCstring - 6; //Along with whatever pointer casting stuff may be needed
My concern is that perhaps the string's contents possibly cannot be guaranteed to be stored in contiguous memory on some or all platforms, etc.
Given that I know myCstring points to contents of an existing string, is there any way to safely access the pointer of the parent string from which it originated?
No, there is no way to obtain a valid std::string* pointer from a const char* pointer to character data that belongs to a std::string.
I received the const char* from a function call, and I cannot modify the function's argument list
Your only option in this situation would be if you can pass a pointer to the std::string itself as the actual const char* pointer, but that will only work if whatever is calling your function does not interpret the const char* in any way (and certainly not as a null-terminated C string), eg:
void doSomething(void (*func)(const char*), const char *data)
{
...
func(data);
...
}
void myFunc(const char *myCstring)
{
std::string* hackyStringPointer = reinterpret_cast<std::string*>(myCstring);
...
}
...
std::string myString = "Hello World!";
doSomething(&myFunc, reinterpret_cast<char*>(&myString));
You cannot convert a const char* that you get from std::string::c_str() to a std::string*. The reason you can't do this is because c_str() returns a pointer to the string data, not the string object itself.
If you are trying to get std::string so you can use it's member functions then what you can do is wrap myCstring in a std::string_view. This is a non-copying wrapper that lets you treat a c-string like it is a std::string. To do that you would need something like
std::string_view sv{myCstring, std::strlen(myCstring)};
// use sv here like it was a std::string
Yes (it seems), although I agree that if I need to do this it's likely a sign that my code needs reworking in general. Nevertheless, the answer seems to be that the string pointer resides 4 words before the const char* which c_str() returns, and I did recover a string* from a const char* belonging to a string.
#include <string>
#include <iostream>
std::string myString = "Hello World!";
const char* myCstring = myString.c_str();
unsigned int strPtrSize = sizeof(std::string*);
unsigned int cStrPtrSize = sizeof(const char*);
long strAddress = reinterpret_cast<std::size_t>(&myString);
long cStrAddress = reinterpret_cast<std::size_t>(myCstring);
long addressDifference = strAddress - cStrAddress;
long estStrAddress = cStrAddress + addressDifference;
std::string* hackyStringPointer = reinterpret_cast<std::string*>(estStrAddress);
cout << "Size of String* " << strPtrSize << ", Size of const char*: " << cStrPtrSize << "\n";
cout << "String Address: " << strAddress << ", C String Address: " << cStrAddress << "\n";
cout << "Address Difference: " << addressDifference << "\n";
cout << "Estimated String Address " << estStrAddress << "\n";
cout << "Hacky String: " << *hackyStringPointer << "\n";
//If any of these asserts trigger on any platform, I may need to re-evaluate my answer
assert(addressDifference == -4);
assert(strPtrSize == cStrPtrSize);
assert(hackyStringPointer == &myString);
The output of this is as follows:
Size of String* 4, Size of const char*: 4
String Address: 15725656, C String Address: 15725660
Address Difference: -4
Estimated String Address: 15725656
Hacky String: Hello World!
It seems to work so far. If someone can show that the address difference between a string and its c_str() can change over time on the same platform, or if all members of a string are not guaranteed to reside in contiguous memory, I'll change my answer to "No."
This reference says
The pointer returned may be invalidated by further calls to other member functions that modify the object.
You say you got the char* from a function call, this means you do not know what happens to the string in the mean time, is that right? If you know that the original string is not changed or deleted (e.g. gets out of scope and thus is destructed) then you can still use the char*.
Your example code however has multiple problems. You want to do this:
std::string* hackyStringPointer = myCstring - 6;
but I think you meant
char* hackyStringPointer = myCstring;
One, you cannot cast the char* to a string* and second you do not want to go BEFORE the start of the char*. The char* points to the first character of the string, you can use it to access the characters up to the trailing 0 character. But you should not go before the first or after the trailing 0 character though, as you do not know what is in that memory or if it even exists.

Use strcpy to transform a C++ string to a Char array

For some reason, I was trying to covert a C++ string to a char array. Below is what I did:
string aS="hello world";
char aC[aS.size()];
strcpy(aC, aS.c_str());
cout << aC[0] << endl;
string bS="veooci m eode owtwolwwwwtwwj mooawee mdeeme eeeec eme aemmeledmll llllleolclclcmslococecewaccocmelaeaccoaaooojutmjooooocoemoooealm omjcdmcmkemmdemmmiwecmcmteeeote eoeeeem ecc e yolc e w dtoooojttttmtwtt ttjcttoowl otdooco ko mooooo aowmemm o et jmc cmlctmmcccjcccecomatocooccoeoclooomoecwooo mcdoo dcdco dddooedoemod eddeedoedje emadleweemeeedeeeec or o m wejeetoj o ojjjlwdjjjj mjmceaeoaai laaadoaa aetmotaemmj mmmmmmlmm cmol c mwoaoe omav";
char bC[bS.size()];
strcpy(bC, bS.c_str());
cout << aC[0] << endl;
When aC[0] was first called, it gave 'h' as expected. However, when aC[0] is called at the second time, it gave ''. Could someone explain me what happened here?
For some reason, I was trying to covert a C++ string to a char array
Why don't you just use .c_str(), it does this for you
string aS="hello world";
cout << aS.c_str();
char aC[aS.size()];
would need to be:
char aC[aS.size() + 1];
in order to allow for the terminating '\0' required for a C string.
If you don't want to use the std::string::c_str() member function, you should then allocate the char array dynamically, as you cannot declare variable length arrays in C++, such as:
char* bC = new char[aS.size() + 1]; // don't forget to delete[]
strcpy(bC, bS.c_str());
I can see some utility of changing to an array if you're calling a function that will change the string buffer (pre C++11). Otherwise, use the other solutions such as c_str() if the buffer is not going to be changed.
However, if you really wanted a char array due to the buffer possibly being changed, use std::vector<char>. This will bypass the issue of using non-standard syntax (aC[aS.size()]), and removes the need to dynamically allocate memory. A std::vector<char> effectively is a changeable string buffer, only wrapped.
#include <vector>
#include <string>
#include <cstring>
#include <iostream>
using namespace std;
int main()
{
string aS="hello world";
std::vector<char> aC(aS.begin(), aS.end()); // copy
aC.push_back(0); // null-terminate
cout << &aC[0] << endl;
}
Output:
hello world
Now, where you need to specify a character array pointer, you just pass the address of the first element in the vector (provided that the vector is not empty).
Live Example: http://ideone.com/tF32Zt

What is the return type of stack.top() and stack.pop() using stack<string> in cpp?

I am trying to print the return value of stack.top() using printf() of a stack but it is giving a format mismatch. The code is given below :
int main(){
stack <string> cards;
char *ch1;
char ch2[20];
cards.push("Ace");
cards.push("King");
cards.push("Queen");
cards.push("Jack");
printf("Number of cards : %ld \n", cards.size());
ch1 = cards.top(); // As sizeof(cards.top()) is 8. error of type conversion
strcpy(ch2,cards.top()); // cannot convert ‘std::basic_string<char>’ to ‘const char*’
printf("Top of the Stack : %s \n", ch);
return 0
}
In all examples I saw it was printed using "cout".
A std::string is a different type from a char*, the following won't work:
ch1 = cards.top(); // top() returns a string, not a char*
I suggest using std::strings for your code:
int main(){
stack <string> cards;
string ch1; // std::strings
string ch2;
...
ch1 = cards.top(); // Correct
printf("Top of the Stack : %s \n", ch1.c_str()); // c_str() needed
return 0;
}
Also notice that using printf requires a char* type, you can get one with std::string::c_str(), or (even better) you can use cout in the first place:
std::cout << "Top of the Stack : " << ch1;
Therefore I'd suggest doing something like:
#include <iostream>
#include <stack>
#include <string>
int main() {
std::stack <std::string> cards;
std::string ch1;
cards.push("Ace");
cards.push("King");
cards.push("Queen");
cards.push("Jack in the Jack");
std::cout << "Number of cards : " << cards.size() << std::endl;
ch1 = cards.top(); // Get the top card
std::cout << "Top of the Stack : " << ch1;
}
Example
The return value of is pop is void, top returns a reference to the data type that the stack holds. std::string is not the same as an array of char and it does not directly work with any of the C string functions. You can use std::string::c_str() to get the raw data, but it is better to stay in STL land. You can directly print std::string using std::cout.
You can't use strcpy, which is a C function for C-style char * strings, for C++ std::strings - if you must use C strings for some reason then change:
strcpy(ch2,cards.top());
to
strcpy(ch2,cards.top().c_str());
^^^^^^^^
This takes the std::string returned by cards.top() and returns a const char * which can be used by strcpy.
A better solution though would be to stick to C++ idioms throughout, i.e. use std::string exclusively and use std::cout instead of printf for display purposes.
In the following line
ch1 = cards.top();
stack<string>::top() returns string, while ch1 is char *. There is no type conversion from string to char *. To convert it, use the member function c_str :
ch1 = cards.top().c_str();
And ch1 must be const char*, not char *, because thats what c_str returns.
Why it returns const char* ? Because otherwise you could disrupt the string value by extracting char * and changing it.

C++ char* array

When I create something like
char* t = new char[44];
t = strcpy(s,t);
then strlen(t); return some wrong results. how I can change this?
Both strcpy and strlen expect to find the special character NUL or '\0' in the array. An uninitialized array, as the one you've created, may contain anything at all, which means the behavior of your program is undefined when it is passed to strcpy as the source argument.
Assuming the goal was to copy s into t, to make the program behave as expected, try this:
#include <iostream>
#include <cstring>
int main()
{
const char* s = "test string";
char* t = new char[44];
// std::strcpy(t, s); // t is the destination, s is the source!
std::strncpy(t, s, 44); // you know the size of the target, use it
std::cout << "length of the C-string in t is " << std::strlen(t) << '\n';
delete[] t;
}
But keep in mind that in C++, strings are handled as objects of type std::string.
#include <iostream>
#include <string>
int main()
{
const std::string s = "test string";
std::string t = s;
std::cout << "length of the string in t is " << t.size() << '\n';
}
What are you trying to do? Do you want to copy from s to t? If so, the arguments to strcpy are reversed.
char* t = new char[44]; // allocate a buffer
strcpy(t,s); // populate it
Such C-style string processing is a red flag, but that's all I can say given this little information.
This code might be helpful:
char * strcpy (char * destination, const char * source);
t = strcpy(t, s);
You have to initialize the variable t
Do something like this:
char *t = new char[44];
memset(t, 0, 44);
// strlen(t) = 0
The strcpy function is described thus:
#include <string.h>
char *strcpy(char *dest, const char *src);
The strcpy() function copies the string pointed to by src (including the terminating '\0' character) to the array pointed to by dest.
So, if you are trying to fill in your newly allocated array, you should be doing:
strcpy(t, s);
Not the other way around.

C++ convert int and string to char*

This is a little hard I can't figure it out.
I have an int and a string that I need to store it as a char*, the int must be in hex
i.e.
int a = 31;
string str = "a number";
I need to put both separate by a tab into a char*.
Output should be like this:
1F a number
With appropriate includes:
#include <sstream>
#include <ostream>
#include <iomanip>
Something like this:
std::ostringstream oss;
oss << std::hex << a << '\t' << str << '\n';
Copy the result from:
oss.str().c_str()
Note that the result of c_str is a temporary(!) const char* so if your function takes char * you will need to allocate a mutable copy somewhere. (Perhaps copy it to a std::vector<char>.)
Try this:
int myInt = 31;
const char* myString = "a number";
std::string stdString = "a number";
char myString[100];
// from const char*
sprintf(myString, "%x\t%s", myInt, myString);
// from std::string :)
sprintf(myString, "%x\t%s", myInt, stdString.c_str());
#include <stdio.h>
char display_string[200];
sprintf(display_string,"%X\t%s",a,str.c_str());
I've used sprintf to format your number as a hexadecimal.
str.c_str() will return a null-terminated C-string.
Note: not answering the main question since your comment indicated it wasn't necessary.
those who write "const char* myString = "a number";"
are just lousy programmers. Being not able to get the C basics - they rush into C++ and start speaking about the things they just don't understand.
"const char *" type is a pointer.
"a number" - is array. You mix pointers and arrays. Yes, C++ compilers sometimes allow duct typing. But you must also understand - if you do duct typing not understanding where your "ductivity" is - all your program is just a duct tape.