i have a problem.
i tried to proceede the following steps:
char * str;
char * s="Hello";
int len = std::strlen(s);
str=new char[len +10];
strcpy_s(str,sizeof(str) ,s);
But the programm displays the error, which i write in the title.
If i replace the sizeof(str) with a number, for example 256, a pop up window appear with the message project.exe has triggered a breakpoint.
How can i solve this errors with strcpy_s??
Thank you!
The sizeof(str) returns the size of char* which is (probably) either 4 or 8 (bytes) depending on the implementation. In your case it appears to be 4 which is not enough to hold the characters that make up the "Hello" literal plus the null terminating character. Since there is not enough space the strcpy_s function invokes undefined behavior. You need at least 6 bytes which is the number of characters + 1 byte for a null character. Also instead of str=new char[len + 10]; you probably meant str = new char[len + 1]; to accommodate for the \0 character. Hence your code should be:
#include <iostream>
int main(){
char* str;
char* s = "Hello";
int len = std::strlen(s);
str = new char[len + 1];
strcpy_s(str, len + 1, s);
}
That being said prefer std::string to C-style character array.
sizeof(str) gives the size of char*, which is not the length of the allocated array. To fix this, you must give the allocated length. In this case this would be
strcpy_s(str, len + 10, s);
Related
Let's suppose I've this code snippet in C++
char* str;
std::string data = "This is a string.";
I need to copy the string data (except the first and the last characters) in str.
My solution that seems to work is creating a substring and then performing the std::copy operation like this
std::string substring = data.substr(1, size - 2);
str = new char[size - 1];
std::copy(substring.begin(), substring.end(), str);
str[size - 2] = '\0';
But maybe this is a bit overkilling because I create a new string. Is there a simpler way to achieve this goal? Maybe working with offets in the std:copy calls?
Thanks
As mentioned above, you should consider keeping the sub-string as a std::string and use c_str() method when you need to access the underlying chars.
However-
If you must create the new string as a dynamic char array via new you can use the code below.
It checks whether data is long enough, and if so allocates memory for str and uses std::copy similarly to your code, but with adapted iterators.
Note: there is no need to allocate a temporary std::string for the sub-string.
The Code:
#include <string>
#include <iostream>
int main()
{
std::string data = "This is a string.";
auto len = data.length();
char* str = nullptr;
if (len > 2)
{
auto new_len = len - 2;
str = new char[new_len+1]; // add 1 for zero termination
std::copy(data.begin() + 1, data.end() - 1, str); // copy from 2nd char till one before the last
str[new_len] = '\0'; // add zero termination
std::cout << str << std::endl;
// ... use str
delete[] str; // must be released eventually
}
}
Output:
his is a string
There is:
int length = data.length() - 1;
memcpy(str, data.c_str() + 1, length);
str[length] = 0;
This will copy the string in data, starting at position [1] (instead of [0]) and keep copying until length() - 1 bytes have been copied. (-1 because you want to omit the first character).
The final character then gets overwritten with the terminating \0, finalizing the string and disposing of the final character.
Of course this approach will cause problems if the string does not have at least 1 character, so you should check for that beforehand.
I have the following string tok_str which is like "default.png" I would like to preprend char ' and append char ' too.
That's what I have done, but the chars are appended and prepended in the wrong places
char *tok_str = const_cast<char*>(mReader->getAttributeValue(pAttrIdx));
char * mod_tok = new char[tok_str_len+2];
mod_tok[0] = '\'';
size_t len = strlen(tok_str);
size_t i;
memmove(mod_tok + len, mod_tok, strlen(mod_tok) + 1);
for (i = 0; i < len; ++i)
{
mod_tok[i] = tok_str[i];
}
char *dup;
char *cstr="'";
sprintf(mod_tok,"%s%s",cstr,(dup=strdup(mod_tok)));
free(dup);
If you want to continue using null-terminated byte strings there are a few things you need to think of and do.
The first is of course the null-terminated part. A string of X characters needs space for X+1 to include the terminator.
The second is that all you need is really a single sprintf (or better yet snprintf) call (once you allocated memory):
char* mod_tok = new char[strlen(tok_str) + 3]; // +2 for the extra characters, +1 for terminator
snprintf(mod_tok, strlen(tok_str) + 3, "'%s'", tok_str);
That is it, now you have added the single quotes in front and at the end of the original string.
There are a couple of things to improve:
usage of const when possible
len vs tok_str_len, use only one.
the memmove done in the middle seems to have no effect on the final result
pay attention to the indexes in the for loop
be aware that strlen doesn't count the NULL terminator
if your code starts to mix new/delete with free try to refactor it
That's my proposal:
//keep it const and protect your data
const char *tok_str = mReader->getAttributeValue(pAttrIdx);
//retrive the len once for all (const, no one is supposed to change it)
const size_t len = strlen(tok_str);
char * mod_tok = new char[len+3]; // 2 "'" + '\0'
mod_tok[0] = '\'';
for (size_t i = 0; i < len; ++i)
{
mod_tok[i+1] =tok_str[i];
}
mod_tok[len+1] = '\'';
mod_tok[len+2] = '\0';
//done.
//later...
delete[] mod_tok;
Enjoy your coding!
Stefano
PS: I agree, though, that a use of std::string is reccomended.
This question already has answers here:
How do I concatenate const/literal strings in C?
(17 answers)
Closed 9 years ago.
I need to put "Hello World" in str3. How can I do this ?
const char *one = "Hello ";
char *two = "World";
char *str3;
You have to allocate void* malloc (size_t size); for str3 first then you can use sprintf to write in a string.
char *str3 = malloc(strlen(one) + strlen(two) + 1);
sprintf(str3, "%s%s", one, two); // ^ \0 termination
Adding #Nik Bougalis Suggestion:
One should know dynamic memory allocation in C. In my code I allocated using malloc() so latter in code when I don't need str3 we should explicitly deallocate memory using free() in C.
Also to avoid buffer-overflow always use snprintf instead of sprintf: So re-writing code as follows:
int length = strlen(one) + strlen(two) + 1;
char *str3 = malloc(length * sizeof(char));
snprintf(str3, length, "%s%s", one, two);
// write more code that uses str3
free(str3);
// now don't uses `str3`'s allocated memory
Read a book about C.
str3 = malloc(strlen(one) + strlen(two) + 1) ; // +1 for the 0 terminator
strcpy(str3, one) ;
strcat(str3, two) ;
...
free(str3) ; // frees allocated space when you are finished.
std::vector<char> v;
v.insert(v.end(), one, one + strlen(one));
v.insert(v.end(), two, two + strlen(two));
v.push_back('\0');
str3 = v.data();
String literals like "Hello" are stored in read-only memory, so you need to copy them somewhere where they can be modified.
So you must first allocate memory where the strings are to be stored. A simply char array will do. Then use strcpy() and strcat() to copy the string literals into that array.
I wrote a very simple encryption program to practice c++ and i came across this weird behavior. When i convert my char* array to a string by setting the string equal to the array, then i get a wrong string, however when i create an empty string and add append the chars in the array individually, it creates the correct string. Could someone please explain why this is happening, i just started programming in c++ last week and i cannot figure out why this is not working.
Btw i checked online and these are apparently both valid ways of converting a char array to a string.
void expandPassword(string* pass)
{
int pHash = hashCode(pass);
int pLen = pass->size();
char* expPass = new char[264];
for (int i = 0; i < 264; i++)
{
expPass[i] = (*pass)[i % pLen] * (char) rand();
}
string str;
for (int i = 0; i < 264; i++)
{
str += expPass[i];// This creates the string version correctly
}
string str2 = expPass;// This creates much shorter string
cout <<str<<"\n--------------\n"<<str2<<"\n---------------\n";
delete[] expPass;
}
EDIT: I removed all of the zeros from the array and it did not change anything
When copying from char* to std::string, the assignment operator stops when it reaches the first NULL character. This points to a problem with your "encryption" which is causing embedded NULL characters.
This is one of the main reasons why encoding is used with encrypted data. After encryption, the resulting data should be encoded using Hex/base16 or base64 algorithms.
a c-string as what you are constructing is a series of characters ending with a \0 (zero) ascii value.
in the case of
expPass[i] = (*pass)[i % pLen] * (char) rand();
you may be inserting \0 into the array if the expression evaluates to 0, as well as you do not append a \0 at the end of the string either to assure it being a valid c-string.
when you do
string str2 = expPass;
it can very well be that the string gets shorter since it gets truncated when it finds a \0 somewhere in the string.
This is because str2 = expPass interprets expPass as a C-style string, meaning that a zero-valued ("null") byte '\0' indicates the end of the string. So, for example, this:
char p[2];
p[0] = 'a';
p[1] = '\0';
std::string s = p;
will cause s to have length 1, since p has only one nonzero byte before its terminating '\0'. But this:
char p[2];
p[0] = 'a';
p[1] = '\0';
std::string s;
s += p[0];
s += p[1];
will cause s to have length 2, because it explicitly adds both bytes to s. (A std::string, unlike a C-style string, can contain actual null bytes — though it's not always a good idea to take advantage of that.)
I guess the following line cuts your string:
expPass[i] = (*pass)[i % pLen] * (char) rand();
If rand() returns 0 you get a string terminator at position i.
I am using C Style strings for a project, and I am confusing myself a bit. I am checking strings to see what they are prepended with (zone_, player_, etc) then getting the rest of the string after that.
else if(strncmp(info, "zone_", 5) == 0)
{
int len = strlen(info);
char *zoneName = new char[len];
strncpy(zoneName, &info[5], len-5);
Msg("Zone Selected: %s\n", zoneName);
delete zoneName;
}
When I print out the zoneName variable though, it is correct except it is followed by a bunch of gibberish. What am I doing wrong? (I realize that the gibberish is the rest of the char array being empty, but I don't know a better way to do this)
See strncpy description :
No null-character is implicitly
appended to the end of destination, so
destination will only be
null-terminated if the length of the C
string in source is less than num.
You have to remember that C-style strings are terminated with a NUL character. You've allocated enough space in zoneName, but you only need len-5 plus one:
char *zoneName = new char[len - 5 + 1];
Then, you can actually use strcpy() to copy the tail of the string:
strcpy(zoneName, &info[5]);
You don't need to specify the length because the source string is NUL terminated.
C strings are zero terminated - so they occupy len bytes (chars to be precise) plus one more with value zero known as the 'zero terminator'. You need to allocate one more character, and either copy one more from the source (since it should be zero terminated) or just set the last char of the destination to 0.
int len = strlen(info);
char *zoneName = new char[len - 5 + 1];
strncpy(zoneName, &info[5], len - 5 + 1);
C-style strings has to be finished with a byte with zero value. You should modify your code like this:
char *zoneName = new char[len-5+1];
strncpy(zoneName, &info[5], len-5);
/* correct string ending */
zoneName[len]=0;
/* Now, it's safe to print */
Msg("Zone Selected: %s\n", zoneName);