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
Related
I am facing an issue with string and null characters in C++.
When I am writing '\0' in between the string and printing the string then I am getting only part before '\0' but on the other hand when I am taking string as input then changing any index as '\0' then it is printing differently. Why is it so and why the sizeof(string) is 32 in both the cases
Code is below for reference. Please help.
First code:
#include<iostream>
using namespace std;
int main(){
string s = "he\0llo";
cout<<s.length()<<"\n";
cout<<s<<endl;
cout<<sizeof(s)<<"\n";
}
output of First code:
2\n
he\n
32\n
Second code
#include<iostream>
using namespace std;
int main(){
string s;
cin>>s;
s[1] = '\0';
cout<<s<<"\n";
cout<<s.length()<<"\n";
cout<<sizeof(s)<<"\n";
return 0;
}
output of second code:
hllo\n
5\n
32\n
Below is the image for your reference.
std::string's implicit const CharT* constructors and assignment operator don't know the exact length of the string argument. Instead, it only knows that this is a const char* and is forced to assume that the string will be null-terminated, and thus computes the length using std::char_traits::length(...) (effectively std::strlen).
As a result, constructing a std::string object with an expression like:
std::string s = "he\0llo";
will compute 2 as the length of the string, since it assumes the first \0 character is the null terminator for the string, whereas your second example of:
s[1] = '\0';
is simply adding a null character into an already constructed string -- which does not change the size of the string.
If you want to construct a string with a null character in the middle, you can't let it compute the length of the string for you. Instead, you will have to construct the std::string and give it the length in some other way. This could either by done with the string(const char*, size_t) constructor, or with an iterator pair if this is an array:
// Specify the length manually
std::string s{"he\0llo",6};
Live Example
// Using iterators to a different container (such as an array)
const char c_str[] = "he\0llo";
std::string s{std::begin(c_str), std::end(c_str)};
Live Example
Note: sizeof(s) is telling you the size of std::string class itself in bytes for your implementation of the standard library. This does not tell you the length of the contained string -- which can be determined from either s.length() or s.size().
As of c++14, there is an option to specify quoted strings as a std::string by using std::literals. This prevents conversion of an array of chars to string which automatically stops at the first nul character.
#include<iostream>
#include <string>
using namespace std;
using namespace std::literals;
int main() {
string s = "he\0llo"s; // This initializes s to the full 6 char sequence.
cout << s.length() << "\n";
cout << s << endl;
cout << sizeof(s) << "\n"; // prints size of the s object, not the size of its contents
}
Results:
6
hello
28
I have the following stupid snippet:
#include <iostream>
#include <cstring>
using namespace std;
int main() {
const string classpath = "Hello Dolly!";
const int len = classpath.length()+1;
char str[len];
strncpy(str, classpath.c_str(), len);
cout << str << endl;
return 0;
}
The aim ist to assign a c++ string to a c char array. The string is known at compile time, hence a constant. But the string may vary from one project to an other. I have no intention to count chars for the compiler. Hence the const len should be computed at compile time as shown. This works with cygwin and on linux. But the visualstudio compiler sees a problem and gives me the error C2131!
How to work around?
(Please consider I'm a Java programmer being troubled loosing time on such kind of problems!)
In C++ array sizes must be known at compile time.
You can dynamically allocate contiguous memory during run-time by using operator new:
char * my_array = new char[length];
Remember to use the delete[] to free up the memory after you are finished with it.
Also, C-style arrays need that terminating nul character so you will need to allocate one extra slot in the array.
To copy a std::string to a character array:
const std::string example = "example";
const std::string::size_type length = example.length();
char * p_array = new char [length + 1];
strcpy(p_array, example.c_str());
cout << p_array << endl;
delete[] p_array;
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());
#include <iostream>
#include <string>
using namespace std;
int main() {
string s = "hello";
cout << s[5] << endl;
return 0;
}
In the above code, if I print s[5], it correctly prints a NULL character. But if I change the code to this:
#include <iostream>
#include <string>
using namespace std;
int main() {
char[] s = {'a','b','c','d','e'};
cout << s[5] << endl;
return 0;
}
It doesn't print a NULL character but something random. If I store the string as a string or as a char*, then the behavior is in tune with what I expect.
But if I explicitly declare the character array, how does the compiler know when the array ends? Does the size of the array gets stored at compile time?
String literals and std::strings store null terminated strings.
But an array of 5 char declared like:
char s[] = {'a','b','c','d','e'};
contains only 5 char, no null terminator.
But the compiler does know the size of s. It is part of the type of s. It has no convenient .size() function like std::string, std::vector or std::array does but you can get it by doing:
sizeof(s) / sizeof(s[0])
Or more safely in C++11:
std::extent<decltype(s)>::value
Or in C++17:
std::size(s)
(demo)
Arrays have a habit of decaying to pointers though and then there is no way of getting the size, you have to keep track of it yourself. Which is why std::string, std::vector or std::array is preferred in C++.
Strings are null-terminated, and const char* are treated the same way as Strings are. When you declare a array with a size it's put on the stack and the compiler doesn't know the size. Array out-of-bounds exceptions aren't determined during compile time.
the string class in c++ has the constructor which by itself adds the null character to the string passed to it if not explicitly added. But while using char it only stores the content passed to it (i.e) if you want to have a null character you have to explicitly add in the declaration or the definition of that char.
When you do char[] s = {'a','b','c','d','e'};, it will store characters mentioned and nothing else.
if I explicitly declare the character array, how does the compiler know when the array ends?
size is determined by number of characters provided by you.
Does the size of the array gets stored at compile time?
no, the size of array is determined by memory blocks allocated to it. (It is not stored separately in memory, if that's what you meant)
And when you use this string s = "hello";, strings are always null terminated.
Your code is char s[] = {'a','b','c','d','e'};, so it will not put the \0 at the end of your char array. It will put the \0 with three methods below:
1. char s[] = {'a','b','c','d','e', '\0'};
2. char s[] = "abcde";
3. string s = "abcde";
So if you use any of the three above, you will get a NULL character.
"how does the compiler know when the array ends ?": the compiler knows how many elements the array has, from its declaration, and this information is available through the sizeof operator.
Anyway C-style arrays have virtually no size, as they are implicitly turned to pointers when passed as arguments, and their length is dropped (IMO a major flaw in the design of the C language). Overflow avoidance is your responsibility.
For this reason, you mustn't use a cout << statement if your string isn't null-terminated.
Is this correct or is there a better way to do this.
Visual Studio gives an error saying 'strcpy() is depreciated'.
using namespace std;
char* ptr;
ptr=(char *)calloc(1,sizeof(char));
cout << "Input the equation." << endl;
string eqn;
getline(cin, eqn);
ptr = (char *)realloc(ptr, top + eqn.size()+1);
strcpy(ptr, eqn.c_str());
P.S. I want to ptr to be the exact size of the input equation.
Assuming that what you're trying to achieve is to create a modifiable char buffer given a std::string, the better choice is to use std::vector<char> to create such a buffer.
#include <vector>
#include <string>
#include <iostream>
//...
void foo(char *x)
{
// do something to 'x'
}
using namespace std;
int main()
{
cout << "Input the equation." << endl;
string eqn;
getline(cin, eqn);
// construct vector with string
std::vector<char> ptr(eqn.begin(), eqn.end());
// add null terminator
ptr.push_back(0);
foo( &ptr[0] );
}
The above creates a modifiable, null-terminated C-string by utilizing the std::vector called ptr. Note that there are no calls to malloc, calloc, etc.
strcpy is deprecated because it's a common source of buffer overflow problems, that are generally fixed with strncpy. Having said that, you are much better off using std::string in the first place.
If you want to have a duplicate of a string with malloc, you may simply use strdup:
char* ptr = strdup(eqn.c_str());
// ..
free(ptr);