String to const char * in c++ puts garbage at end - c++

I have a struct that needs to store const char * for later. The string gets destroyed by then. The code that i have till now for the same is
HttpRequest* send(string reply)
{
int len = strlen(reply.c_str());
char *buffer = new char[len+1];
strncpy(buffer, reply.c_str(), len);
cout << "LEN:"<<reply.length()<<endl;
cout << "OG:"<<reply<<endl<<"TC:"<<buffer<<endl<<"CS"<<reply.c_str()<<endl;
this->res.response = "test";
return this;
};
res.response is the char * that i want to store the value in. The output from cout that i am getting is
LEN:5
OG:hello
TC:hello�������������������q{
CShello
This behavior is pretty strange to me. Can someone please explain what i am doing wrong. Also the above code shows me using strlen but i am getting the same result using length() in c++ also.
Also it is worth mentioning that this happens only the first time that i invoke this, after that it goes fine.

You never put the null terminator:
char *buffer = new char[len+1];
strncpy(buffer, reply.c_str(), len);
buffer[len] = 0; // <-- HERE
strncpy doesn't add it.

Your arguments to strncpy() make the function misunderstand that there is no space for terminating null-character, so it isn't written. Correct the argument like
strncpy(buffer, reply.c_str(), len+1);
In this code, it is guaranteed that the length of buffer is sufficient to store the string, so you can simply use strcpy() instead of the strncpy() like this:
strcpy(buffer, reply.c_str());
You can use strdup() function if your system supports it. Using it, the lines
int len = strlen(reply.c_str());
char *buffer = new char[len+1];
strncpy(buffer, reply.c_str(), len);
can be replaced with
char *buffer = strdup(reply.c_str());
Note that strdup() is a function from C and it uses malloc() internally, so you must use free(), not delete[], to free the memory allocated via strdup().

Don't use strncpy until you've read and understood its documentation. And then don't use it. It's a very specialized function, and there's no need to deal with its quirks here. The code in the question allocates enough space for the result, so just use strcpy.

The problem is that this statement
strncpy(buffer, reply.c_str(), len);
does not copy the terminating zero ( '\0' ) of the original string to buffer.
You should use the standard C function strlen with objects of type std::string only in case when the objects contain embedded zeroes. Otherwise use member functions of the class std::string size or length.
Instead of the standard C function strncpy you could use standard C function strcpy to copy the zero-terminated string in the buffer.
For example
char *buffer = new char[len+1];
strcpy( buffer, reply.c_str() );

Related

Do not understand about strcpy in C++

char* s1;
strcpy(s1,"smilehihi");
s1[6] = 'a';
When I compile, VS do not have any errors. But in the runtime, my code makes mistake. I think I do not really understand about strcpy
The main issue here is not the strcpy() function but the fact that you don't allocate any memory for the string itself.
If I were you, I would do something like
char* s1=(char*)malloc(SIZE); // the SIZE is the predefined maximum size of your string
strcpy(s1,"smilehihi");
s1[6] = 'a';
Edit:
Just as an advice, consider using stpncpy(). It helps to avoid buffer overflow, and, in your case, will help you avoid exceeding the maximum size of char*
char * stpncpy(char * dst, const char * src, size_t len);
The problem is that you have not allocated any space for what you wish to store in s1: "smilehihi". You declare s1 as a pointer variable, but it needs something to point at. You can allocate space by using the new operator.
char* s1 = new char[stringLength + 1]; //stringLength = length of string stored
// + 1 to hold null terminator character
strcpy(s1, "smilehihi");
s1[6] = 'a';
You have to declare #define _CRT_SECURE_NO_WARNINGS at the top of your main file to avoid an error during compilation due to strcpy() being deprecated.
You need to allocate variable first by malloc() or by using the keyword new .
Also deallocate the memory at the end
At first you should allocate char* s1.
char *s1 = new char[9]; // C++ version
or you can you use C version:
char *s1 = (char*)malloc(9);
Then you can use following code:
strcpy(s1, "smilehihi");
s1[6] = 'a';

How to add to an already allocated char?

This is a really simple question.
I have a structure with a char buffer[250].
struct testStruct{
char buffer[250];
};
How do I add, let's say-- "test characters" to that buffer?
I can't really do a simple assignment like newStruct.buffer = "test characters";
You can use the function sprintf or snprintf or strcpy or strncpy
so something like this:
sprintf(newStruct.buffer,"%s","test characters"); // doesnt protect against buffer overflow
snprintf(newStruct.buffer,250,"%s","test characters"); // guards against overflows
strcpy(newStruct.buffer,"test characters"); // as suggested in another answer also doesnt guard against overflows
strncpy(newStruct.buffer,"test characters",250);// guards against overflows
( instead of explicitly mentioning size 250 in snprintf and strncpy , you can use the sizeof function/instruction instead )
This will put "test characters" into the buffer array with a \0 character at the end ...
You can append more strings to it using strcat function if needed later.
here is the man page for sprintf:
http://linux.die.net/man/3/sprintf
newStruct.buffer = "test characters"; puts the constant value of "test characters" to the pointer of the array buffer. Obviously you're new to C and C++ programming, you should read on that a little bit more please, try here and here.
strcpy(newStruct.buffer, "test characters");
When you have an array of char, you can use strcpy. This function will copy each character until the end of the string ('\0' is also copied). You can also use strncpy for security matters.
#include <string.h>
char *strcpy(char *dest, const char *src);
char *strncpy(char *dest, const char *src, size_t n);
Remember that the order of the arguments is in fact the same as an affectation: dest = src.
You can also use sprintf for more advanced stuff. It's similar to printf but writes in the string.
#include <stdio.h>
int sprintf(char *str, const char *format, ...);
However, if you don't have an already allocated string, have a look to strdup when the source string could possibly be freed.
Back to your case, you can't write something like that: newStruct.buffer = "test characters"; because it would try to change the address of newStruct.buffer to point somewhere else. That would only be possible with a pointer (char*) but not with an array.
strcpy(newStruct.buffer, "test characters");
or
strncpy(newStruct.buffer, "test characters", sizeof(newStruct.buffer));
If you mean to append a string saying to add then you should use standard C functions either strcat or strncat provided that the last actual character in buffer is the terminating zero.
If you want to copy a string into buffer starting from the first character of buffer you should use standard C function either strcpy or strncpy.
For example if you are sure that the length of the string is less than 250 then you can write simply
std::strcpy( buffer, "test characters" );
If You do not know the size of the string you are going to copy then you can use strncpy
std::strncpy( buffer, SomeString, 250 );
buffer[249] = '\0';
In this case it is possible that the copy will be truncated.
If buffer already contains some string and you are going to append a new one then again your selection deoends on whether you are sure that the new string will fit in buffer,
If you are sure then you can write
strcat( buffer, "test characters" );
If you are not sure you can write
size_t n = 250 - std::strlen( buffer );
strcat( buffer, SomeString, n );
buffer[249] = '\0';

How can I transfer string to char* (not const char*)

I wanna do something like:
string result;
char* a[100];
a[0]=result;
it seems that result.c_str() has to be const char*. Is there any way to do this?
You can take the address of the first character in the string.
a[0] = &result[0];
This is guaranteed to work in C++11. (The internal string representation must be contiguous and null-terminated like a C-style string)
In C++03 these guarantees do not exist, but all common implementations will work.
string result;
char a[100] = {0};
strncpy(a, result.c_str(), sizeof(a) - 1);
There is a member function (method) called "copy" to have this done.
but you need create the buffer first.
like this
string result;
char* a[100];
a[0] = new char[result.length() + 1];
result.copy(a[0], result.length(), 0);
a[0][result.length()] = '\0';
(references: http://www.cplusplus.com/reference/string/basic_string/copy/ )
by the way, I wonder if you means
string result;
char a[100];
You can do:
char a[100];
::strncpy(a, result.c_str(), 100);
Be careful of null termination.
The old fashioned way:
#include <string.h>
a[0] = strdup(result.c_str()); // allocates memory for a new string and copies it over
[...]
free(a[0]); // don't forget this or you leak memory!
If you really, truly can't avoid doing this, you shouldn't throw away all that C++ offers, and descend to using raw arrays and horrible functions like strncpy.
One reasonable possibility would be to copy the data from the string to a vector:
char const *temp = result.c_str();
std::vector<char> a(temp, temp+result.size()+1);
You can usually leave the data in the string though -- if you need a non-const pointer to the string's data, you can use &result[0].

C++ copy const char* to char*

I have a function
ClassA::FuncA(const char *filePath)
and want to copy this const char string* to a char*!
My solution:
char *argv[2];
int length = strlen(filePath);
argv[1] = new char(length +1);
strncpy(argv[1], filePath, length);
after this I have in argv[1] the desired chars but also some other undefined chars!
filePath:
"C:\Users\userA\Parameter.xmlþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþKŸQyá•"
Whats wrong here? The length with strlen is OK!
Like so:
argv[1] = new char[length +1](); // () to value-initialize the array
Your version:
argv[1] = new char(length +1);
only allocates a single char and value-initializes it to length+1.
You have two problems in your code:
You need to add 1 to length after copying in order to copy null character (as strlen returns only number of chars without null character; see more here). So change code to:
strncpy(argv[1], filePath, length + 1);
You need fix how your array is being initialized as you are initializing only one character (and we assume you want full string to be copied). So:
argv[1] = new char[length + 1]();
Notes:
Please when you post also post the code that was used to print out data as problems such as these in a lot of cases depend on what you call to print out data.
And at the end you might consider using just an array of fixed size that is initialized to maximum path. For max path size in windows checkout following post
The problem is that you're using strncpy, rather than strcpy. And
the way you're using it, it doesn't copy the terminating \0.
In practice, because strncpy may leave a string without a \0 terminator, it's best to avoid it. In your case, strcpy alone is fine, since you've just allocated a sufficiently large buffer. In the more general case, you may have to use strlen, to ensure that the string you have fits in the target buffer (without ever forgetting to add 1 to the results, for the \0).
If the situation occurs a lot, you might want to write your own version
of strncpy, which works (i.e. guarantees a terminating \0, and
doesn't copy or write more characters than necessary). Something like:
void
stringCopy( char* dest, int maxLength, char const* source )
{
assert( maxLength > 0 );
char* end = dest + maxLength - 1;
while ( dest != end && *source != '\0' ) {
*dest = *source;
++ dest;
++ source;
}
*dest = '\0';
}
(This function actually exists, under the name strcpy_s in C 2011, but
it isn't widely implemented; Microsoft has it, but I've not seen it
elsewhere.)
strncpy() copies not more than length characters. In doing so, terminating \0 was not copied.

Can I get a non-const C string back from a C++ string?

Const-correctness in C++ is still giving me headaches. In working with some old C code, I find myself needing to assign turn a C++ string object into a C string and assign it to a variable. However, the variable is a char * and c_str() returns a const char []. Is there a good way to get around this without having to roll my own function to do it?
edit: I am also trying to avoid calling new. I will gladly trade slightly more complicated code for less memory leaks.
C++17 and newer:
foo(s.data(), s.size());
C++11, C++14:
foo(&s[0], s.size());
However this needs a note of caution: The result of &s[0]/s.data()/s.c_str() is only guaranteed to be valid until any member function is invoked that might change the string. So you should not store the result of these operations anywhere. The safest is to be done with them at the end of the full expression, as my examples do.
Pre C++-11 answer:
Since for to me inexplicable reasons nobody answered this the way I do now, and since other questions are now being closed pointing to this one, I'll add this here, even though coming a year too late will mean that it hangs at the very bottom of the pile...
With C++03, std::string isn't guaranteed to store its characters in a contiguous piece of memory, and the result of c_str() doesn't need to point to the string's internal buffer, so the only way guaranteed to work is this:
std::vector<char> buffer(s.begin(), s.end());
foo(&buffer[0], buffer.size());
s.assign(buffer.begin(), buffer.end());
This is no longer true in C++11.
There is an important distinction you need to make here: is the char* to which you wish to assign this "morally constant"? That is, is casting away const-ness just a technicality, and you really will still treat the string as a const? In that case, you can use a cast - either C-style or a C++-style const_cast. As long as you (and anyone else who ever maintains this code) have the discipline to treat that char* as a const char*, you'll be fine, but the compiler will no longer be watching your back, so if you ever treat it as a non-const you may be modifying a buffer that something else in your code relies upon.
If your char* is going to be treated as non-const, and you intend to modify what it points to, you must copy the returned string, not cast away its const-ness.
I guess there is always strcpy.
Or use char* strings in the parts of your C++ code that must interface with the old stuff.
Or refactor the existing code to compile with the C++ compiler and then to use std:string.
There's always const_cast...
std::string s("hello world");
char *p = const_cast<char *>(s.c_str());
Of course, that's basically subverting the type system, but sometimes it's necessary when integrating with older code.
If you can afford extra allocation, instead of a recommended strcpy I would consider using std::vector<char> like this:
// suppose you have your string:
std::string some_string("hello world");
// you can make a vector from it like this:
std::vector<char> some_buffer(some_string.begin(), some_string.end());
// suppose your C function is declared like this:
// some_c_function(char *buffer);
// you can just pass this vector to it like this:
some_c_function(&some_buffer[0]);
// if that function wants a buffer size as well,
// just give it some_buffer.size()
To me this is a bit more of a C++ way than strcpy. Take a look at Meyers' Effective STL Item 16 for a much nicer explanation than I could ever provide.
You can use the copy method:
len = myStr.copy(cStr, myStr.length());
cStr[len] = '\0';
Where myStr is your C++ string and cStr a char * with at least myStr.length()+1 size. Also, len is of type size_t and is needed, because copy doesn't null-terminate cStr.
Just use const_cast<char*>(str.data())
Do not feel bad or weird about it, it's perfectly good style to do this.
It's guaranteed to work in C++11. The fact that it's const qualified at all is arguably a mistake by the original standard before it; in C++03 it was possible to implement string as a discontinuous list of memory, but no one ever did it. There is not a compiler on earth that implements string as anything other than a contiguous block of memory, so feel free to treat it as such with complete confidence.
If you know that the std::string is not going to change, a C-style cast will work.
std::string s("hello");
char *p = (char *)s.c_str();
Of course, p is pointing to some buffer managed by the std::string. If the std::string goes out of scope or the buffer is changed (i.e., written to), p will probably be invalid.
The safest thing to do would be to copy the string if refactoring the code is out of the question.
std::string vString;
vString.resize(256); // allocate some space, up to you
char* vStringPtr(&vString.front());
// assign the value to the string (by using a function that copies the value).
// don't exceed vString.size() here!
// now make sure you erase the extra capacity after the first encountered \0.
vString.erase(std::find(vString.begin(), vString.end(), 0), vString.end());
// and here you have the C++ string with the proper value and bounds.
This is how you turn a C++ string to a C string. But make sure you know what you're doing, as it's really easy to step out of bounds using raw string functions. There are moments when this is necessary.
If c_str() is returning to you a copy of the string object internal buffer, you can just use const_cast<>.
However, if c_str() is giving you direct access tot he string object internal buffer, make an explicit copy, instead of removing the const.
Since c_str() gives you direct const access to the data structure, you probably shouldn't cast it. The simplest way to do it without having to preallocate a buffer is to just use strdup.
char* tmpptr;
tmpptr = strdup(myStringVar.c_str();
oldfunction(tmpptr);
free tmpptr;
It's quick, easy, and correct.
In CPP, if you want a char * from a string.c_str()
(to give it for example to a function that only takes a char *),
you can cast it to char * directly to lose the const from .c_str()
Example:
launchGame((char *) string.c_str());
C++17 adds a char* string::data() noexcept overload. So if your string object isn't const, the pointer returned by data() isn't either and you can use that.
Is it really that difficult to do yourself?
#include <string>
#include <cstring>
char *convert(std::string str)
{
size_t len = str.length();
char *buf = new char[len + 1];
memcpy(buf, str.data(), len);
buf[len] = '\0';
return buf;
}
char *convert(std::string str, char *buf, size_t len)
{
memcpy(buf, str.data(), len - 1);
buf[len - 1] = '\0';
return buf;
}
// A crazy template solution to avoid passing in the array length
// but loses the ability to pass in a dynamically allocated buffer
template <size_t len>
char *convert(std::string str, char (&buf)[len])
{
memcpy(buf, str.data(), len - 1);
buf[len - 1] = '\0';
return buf;
}
Usage:
std::string str = "Hello";
// Use buffer we've allocated
char buf[10];
convert(str, buf);
// Use buffer allocated for us
char *buf = convert(str);
delete [] buf;
// Use dynamic buffer of known length
buf = new char[10];
convert(str, buf, 10);
delete [] buf;