How to concatenate a char * and a const char*? [duplicate] - c++

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.

Related

Copy a part of an std::string in a char* pointer

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.

Comparing chars one by one in a character array with strcmp [duplicate]

This question already has answers here:
Comparing chars in a character array with strcmp
(3 answers)
Is there a possible way to use char in strcmp?
(2 answers)
Closed 1 year ago.
I'm writing a c++ script that compare chars of two strings one by one using strcmp().
I wrote this code:
char test1[1];
char test2[1];
test1[0]=str1[i]; //str1 is a char array
test2[0]=str2[i]; //str2 is a char array
int result=strcmp(test1,test2);
but if I print test1 or test2 I encountered with two chars.
for example if first index of str1='a' then test1 is "aa" but I don't know why?
Please Help.
strcmp() takes null-terminated strings, but neither of your char[] arrays are null-terminated.
char test1[2]; // <-- increase this!
char test2[2]; // <-- increase this!
test1[0] = str1[i];
test1[1] = '\0'; // <-- add this!
test2[0] = str2[i];
test2[1] = '\0'; // <-- add this!
int result = strcmp(test1, test2);
Otherwise, you can use strncmp() instead, which does not require null terminators, so no char[] arrays are needed, eg:
char test1 = str1[i];
char test2 = str2[i];
int result = strncmp(&test1, &test2, 1);
Or simply:
int result = strncmp(&str1[i], &str2[i], 1);
// or:
// int result = strncmp(str1+i, str2+i, 1);

How to convert multiple strings into the same char array?

I need a way to convert multiple strings into the same char array. For example if I have
string str1;
string str2;
char *myArray = new char[str1.size() + str2.size() + 1];
What's the best way to add the string characters into myArray?
You could use another string to combine the two:
auto myArray = str1 + str2;
You can then access the underlying (constant!) char array with the .c_str method or, if you want to modify certain characters, access them with the operator[] on string.
If you need an actual, modifiable char* style array, use std::vector:
std::vector<char> myArray (str1.begin(), str1.end());
myArray.insert(myArray.end(), str2.begin(), str2.end());
myArray.push_back('\0'); // If the array should be zero terminated
You can then access the underlying, modifiable char array with the .data method.
Note that variable length arrays like char myArray[str1.size() + str2.size() + 1] are a compiler extension that only works on certain compilers. They are not standard C++.
strcpy(myarray,(str1+str2).c_str())
or
strncpy(myarray,(str1+str2).c_str(),(str1+str2).length())
use strcpy and strcat:
strcpy(myArray,str1.c_str());
strcat(myArray,str2.c_str());
although , the expression char myArray[str1.size() + str2.size() + 1] will not compile under C++ , since VLAs are forbidden , use dynamic memory allocation:
char* myArray = new char[str1.size() + str2.size() + 1]

Combining std::string and std::vector<char>

This is not the actual code, but this represents my problem.
std::string str1 = "head";
char *buffer = "body\0body"; // Original code has nullbytes;
std::string str2 = "foot";
std::vector<char> mainStr(buffer, buffer + strlen(buffer));
I want to put str1 and str2 to mainStr in an order:
headbody\0bodyfoot
So the binary data is maintained. Is this possible to do this?
PS: Thanks for telling the strlen part is wrong. I just used it to represent buffer's length. :)
There should be some way of defining length of data in "buffer".
Usually character 0 is used for this and most of standard text functions assume this. So if you use character 0 for other purposes, you have to provide another way to find out length of data.
Just for example:
char buffer[]="body\0body";
std::vector<char> mainStr(buffer,buffer+sizeof(buffer)/sizeof(buffer[0]));
Here we use array because it provides more information that a pointer - size of stored data.
You cannot use strlen as it uses '\0' to determine the end of string. However, the following will do what you are looking for:
std::string head = "header";
std::string foot = "footer";
const char body[] = "body\0body";
std::vector<char> v;
v.assign(head.begin(), head.end());
std::copy(body, body + sizeof(body)/sizeof(body[0]) - 1, std::back_inserter<std::vector<char> >(v));
std::copy(foot.begin(), foot.end(), std::back_inserter<std::vector<char> >(v));
Because the character buffer adds an NUL character at the end of the string, you'll want to ignore it (hence the -1 from the last iterator).
btw. strlen will not work if there are nul bytes in your string!
The code to insert into the vector is:
front:
mainStr.insert(mainStr.begin(), str1.begin(), str1.end());
back:
mainStr.insert(mainStr.end(), str2.begin(), str2.end());
With your code above (using strlen will print)
headbodyfoot
EDIT: just changed the copy to insert as copy requires the space to be available I think.
You could use std::vector<char>::insert to append the data you need into mainStr.
Something like this:
std::string str1 = "head";
char buffer[] = "body\0body"; // Original code has nullbytes;
std::string str2 = "foot";
std::vector<char> mainStr(str1.begin(), str1.end());
mainStr.insert(mainStr.end(), buffer, buffer + sizeof(buffer)/sizeof(buffer[0]));
mainStr.insert(mainStr.end(), str2.begin(), str2.end());
Disclaimer: I didn't compile it.
You can use IO streams.
std::string str1 = "head";
const char *buffer = "body\0body"; // Original code has nullbytes;
std::string str2 = "foot";
std::stringstream ss;
ss.write(str1.c_str(), str1.length())
.write(buffer, 9) // insert real length here
.write(str2.c_str(), str2.length());
std::string result = ss.str();
std::vector<char> vec(result.c_str(), result.c_str() + result.length());
str1 and str2 are string objects that write the text.
I wish compilers would fail on statements like the declaration of buffer and I don't care how much legacy code it breaks. If you're still building it you can still fix it and put in a const.
You would need to change your declaration of vector because strlen will stop at the first null character. If you did
char buffer[] = "body\0body";
then sizeof(buffer) would actually give you close to what you want although you'll get the end null-terminator too.
Once your vector mainStr is then set up correctly you could do:
std::string strConcat;
strConcat.reserve( str1.size() + str2.size() + mainStr.size() );
strConcat.assign(str1);
strConcat.append(mainStr.begin(), mainStr.end());
strConcat.append(str2);
if vector was set up using buffer, buffer+sizeof(buffer)-1
mainStr.resize(str1.length() + str2.length() + strlen(buffer));
memcpy(&mainStr[0], &str1[0], str1.length());
memcpy(&mainStr[str1.length()], buffer, strlen(buffer));
memcpy(&mainStr[str1.length()+strlen(buffer)], &str2[0], str2.length());

How to declare array string in c++

This is very basic but so:
I want a string with 4 characteres: "abcd"
how must I declare a new string, like that?
char *newStr = new char[4]; // or -> char newStr[4];
strcpy(newStr, "abcd");
the null '\0' character must be on the size of the string, so new char[5]?
yes, \0 character is a part of string and you must allocate memory for it as well
Yes, the termination nul character is part of the string. So you need to allocate space for 5 characters:
char *newStr = new char[5];
strcpy(newStr, "abcd");
Don't forget to free the dynamically allocate memory once you are done using it as:
delete[] newStr;
Alternatively you can also do:
char newStr[] = "abcd";
In C++ it's better to use the string class for representing strings:
string newStr = "abcd";
You don't have "new" in C, but only in C++.
You could:
char* string = "abc";
or
char string[] = "abc";
or
char* string = (char*) malloc(sizeof(char) * 4);
strcpy(string, "abc");
string[3]='\0';
/* remember to free the used memory */
or
char string[] = { 'a', 'b', 'c', '\0' };
This should do the dirty work for you:
char newString[] = "abcd";
Also, yes, you need new char[5];
If this is C++ (seems re-tagged for what i've read), whats wrong with
std::string my_string = "abcd";
?
Isn't that what you are looking for ? I Could be missing something.
/ ------------------- string constructors ----------------
string emp(""); // constructs the "empty string"
string emp2; // constructs another "empty string"
string spc(" "); // constructs string containing " "
string sstr("Some string"); // string containing "Some string"
char frob[] = "Frobnitz";
string sfrob(frob); // constructs a C++ string containing
// "Frobnitz" from a C-style string
string bar = "foobar"; // string containing "foobar"
// ------------------- stdout, c_str() --------------------
Source: http://www-cs-students.stanford.edu/~sjac/c-to-cpp-info/string-class
If it is a string literal, you can do either of these:
char *string = "abcd";
char astring[] = "abcd";
If you want to know this for eventually copying strings, you can either have a buffer, or allocate memory, and space for '\0' is necessary, even though strlen("abcd") will return 4 because it does not count the terminator.
/* buffer way */
char string[5];
strcpy(string, "abcd");
/* allocating memory */
// char *ptr = malloc(5*sizeof(*ptr)); // question was retagged C++
char *ptr = static_cast<char*>(malloc(5*sizeof(*ptr));
strcpy(ptr,"abcd");
/* more stuff */
free(ptr);
Since the question has been retagged to C++, you can also use new and delete.
/* using C++ new and delete */
char *ptr = new char[5]; // allocate a block of 5 * sizeof(char)
strcpy(ptr, "abcd");
// do stuff
delete [] ptr; // delete [] is necessary because new[] was used
Or you could also use std::string.