My problem is that I don't know how to convert int value to char array char* m_value. I tried to use itoa but it doesn't work. itoa(m_val, m_wartosc, 10); Maybe there is some other function to do this ?
Main.cpp
int main(int argc, char *argv[])
{
LargeNumber l1;
LargeNumber l3(172839); //how to convert this int to char*
return 0;
}
LargeNumber.h
class LargeNumber{
public:
LargeNumber()
{
m_array = "0"; //zero for no arg.
}
LargeNumber(int val):m_val(val)
{
itoa(m_val, m_array, 10); //doesn't work
//sprintf(m_array, "%d", m_val);
}
LargeNumber(const LargeNumber& p):m_array(p.m_array)
{ } //copy constructor
~LargeNumber(){
delete []m_array; //for object with new
}
public: //should be private
int m_val;
char* m_array;
};
The simple answer is: don't. For two reasons:
As you can see from all the (wrong) other answers, memory management is tricky and bug-prone.
I can't see how storing your value in base-10, in an ASCII string, could possibly be useful. (Compared to, say, a base-232 representation.)
But if you really must store it this way, you will need to allocate the relevant amount of memory, use snprintf to convert (itoa is a non-standard function), and remember to free the memory at the correct time(s) (you will have to read and understand about the Rule of Three).
I would strongly recommend using a std::string instead of a raw C-style array, because it will at least deal with its own memory management, and you will then be able to populate it with a std::stringstream.
The second argument of itoa() needs to be an array in memory large enough to store the null-terminated string. An example:
int number = 172839;
char buffer[10];
itoa(number,buffer,10);
LargeNumber(int val):m_val(val)
{
std::stringstream stream;
stream << val;
m_array = new char[stream.str().size()];
strcpy(m_array, stream.str().c_str());
}
You have to first allocate the array with
m_array = new char[20]
in constructor before calling iota.
the iota doesnt allocate memory.
Related
I am working on a function encode data into buffer. I already have functions for the encoding part.
I am encoding and then i push back into a uint8_t vector, which is my output buffer.
For the ints i have no problem, i use my function and everything is done, but now i have to encode a string.
There is already a function made by some developpers before me, which takes as argument char** (buffer to fill), size_t*, and char* which is the string i'm going to encode.
For the char * i just do .c_str() with my string in my C++ object but i don't know what to do about the buffer to fill, because i'm actually using a uint8_t vector.
I thinked about creating a temporary buffer then pushing it in the vector by casting it, is it a good way?
Here is my class (the mother class which is virtual but the string is here so i show you this one):
class CDnsMessage
{
public:
CDnsMessage();
virtual ~CDnsMessage();
virtual void GetSize() = 0;
uint32_t m_ttl;
eDnsClass m_class;
eDnsType m_type;
std::string m_domain;
uint8_t m_sizeDnsCorpse;
uint8_t m_sizeDomainName;
};
The encode part:
std::vector<uint8_t>& output
char * buffer;
std::size_t* bufsz;
EncodeSmallString(*buffer,*bufsz,RR_A_msg->m_domain.c_str());
output.push_back((uint8_t)buffer)
The encoding part needs to look like
char* buffer;
std::size_t bufsz;
EncodeSmallString(&buffer, &bufsize, RR_A_msg->m_domain.c_str());
(You pass in the address of a buffer pointer and size, and the function will allocate the buffer for you.)
Now you need to copy the temporary buffer into your output. This is not a cast, this is a matter of copying each byte. This being C++ there are a zillion ways to do this, but something like:
for (std::size_t i = 0; i<bufsiz;i++) {
output.push_back(static_cast<uint8_t>(buffer[i]));
}
will work (you could also use std::copy or std::vector::insert).
Finally, you need to free the temporary buffer. You will have to look at the documentation of EncodeSmallString to see how to do that - the most likely answers are free or delete[] depending on whether it was allocated with malloc or new [].
I would be very tempted to rewrite EncodeSmallString in terms of appending to a vector, and then write a wrapper overload (with the existing signature) something like:
void EncodeSmallString(char** pbuf, std::size_t* pbufsiz, const char* txt) {
std::vector<uint8_t> temp;
EncodeSmallString(temp, txt);
*pbufsiz = temp.size();
*pbuf = malloc(*pbufsiz); // or new or whatever the existing code uses.
// add error handling to taste
std::copy(*pbuf, temp.begin(), temp.end());
}
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].
i have a member function in which i need to get some char array at run time
My fear
Is if i try
delete buffer;
then i cant
return buffer;
But how to i release the memory i allocated with
char * buffer= new char[size]
The class
class OpenglShaderLoader
{
char * getLastGlslError()
{
char * buffer;//i don't know the size of this until runtime
int size;
glShaderiv(hShaderId,GL_INFO_LOG_LENGTH,&size);//get size of buffer
buffer= new char[size];
//.. fill in the buffer
return buffer;
}
}
You should return a std::vector<char>. That way, when the caller finishes using the vector, its contents are freed automatically.
std::vector<char> getLastGlslError()
{
int size;
glShaderiv(hShaderId, GL_INFO_LOG_LENGTH, &size);
std::vector<char> buffer(size);
// fill in the buffer using &buffer[0] as the address
return buffer;
}
There is a simple adage - for every new there must be a delete, in your case, in relation to the class OpenglShaderLoader, when you call getLastGlsError, it returns a pointer to the buffer, it is there, that you must free up the memory, for example:
OpenglShaderLoader *ptr = new OpenglShaderLoader();
char *buf = ptr->getLastGlsError();
// do something with buf
delete [] buf;
You can see the responsibility of the pointer management rests outside the caller function as shown in the above code example/
You'd need another method, such as:
void freeLastGlslError(const char* s)
{
delete [] s;
}
But since you're using C++, not C, you shouldn't return a char*. For an object-oriented design, use a string class that manages the memory for you, like std::string. (Here's the litmus test to keep in mind: if memory is being freed outside of a destructor, you're probably doing something inadvisable.)
Here's a trick how to do it:
class A {
public:
A() : buffer(0) { }
char *get() { delete [] buffer; buffer = new char[10]; return buffer; }
~A() { delete [] buffer; }
private:
char *buffer;
}
When you return that pointer, whatever you're returning the pointer to should assume responsibility over that resource (i.e. delete it when done with it).
Alternatively, you can use a smart pointer to automatically delete the memory for you when nothing points to it.
Creating and returning a stl container or class (e.g. std::vector, std::string) is also a viable option.
Don't return a primitive char*. Encapsulate it in a class.
Assuming that the char array is really not a NULL terminated string, you need to include the size of it on return anyway. (It is sort of messy to continuously call glShaderiv to get the length, especially if it has performance implications. Easier to store the size with the allocation.)
Some have suggested using std::string or std::vector as the return. While each of these will work to a varying degree, they don't tell you what it is that is in each instance. Is it a string you print or is it an array of signed 8 bit integers?
A vector might be closer to what you need, but when you're looking at the code a year from now you won't know if the output vector of one method contains shader info when compared to another method that also returns a vector. There may also be implications of vector that make it undesirable for things like filling the buffer by passing a pointer to a device driver method since the storage is technically hidden.
So putting the return in a class that allocates your buffer and stores the size of the allocation allows you to let the return instance go out of scope and delete the buffer when the caller is done with it.
now body mentioned managed pointers yet?
If you don't need the features of a vector then ::array_ptr<char> might also help rather than rolling your own as in tp1's answer. Depending on version of compiler, available in boost/TR1/std.
boost::array_ptr<char> getLastGlslError()
{
int size;
glShaderiv(hShaderId, GL_INFO_LOG_LENGTH, &size);
boost::array_ptr<char> buffer = new char[size];
return buffer;
}
In my application, I create a char* like this:
class sample
{
public:
char *thread;
};
sample::sample()
{
thread = new char[10];
}
sample::~sample()
{
delete []thread;
}
Am I doing the right thing in the code?
If you have [] after your new, you need [] after your delete. Your code looks correct.
List of points to be noted:
1) You need to allocate room for n characters, where n is the number of characters in the string, plus the room for the trailing null byte.
2) You then changed the thread to point to a different string. So you have to use delete[] function for the variable you are created using new[].
But why are you fooling around with new and delete for character data? Why not just use std::string, instead of 'C' functions? It's amazing why so many don't do the easiest thing:
#include <cstdio>
#include <string>
int countWords(const char *p);
int main(int argc, char *argv[])
{
std::string pString = "The Quick Brown Fox!";
int numWords1 = countWords(pString.c_str());
printf("\n\n%d words are in the string %s", numWords1, pString.c_str());
int numWords2 = countWords(argv[1]);
printf("\n%d words are in the string %s", numWords2, argv[1]);
}
No need for new[], delete[], strcpy(), etc.
Use strlen(). Better yet, don't use char* and use std::string for string data.
It's "right"*, but it's very wrong.
You should not use new[], but instead use std::vector<char> or std::string. Even if you weren't doing that, you need to respect the rule of three, or your class is broken.
*Assuming you meant new char[10]. Also, more orthodox is delete[] thread.
Consider the following code:
char CeaserCrypt(char str[256],int key)
{
char encrypted[256],encryptedChar;
int currentAsci;
encrypted[0] = '\0';
for(int i = 0; i < strlen(str); i++)
{
currentAsci = (int)str[i];
encryptedChar = (char)(currentAsci+key);
encrypted[i] = encryptedChar;
}
return encrypted;
}
Visual Studio 2010 gives an error because the function returns an array. What should I do?
My friend told me to change the signature to void CeaserCrypt(char str[256], char encrypted[256], int key). But I don't think that is correct. How can I get rid of the compile error?
The return type should be char * but this'll only add another problem.
encrypted is "allocated" on the stack of CeaserCrypt and might not be valid when the function returns. Since encrypted would have the same length as the input, do:
int len = strlen(str);
char *encrypted = (char *) malloc(len+1);
encrypted[len] = '\0';
for (int i = 0; i < len; i++) {
// ...
}
Don't forget to deallocate the buffer later, though (with free()).
EDIT: #Yosy: don't feel obliged to just copy/paste. Use this as a pointer to improve your coding practice. Also, to satisfy criticizers: pass an already allocated pointer to your encryption routine using the above example.
It wants you to return a char* rather than a char. Regardless, you shouldn't be returning a reference or a pointer to something you've created on the stack. Things allocated on the stack have a lifetime that corresponds with their scope. After the scope ends, those stack variables are allowed to go away.
Return a std::vector instead of an array.
std::vector<char> CeaserCrypt(char str[256],int key)
{
std::vector<char> encrypted(256);
char encryptedChar;
int currentAsci;
encrypted[0] = '\0';
for(int i = 0; i < strlen(str); ++i)
{
currentAsci = (int)str[i];
encryptedChar = (char)(currentAsci+key);
encrypted[i] = encryptedChar;
}
return encrypted;
}
There's another subtle problem there though: you're casting an integer to a character value. The max size of an int is much larger than a char, so your cast may truncate the value.
Since you're using C++ you could just use an std::string instead. But otherwise, what your friend suggested is probably best.
There are a few problems here. First up:
char CeaserCrypt(char str[256],int key)
As others have pointed out, your return type is incorrect. You cannot return in a single character an entire array. You could return char* but this returns a pointer to an array which will be allocated locally on the stack, and so be invalid once the stack frame is removed (after the function, basically). In English, you'll be accessing that memory address but who knows what's going to be there...
As your friend suggested, a better signature would be:
void CeaserCrypt(char* encrypted, const char str*, const size_t length ,int key)
I've added a few things - a size_t length so you can process any length string. This way, the size of str can be defined as needed. Just make sure char* encrypted is of the same size.
Then you can do:
for(int i = 0; i < length; i++)
{
// ...
For this to work your caller is going to need to have allocated appropriately-sized buffers of the same length, whose length you must pass in in the length parameter. Look up malloc for C. If C++, use a std::string.
If you need C compatibility make encrypted string function argument.
If not, than use C++ std::string instead C style string.
And also In your code encrypted string isn't ending with '\0'
The problem with the original code is that you are trying to return a char* pointer (to which your local array decayed) from a function that is prototyped as one returning a char. A function cannot return arrays in C, nor in C++.
Your friend probably suggested that you change the function in such a way, that the caller is responsible for allocation the required buffer.
Do note, that the following prototypes are completely equal. You can't pass an array as a parameter to normal function.
int func(char array[256]);
int func(char* array);
OTOH, you should (if you can!) decide the language which you use. Better version of the original (in C++).
std::vector<unsigned char> CeaserCrypt(const std::string& str, const int key)
{
std::vector<unsigned char> encrypted(str.begin(), str.end());
for (std::vector<unsigned char>::iterator iter = vec.begin();
iter != vec.end(); ++iter) {
*iter += key;
}
return vec;
}
Do note that overflowing a signed integer causes undefined behavior.
VS2010 is "yelling" at you because you are trying to return a value that is allocated on the stack, and is no longer valid once your function call returns.
You have two choices: 1) Allocate memory on the heap inside your function, or 2) use memory provided to you by the caller. Number 2 is what your friend in suggesting and is a very good way to do things.
For 1, you need to call malloc() or new depending on whether you are working in C or C++. In C, I'd have the following:
char* encrypted = malloc(256 * sizeof(char));
For C++, if you don't want to use a string, try
char* encrypted = new char[256];
Edit: facepalm Sorry about the C noise, I should have looked at the question more closely and realized you are working in C++.
You can just do your Ceaser cipher in place, no need to pass arrays in and out.
char * CeaserCrypt(char str[256], int key)
{
for(unsigned i = 0; i < strlen(str); i++)
{
str[i] += key;
}
return str;
}
As a further simplification, skip the return value.
void CeaserCrypt(char str[256], int key)
{
for(unsigned i = 0; i < strlen(str); i++)
{
str[i] += key;
}
}
well what you're returning isn't a char, but a char array. Try changing the return type to char*(char* and a char array are ostensibly the same thing for the compiler)
char* CeaserCrypt(char str[256],int key)
EDIT: as said in other posts, the encrypted array will probably not be valid after the function call. you could always do a new[] declaration for encrypted, remembering to delete[] it later on.