I want to pass string to second function where it fills the character array and gives the value back. In the first function I want to take the string length after second function fills it.
first step
Planning to pass the character array
char data[10]="";
GetData(data); // Here Iam doing memset value to data
strlen(data);
second step
Planning to pass the character pointer
char *data;
GetData(data); // what I should do
strlen(data);
Can someone suggest which is the best practice
You want to use std::string, something like:
std::string data;
void GetData(std::string& str);
passing by non-const reference allows GetData to alter str.
Ideally the character pointer should be owned by the caller, and should take care of allocation (if possible, or callee has to do that on behalf of the caller) and deallocation
char *data = (char *) NULL; // should initialize to know allocated or not
the prototype of the call, GetData should be:
void GetData(char *& d); // pointer passed as reference
Within GetData, d shoud be allocated as:
d = new char[size]; //size should be appropriately decided including null terminating character
for example, if you wish to store a "hello" say, d should be allocated as :
d = new char[5+1]; // example
once done, in the caller, you must deallocate as:
if (data) delete [] data;
data = (char *) NULL;
The "classic", C-compatible method in Windows (where Visual C++ is most used) is to have a function that takes the buffer size as argument, and returns the size or length of data copied. Example:
//Inputs:
// buffer: [out/opt] If not null, write data here.
// size: [in] Buffer size including null terminator, ignored if buffer is null.
//Outputs:
// buffer: The data.
// Return Value: Length of data written to the buffer, without null terminator.
int GetData(char *buffer, size_t bufferSize);
This allows calling the function with a null buffer to obtain the length to allocate, allocate the data, and call the function again.
However, it's not very C++ and it's error-prone. Passing a pointer/reference to the pointer to allocate is better from a language standpoint, but has its drawbacks when crossing a DLL boundary, where it's recommended that any data allocated by a DLL be deallocated by the same DLL (preventing the use of ordinary smart pointers).
Related
Assume we have defined a char* as follow:
char *x;
And we have a function like it:
void append(void *y, char *z);
This function appends it's second parameter (where the pointer z is pointing at) to the end of a string that the pointer y is pointing to it's beginning. The reason that I am restricted to have the first parameter to be void* is that I need to override a libcurl function:
size_t header_callback(char *buffer, size_t size, size_t nitems, void *userdata);
Any time the header_callback function is called I need to append buffer to the end of userdata. The userdata pointer is pointing to beginning of a string.
According to documentation you linked, userdata is a pointer previously supplied to CURLOPT_HEADERDATA. Something like this might work for you.
size_t header_callback(char *buffer, size_t size, size_t nitems, vector<string> *userdata)
{
userdata->push_back(string(buffer, size*nitems));
return size*nitems;
}
//...
vector<string> headers;
curl_easy_setopt(curl, CURLOPT_HEADERDATA, &headers);
curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, header_callback);
//...
It is impossible to implement your
void append(void *y, char *z);
in such a way that it could append a non-null terminated character sequence.
The char *buffer given to the callback is non-null terminated.
Also, you can convert the void pointer to the correct type of the buffer in the callback, before calling the append. That must be done eventually, since you cannot append anything to void.
You hardly need an external function since appending is quite trivial. Assuming your void* points to a std::string:
auto bytes = size * nitems;
auto str = (std::string*)userdata;
str->append(buffer, bytes);
To append data to buffer those things should be defined:
allowed size of destination buffer
amount of data in buffer present in destination buffer
amount of data to be copied to destination buffer
In C realloc() can be used to create new buffer with content of old one.. that may or may not change location of buffer. In C++ there is flavor of new operator that allows similar action.
If we assume that data stored is strictly null-terminated string (but even that wasn't specified!) then 2nd and 3rd are known - the size of buffer is unknown to append() is size of buffer. Therefore, the function
void append(void *y, char *z);
looks either unfit for the task or very unsafe and possibly ill-defined, unless void y is actually some structure or class (but passing that as void???) .
You did not provide implementation OR description of it. By the look is should be rather limited one. We should pre-allocate a buffer of proper size and ensure that append() won't run outside of its bounds. It cannot reallocate target buffer, so it is limited by already allocated memory. To actually reallocate target buffer append would have void **y or void &* y as formal parameter (realloc() may change pointer and does copy data from old buffer to new buffer)
This poses an architecture problem - ownership of buffer. If we pass buffer we control, we can allocate it properly and pass it to append() OR pass ownership to append() so it would reallocate it. If we don't, we have to create a temporal buffer... but can we use that temporal buffer afterwards?
The point is moot unless you are using custom header write function. user data pointer is CURLOPT_HEADERDATA, which is either pointer to valid FILE and you should _fwrite() data to it... Or, if you are implementing CURLOPT_WRITEFUNCTION and CURLOPT_READFUNCTION callback, that pointer can be used at discretion of designer of callbacks, as a pointer to some useful data container (libcurl uses fwrite as default callback).
Your question looks more referring to C (not C++) approach. Then you need the following:
know the size of the y
realloc the y to be of the size + 1
memcpy/memmove y to the new place
set the last byte of the new buffer to z
return to the user the pointer and the size of the new buffer
free the old buffer y (depends on the need).
In C++ hovewer you need to use some container like std::vector, which will allow you to append one byte.
After allocating and initializing a char* and copying a data for it
char * uri= new char [strlen(realm) + strlen("sip:") +1]();
strcpy(uri, "sip:");
strcat(uri, realm);
I pass this char* to pj_str(char*) function. This function convert the char* to pj_str_t struct that contains a pointer to the buffer and its length.
Then the function continue its logic and uses the uri pj_str.
Before the function return, it's supposed to deallocate *uri. When doing this line of code the first two characters contain an octal garbage data else it contains the expected data.
delete [] uri;
What is the problem?!
Isn't it enough to do
delete [] uri;
The documentation says:
istream::get ( char* s, streamsize n, char delim );
// Extracts characters from the stream and stores them as a
// c-string into the array beginning at s
I tried to analyze what this function does. It takes a pointer "by value". That is it cannot allocate dynamic memory and set the pointer s to it. It can only change what the pointer s points to.
But if the function cannot perform dynamic memory allocation, how can it return an output whose length is not known? How should I use this function? Should I preallocate memory and pass the pointer to it as s and then delete it by myself?
The documentation is clear:
stores them as a c-string into the array beginning at s
– s has to point to a valid array that’s big enough to accommodate the read string.
how can it return an output whose length is not known
The maximum length is known, it’s n (actually n - 1, since one character is reserved for the null termination of the C string).
However, given your questions it’s probably more appropriate to use the std::string overload of getline.
You should preallocate memory (pointed to by s) of size n, pass that s to first and n to second parameter of the function. This way, get will read maximum n bytes (including terminating null) and copy them to buffer pointed to by s
If your buffer is local (an array on the stack, lets say), you don't have to delete it (in fact you can't) However if it is dynamic (i.e, allocated by new[], malloc, operator new or whatever) then you have to free it accordingly.
example:
const int n = 50;
char *s = new char[n];
cin.get(s, n);
//...
delete []s;
note: although this is valid, as others commented, better use std::string instead.
You should use it like this:
const int size = 10;
char s[size]; //large enough to fit string
stream.get(&s[0], size, '\n');
You preallocate the buffer you need and make sure it's large enough to fit target string.
#include <iostream>
#include <string.h>
using namespace std;
void newBuffer(char* outBuffer, size_t sz) {
outBuffer = new char[sz];
}
int main(void) {
const char* abcd = "ABCD";
char* foo;
foo = NULL;
size_t len = strlen(abcd);
cout<<"Checkpoint 1"<<endl;
newBuffer(foo, len);
cout<<"Checkpoint 2"<<endl;
cout<<"Checkpoint 2-A"<<endl;
memset(foo, '-', len);
cout<<"Checkpoint 3"<<endl;
strncpy(foo, abcd, len);
cout<<"Checkpoint 4"<<endl;
cout << foo << endl;
int hold;
cin>>hold;
return 0;
}
This program crashes between checkpoint 2-1 and 3. What it tries to do is to set the char array foo to the char '-', but it fails because of some access issues. I do not understand why this happens. Thank you very much in advance!
Your newBuffer function should accept the first parameter by reference so that changes made to it inside the function are visible to the caller:
void newBuffer(char*& outBuffer, size_t sz) {
outBuffer = new char[sz];
}
As it is now, you assign the result of new char[sz] to the local variable outBuffer which is only a copy of the caller's foo variable, so when the function returns it's as if nothing ever happened (except you leaked memory).
Also you have a problem in that you are allocating the buffer to the size of the length of ABCD which is 4. That means you can hold up to 3 characters in that buffer because one is reserved for the NUL-terminator at the end. You need to add + 1 to the length somewhere (I would do it in the call to the function, not inside it, because newBuffer shouldn't be specialised for C-strings). strncpy only NUL-terminates the buffer if the source string is short enough, so in this case you are only lucky that there happens to be a 0 in memory after your buffer you allocated.
Also don't forget to delete[] foo in main after you're done with it (although it doesn't really matter for a program this size).
It fails because your newBuffer function doesn't actually work. The easiest way to fix it would be to change the declaration to void newBuffer (char *&outBuffer, size_t sz). As it's written, the address of the newly allocated memory doesn't actually get stored into main's foo because the pointer is passed by value.
You are passing the pointer by value. You would need to pass either a reference to the pointer, or the address of the pointer.
That said, using the return value would be better in my view:
char* newBuffer(size_t sz) {
return new char[sz];
}
When written this way, the newBuffer function doesn't really seem worthwhile. You don't need it. You can use new directly and that would be clearer.
Of course, if you are using C++ then this is all rather pointless. You should be using string, smart pointers etc. You should not have any need to call new directly. Once you fix the bug you are talking about in this question you will come across the problem that your string is not null-terminated and that the buffer is too short to hold the string since you forgot to allocate space for the null-terminator. One of the nice things about C++ is that you can escape the horrors of string handling in C.
This is the scenario;
// I have created a buffer
void *buffer = operator new(100)
/* later some data from a different buffer is put into the buffer at this pointer
by a function in an external header so I don't know what it's putting in there */
cout << buffer;
I want to print out the data that was put into the buffer at this pointer to see what went in. I would like to just print it out as raw ASCII, I know there will be some non-printable characters in there but I also know some legible text was pushed there.
From what I have read on the Internet cout can't print out uncasted data like a void, as opposed to an int or char. However, the compiler wont let me cast it on the fly using (char) for example. Should I create a seperate variable that casts the value at the pointer then cout that variable, or is there a way I can do this directly to save on another variable?
Do something like:
// C++11
std::array<char,100> buf;
// use std::vector<char> for a large or dynamic buffer size
// buf.data() will return a raw pointer suitable for functions
// expecting a void* or char*
// buf.size() returns the size of the buffer
for (char c : buf)
std::cout << (isprint(c) ? c : '.');
// C++98
std::vector<char> buf(100);
// The expression `buf.empty() ? NULL : &buf[0]`
// evaluates to a pointer suitable for functions expecting void* or char*
// The following struct needs to have external linkage
struct print_transform {
char operator() (char c) { return isprint(c) ? c : '.'; }
};
std::transform(buf.begin(), buf.end(),
std::ostream_iterator<char>(std::cout, ""),
print_transform());
Do this:
char* buffer = new char[100];
std::cout << buffer;
// at some point
delete[] buffer;
void* you only need in certain circumstances, mostly for interop with C interfaces, but this is definitely not a circumstance requiring a void*, which essentially loses all type information.
You need to cast it to char*: reinterpret_cast<char*>(buffer). The problem is that void* represents anything, so only th pointer is printed; when you cast it to char*, the contents of the memory are interpreted as a C-style string
Note: use reinterpret_cast<> instead of the C-style (char *) to make your intent clear and avoid subtle-and-hard-to-find bugs later
Note: of course you might get a segfault instead, as if the data is indeed not a C-style string, memory not associated with the buffer might be accessed
Update: You could allocate the memory to a char* buffer to begin with and it would solve your problem too: you could still call your 3rd party function (char* is implicitly convertible to void*, which I presume is the 3rd party function's parameter type) and you don't need to do the cast-ing at all. Your best bet is to zero-out the memory and restrict the 3rd party function to copy more than 99*sizeof(char) bytes into your buffer to preserve the ending '\0' C-style string terminator
If you want to go byte by byte you could use an unsigned char and iterate over it.
unsigned char* currByte = new unsigned char[100];
for(int i = 0; i < 100; ++i)
{
printf("| %02X |", currByte[i]);
}
It's not a very modern (or even very "C++") answer but it will print it as a hex value for you.