I need to concatenate to chars and send it as argument to function, but strcat move concatenated chars to first char. I need a method that return concatenated char. Or if I can do it in different way how can I do it?
void abca(char *a)
{
Serial.println(a);
}
void setup()
{
Serial.begin(9600);
char *bb = "1";
char *aa = "2";
abca(strcat(aa, bb));
}
Edit: I'm creating program for Arduino, and I can't use strings. Strings use a lot of memory. Unfortunately Arduino have only 2kB
There are a few problems with your code. First of all, you are using non-const pointers to const arrays:
char *bb = "1"; // "1" is a char constant array
char *aa = "2"; // so it needs a pointer to constant memory
When you fix that your function calls will fail because they need non-const arrays.
One fix is to create a non-const array to receive your concatenated string:
// should be const because it is not modified
void abca(char const* a)
{
Serial.println(a);
}
void setup()
{
Serial.begin(9600);
// char const array decays to pointer to const char
char const* bb = "1";
char const* aa = "2";
// can't concatenate into constant memory
// abca(strcat(aa, bb));
// So make some writable memory and concat to that
char buffer[32]; // long eough for the combined text
strcpy(buffer, bb);
strcat(buffer, aa);
abca(buffer);
}
If you don't know how big the resulting string is you may need to allocate buffer dynamically to make sure it is big enough.
If you are able to change the function to
void abca(const char *a)
Then you could use a std::string at the calling site and the c_str() method:
int main()
{
std::string a = "aa";
std::string b = "bb";
abca((a + b).c_str());
}
Note that the overloaded + operator is used for concatenation. Better still, if you can change the function to
void abca(const std::string& a)
(note that the body of the function is unchanged), you can write
abca(a + b);
at the calling site. All standard C++, and no memory leaks or undefined behaviour either! std::string might get some bad press but it does epitomise the power of C++.
Related
I am trying to write code that will assign a const char array to a dynamically allocated const char array.
I tried to do it like
const char staticArray[4] = "abc";
const char * ptrDynamicArray;
ptrDynamicArray = new const char[4](staticArray);
But I get an error ("parenthesized initializer in array new [-fpermissive]").
I have two questions:
How could I solve it - like turn it off (I am using Code::Blocks 16.01)?
Can I initialize a dynamically allocated const char array somehow else?
Overloading new operator will do your job.
void * operator new[](size_t n, const char *s) {
void *p = malloc(n);
strcpy((char *)p, s);
return p;
}
Now new operator can be called like :
const char staticArray[4] = "abc";
const char * ptrDynamicArray;
ptrDynamicArray = new (staticArray) char[4];
You cannot copy-initialize an array from another array directly, hence the error. You either need to manually copy the elements (or use std::copy), or, better, if you want a "copy"-able array use std::array<char, 4> instead.
But, as mentioned in the comments, the best probably is to use an std::string here, and use its std::string::c_str() member function in case you need to pass around const char* pointers to old C-like interfaces.
How can I write in C++ a function who put the data in a char array, I don't how to explain well but I'll write an example
void functionCopyData(char& buf){
// get data from a char variable
char data1 = "textdata1";
char data2 = "textdata2"
// copy data
copy(&buf,data1);
copy(&buf,data2);
}
char variable[20];
functionCopyData(&variable);
printf(variable);
// return: textdata1textdata2
So summarizing, I need to copy the data from two variables and put in a char array. Sorry if I was not clear enough.
Why this way?
because I need to get the data from and a variable and send it in a function request a reference data sendFunction(&data,sizeVar);
how can I do that?
How can I write in C++ a function who put the data in a char array
Change the argument type.
void functionCopyData(char& buf){
will be good if you want to update just one character, not an array of characters. To update an array of characters, use:
void functionCopyData(char buf[]){
or
void functionCopyData(char* buf){
That could easily lead to problems if buf does not have enough memory to store the data. To make function more robust, pass a number that indicates the capacity of buf.
void functionCopyData(char buf[], size_t capacity){
Fix the definitions of data1 and data2.
char data1 = "textdata1";
char data2 = "textdata2"
are not syntactically valid. Change them to:
char data1[] = "textdata1";
char data2[] = "textdata2";
or
char const* data1 = "textdata1";
char const* data2 = "textdata2";
Make sure that buf can hold data1 and data2.
// You need the additional 1 for the terminating null
// character.
size_t capacityNeeded = strlen(data1) + strlen(data2) + 1;
if ( capacityNeeded > capacity )
{
// Deal with the problem.
}
else
{
// Now copy the contents of data1 and data2 to buf
}
Copy the contents data1 and data2 to buf using standard library functions.
strcpy(buf, data1);
strcat(buf, data2);
Fix the call to the function.
functionCopyData(&variable);
is not the right syntax to use to call the function, given the function declaration. Use:
functionCopyData(variable, 20);
An easy solution is to write a function to copy one array, and then call it twice with different pointers pointing to different positions in the result array.
For example, if you have char data[20] to hold the result, and want to copy two arrays char a[10] and char b[10], then write a function
void copy(char* destination, char* source, int length)
That copies length bytes from source to destination, then call it with
copy(data, a, 10);
copy(data+10, b, 10);
The functions strcpy and strlen can help you:
#include <string.h>
void functionCopyData(char buf[]){
char data1[] = "textdata1";
char data2[] = "textdata2";
strcpy(buf, data1);
strcpy(buf+strlen(buf), data2);
}
...
functionCopyData(variable);
...
void functionCopyData(char* buf){
// get data from a char variable
char* data1 = "textdata1";
char* data2 = "textdata2"
// copy data
copy(buf,data1);
copy(buf,data2);
}
char variable[20];
functionCopyData(variable);
printf(variable);
I think it's more clear use pointer but not reference.
I'm very new to C++ (coming from C#) and it's giving me puzzles :S
I have a very basic question about arrays and it's pointers.
So if I have the following code:
char * test1 = "com";
char * test2 = "ment";
I found similar code in some files already. I don't exactly understand how a string can fit in one character.. but ok...
However, how could I connect these arrays so that I get "comment" ?
I'm pretty sure this char * result = test1 + test2; would only increase the pointer which would then point to something in the memory, which I dont intend to use.
So is it possible to get an array like char array[] = {'c', 'o', 'm', 'm', 'e', 'n', 't'}; back from this?
or can I at least get a pointer which points to something like comment\NUL in the memory?
As you pointed out, pointer arithmetic can't solve this.
If you want to have a C-string as the result, allocating space for the whole new string is required, then copying over the characters, typically using strcat / strncat, but they are C-style string operations.
// Your C-strings
const char *test1 = "com";
const char *test2 = "ment";
// Dynamic allocation of memory for result string
char *result = new char[strlen(test1) + strlen(test2) + 1];
// Start with the empty string
*result = '\0';
// Concatenate both input strings (use strncat if you don't know
// for sure that they will fit into the result array!)
strcat(result, test1);
strcat(result, test2);
// (use result pointer)
// Free the memory after last usage
delete[] result;
In C++, you typically try to avoid them and use std::string instead. Even if you want a C-string as the result, you can use a temporary std::string for allocation and management of the required memory as well as for performing the concatenation:
// Your C-strings
const char *test1 = "com";
const char *test2 = "ment";
// Wrap in temporary C++ strings and concatenate:
std::string result = std::string(test1) + std::string(test2);
// Get the pointer (only valid as long as result is in scope!)
const char *ptr = result.c_str();
Furthermore, please note that you should not assign a string literal to a non-const char * pointer, use a const char* pointer instead. And try to avoid dealing with raw C-strings as long as possible; of course when you use C libraries you have to use them a lot.
Note also that above mentioned methods are performed at runtime; you can't get a compile-time solution for concatenating two string literals, even though the compiler could know what you want to have. I don't know your context, but maybe you only want to have a multi-line string literal, then simply drop the + and write "com" "ment".
A c style solution can be found in the following link:
http://www.cplusplus.com/forum/beginner/5681/:
int len = strlen(test1)+strlen(test2);
char* result = new char[len +1]; // +1 for null terminated string
snprintf(result,len +1, "%s%s",test1,test2);
result[len] = NULL;
// use result
delete(result);
You can utilize std::string:
#include <iostream>
int main() {
// Note: the character literals are const (non const is deprecated)!
const char * test1 = "com";
const char * test2 = "ment";
// This gives a compiler error (there is no way to add pointers)
// const char * concat = test1 + test2;
// A std::string has an overload for the operator +:
std::string comment = std::string(test1) + test2;
// The dynamically allocated string.
// Note: as soon as the comment string gets altered or destroyed the
// pointer s to the internal string data (may) become invalid.
const char* s = comment.c_str();
std::cout << s << '\n';
}
I want to copy a char to an address where a given char* points to.
it's in a function which is called by main:
char data = " ";
myfunction(data, somethingelse);
...
inside the function i have something like
void myfunction(char* data, short somethingelse) {
...
char byte = 0;
inputfilestream.read(&byte, 1);
*data = byte; // here i get the segfault
data++;
...
}
the segfault also comes when i to the copy using strncpy:
strncpy(data, byte, 1);
why is there a segfault? data isn't const and the address where i actually write to is exactly the same as the one where i allocated the data-array. i've tested that multiple times.
thanks in advance.
String literals are readonly. If you want a modifyable string, you must use an array, e.g.:
char data[10];
Or:
char *data = new char[10];
To elaborate a bit more: the type of a string literal is actually const char*. Assigning a string literal to a non-const char* is therefore technically invalid, but most compilers allow it anyway for legacy reasons. Many modern compilers will at least issue a warning when you try to do that.
data is assigned a string literal. String literals are ready only, and writing to them will cause segfaults.
Try this:
char data[10]; // or whatever size you want.
instead.
why is there a segfault? data isn't const and the address where i actually write to is exactly the same as the one where i allocated the data-array.
You didn't allocate anything. char *data = " "; shouldn't even compile in C++. You are assigning a constant string to a non-constant.
char byte = 0;
inputfilestream.read(&byte, 1);
*data = byte; // here i get the segfault
data++; // << How many times?
No problem
#include <stdio.h>
int main(int argc, char **argv)
{
char *data = "Yello"; // or char data[] = "Yello";
*data = 'H';
puts(data); // Hello
}
If i pass a char * into a function. I want to then take that char * convert it to a std::string and once I get my result convert it back to char * from a std::string to show the result.
I don't know how to do this for conversion ( I am not talking const char * but just char *)
I am not sure how to manipulate the value of the pointer I send in.
so steps i need to do
take in a char *
convert it into a string.
take the result of that string and put it back in the form of a char *
return the result such that the value should be available outside the function and not get destroyed.
If possible can i see how it could be done via reference vs a pointer (whose address I pass in by value however I can still modify the value that pointer is pointing to. so even though the copy of the pointer address in the function gets destroyed i still see the changed value outside.
thanks!
Converting a char* to a std::string:
char* c = "Hello, world";
std::string s(c);
Converting a std::string to a char*:
std::string s = "Hello, world";
char* c = new char[s.length() + 1];
strcpy(c, s.c_str());
// and then later on, when you are done with the `char*`:
delete[] c;
I prefer to use a std::vector<char> instead of an actual char*; then you don't have to manage your own memory:
std::string s = "Hello, world";
std::vector<char> v(s.begin(), s.end());
v.push_back('\0'); // Make sure we are null-terminated
char* c = &v[0];
You need to watch how you handle the memory from the pointer you return, for example the code below will not work because the memory allocated in the std::string will be released when fn() exits.
const char* fn(const char*psz) {
std::string s(psz);
// do something with s
return s.c_str(); //BAD
}
One solution is to allocate the memory in the function and make sure the caller of the function releases it:
const char* fn(const char*psz) {
std::string s(psz);
// do something with s
char *ret = new char[s.size()]; //memory allocated
strcpy(ret, s.c_str());
return ret;
}
....
const char* p = fn("some text");
//do something with p
delete[] p;// release the array of chars
Alternatively, if you know an upper bound on the size of the string you can create it on the stack yourself and pass in a pointer, e.g.
void fn(const char*in size_t bufsize, char* out) {
std::string s(psz);
// do something with s
strcpy_s(out, bufsize, s.c_str()); //strcpy_s is a microsoft specific safe str copy
}
....
const int BUFSIZE = 100;
char str[BUFSIZE];
fn("some text", BUFSIZE, str);
//ok to use str (memory gets deleted when it goes out of scope)
You can maintain a garbage collector for your library implemented as
std::vector<char*> g_gc; which is accessible in your library 'lib'. Later, you can release all pointers in g_gc at your convenience by calling lib::release_garbage();
char* lib::func(char*pStr)
{
std::string str(pStr);
char *outStr = new char[str.size()+1];
strcpy(outStr, str.c_str());
g_gc.push_back(outStr); // collect garbage
return outStr;
}
release_garbage function will look like:
void lib::release_garbage()
{
for(int i=0;i<g_gc.size();i++)
{
delete g_gc[i];
}
g_gc.clear();
}
In a single threaded model, you can keep this g_gc static. Multi-threaded model would involve locking/unlocking it.