char string2char(String ipString){
char opChar[ipString.length() + 1];
memset(opChar, 0, ipString.length() + 1);
for (int i = 0; i < ipString.length(); i++)
opChar[i] = ipString.charAt(i);
}
Called as char charssId[AP_NameString.length()+1] = string2char(AP_NameString);
What is the right way to call the function? Want to change String ssid to char ssid, to make it compatible with esp8266 library.
char charssId[AP_NameString.length()+1] = string2char(AP_NameString);
This line is will not work. Because char charssId[AP_NameString.length()+1] this means you are declaring an array of certain size and at the same time replacing it with the returned array from the method.
You can do as follows,
char* string2char(String ipString){ // make it to return pointer not a single char
char* opChar = new char[ipString.length() + 1]; // local array should not be returned as it will be destroyed outside of the scope of this function. So create it with new operator.
memset(opChar, 0, ipString.length() + 1);
for (int i = 0; i < ipString.length(); i++)
opChar[i] = ipString.charAt(i);
return opChar; //Add this return statement.
}
// Now call this as below,
char* charssId = string2char(AP_NameString); // make the variable as pointer so that it can hold an array address.
// use it as a char array.
delete[] charssId; // Remember to delete it after finished using it.
There are many problems with your code.
Your function is declared as returning a single char, not an array of chars. And it is missing an actual return statement. But even if it weren't, you would be returning a local array that goes out of scope when the function exits, leaving the caller with a dangling pointer to invalid data.
You are declaring the opChar array in a non-standard way known as a "variable-length array". VLAs are a compiler-specific extension, and thus not portable. You need to dynamically allocate the array using new[] instead.
Try this:
char* string2char(const String &ipString){
char *opChar = new char[ipString.length() + 1];
/*
for (int i = 0; i < ipString.length(); i++)
opChar[i] = ipString.charAt(i);
*/
ipString.toCharArray(opChar, ipString.length());
opChar[ipString.length()] = '\0';
return opChar;
}
char *charssId = string2char(AP_NameString);
// use charssId as needed...
delete[] charssId;
A safer option is to use std::string instead:
std::string string2char(const String &ipString){
std::string opChar;
opChar.resize(ipString.length());
/*
for (int i = 0; i < ipString.length(); i++)
opChar[i] = ipString.charAt(i);
*/
ipString.toCharArray(opChar, ipString.length());
return opChar;
// alternatively:
// return std::string(ipString.c_str(), ipString.length());
}
std::string charssId = string2char(AP_NameString);
// use charssId.c_str() as needed...
But a conversion is actually not needed at all:
const char *charssId = AP_NameString.c_str();
// use charssId as needed...
You are returning pointer to first character of the array from the function and assigning it to the array, this is not possible. Learn more here.
To make it work you've got to assign a pointer returned from function to pointer variable -- like following:
char* charssId = string2char(AP_NameString);
// Do stuff
delete [] charssId;
and then access it like regular array:
charssId[index]
Thats already explained in answer above, so there are several approaches which handles this task easier.
First is toCharArray() method of string class
char opChar[ipString.length() + 1];
ipString.toCharArray(opChar, ipString.length());
// Do stuff
delete [] opChar;
Second is c_str() method of class string (string returned is const)
const char *unmodificable = ipString.c_str();
Related
At first, I would like to point out that despite using C ++ I cannot use strings or vectors. It is like C with objects.
Ok I have class A with char* test() method:
char* A::test()
{
char to_return[3*this->some_value+3];
for (int i = 0; i < this->some_value; i++)
{
to_return[3*i] = '♥';
to_return[3*i+1] = 'b';
to_return[3*i+2] = ' ';
}
char* dto_return = to_return;
return std::move(dto_return);
}
next in object of class B I have:
ofstream file;
file.open("myfile.txt", ofstream::out | ofstream::trunc);
file.close();
file.open("myfile.txt");
char* to_write = a_obj->test();
size_t len = strlen(to_write);
file.write((char*)&len, sizeof(len));
file.write(to_write, len);
file.close();
(based on this answer)
but the content of the file is:
¥b ¥b ¥b m
and it is definitely not what I'm looking for. The content should be:
♥b ♥b ♥b
How to fix that?
The problems are:
to_return is a local array that ends its lifetime on returning from the function, so returning its pointer is a bad idea.
'♥' may differ from what you want, especially when ♥ cannot be represented by one byte in your character code.
To overcome this problems:
Allocate a dynamic array that persists after returning from the function.
Use string literal to represent the characters to add.
char* A::test()
{
const char *part = "♥b ";
size_t part_len = strlen(part);
char *to_return = new char[part_len*this->some_value+1];
for (int i = 0; i < this->some_value; i++)
{
strcpy(to_return + part_len * i, part);
}
return to_return;
}
The dynamic array returned should be freed via delete[] after completed to use.
char* to_write = a_obj->test();
// ...
delete[] to_write;
I'm doing an exercise in which I have to copy a c-style string into memory allocated on free store. I am required to do it without using subscripting and relying solely on pointer arithmetic. I wrote the following function-
char* str_dup(const char* s)
{
// count no. of elements
int i = 0;
const char* q = s;
while (*q) { ++i; ++q; }
//create an array +1 for terminating 0
char* scpy = new char[i + 1];
//copy elements to new array
while (*s)
{
*scpy = *s;
++s;
++scpy;
}
*scpy = 0;
return scpy;
}
The function is returning random characters. But if I change it into this-
char* str_dup(const char* s)
{
// count no. of elements
int i = 0;
const char* q = s;
while (*q) { ++i; ++q; }
//create an array +1 for terminating 0
char* scpyx = new char[i + 1];
char* scpy = scpyx;
//copy elements to new array
while (*s)
{
*scpy = *s;
++s;
++scpy;
}
*scpy = 0;
return scpyx;
}
it works. Can someone explain me why first code is not working and second is working?
The first code is not working since you return the final value of scpy, which at that point points at the terminating NUL character, and not the start of the string.
One solution is to do as you did, and save a copy of the original pointer to have something to return.
You should really use strlen() and memcpy(), they make this easier but perhaps they're off-limits to you.
Everywhere I've looked for answers to this question, I see people making one small char * array of size like two and hardcoding in paths for execv. What I need to do is to take a string of parameters with the path as the first set of characters, tokenize them, and then put them in an array of char *s that execv will accept.
here is my tokenization function
char ** stringToVectorToCharArray(string inputString)
{
stringstream ss(inputString);
cout << "\n inputString is: " << inputString <<"\n";
vector<string> tokens;
tokens.clear();
while(ss >> inputString)
{
tokens.push_back(inputString);
}
int size = tokens.size();
char **args = new char*[size + 1];
int i = 0;
for(; i < size; i++)
args[i] = const_cast<char *>(tokens.at(i).c_str());
args[i + 1] = (char *) 0;
return args;
}
And this is called from
char **args = stringToVectorToCharArray(inputString);
execv(executeChar, args);
Within the Child section of my fork() if-else statements for flow control.
I get a bad_alloc error, but I'm not sure which of my allocation statements are right, if any are for that matter. I know the return has to be in the form
char *const argv[]
But I'm not sure how to set that up.
You are returning memory from a local variable (tokens) from your function.
for(; i < size; i++) {
// stores pointer to local memory: args[i] = const_cast<char *>(tokens.at(i).c_str());
args[i] = new char[tokens.at(i).size()+1]; // Create dynamically allocated copy
strcpy(args[i], tokens.at(i).c_str());
}
The above should fix the problem. Technically, this would create a memory leak, since the memory is never deallocated, but your call to execv will replace your executable and effectively deallocate the memory.
I wrote a function which receives as a parameter a char pointer,then builds a new dynamic allocated char array that contains that parameter char.Then,it returns the new char array.
This is the function:
char* read_string(char *pstr)
{
char *str;
str = new char[strlen(pstr)];//allocate memory for the new char
str[strlen(pstr)] = '\0';
for(unsigned i=0;i<strlen(pstr);i++)//build the new char
str[i]=pstr[i];
return str;//then return it
}
In main I have:
int main()
{
char *Pchar = read_string("Test");
cout<<Pchar;// Outputs "Test"
delete [] Pchar;//"Program received signal SIGTRAP, Trace/breakpoint trap." error
}
I declare a char pointer in main and then make it point to the char array that is returned from the read_string function.It outputs what I want but if I want to free the memory it gives me runtime error.How can I free up the memory if I don't need to use Pchar anymore?
EDIT:Thank you all for your very informative answers.I have successfully resolved the problem.
You need to allocate more memory to have space for EOS character:
str = new char[strlen(pstr)+1];
Your specific problem is an off-by-one error:
str = new char[strlen(pstr) + 1];
// ^^^^ need one more for the '\0'
str[strlen(pstr)] = '\0';
Generally, since this is C++ and not C, it would be better to return a smart pointer so the caller knows what the ownership semantics of the pointer are:
std::unique_ptr<char[]> read_string(char *pstr)
{
std::unique_ptr<char[]> str(new char[strlen(pstr) + 1]);
// rest as before
return str;
}
It seems that the error occurs due to incorrect length of the allocated string.
You have to use the following record to allocate the string
str = new char[strlen(pstr) + 1];//allocate memory for the new char
str[strlen(pstr)] = '\0';
The function can look the following way
char* read_string( const char *pstr )
{
char *str;
size_t n = strlen( pstr );
str = new char[n + 1];//allocate memory for the new char
strcpy( str, pstr );
return str;
}
Right off the bat, I'm required to use dynamically allocated character arrays for my assignment, so do NOT suggest I just use strings. I need to create a method that accepts a character array as an argument, and inserts that character into a char* using strcpy. How do I do this without first initializing the char*?
Here is my code so far:
char* char_array;
char test_array[] = {'t','e','s','t','\0'};
strcpy(char_array, test_array);
Your char_array is just an unitialized pointer. You need to dynamically allocate memory for it and then carry out strcpy.
char* char_array = new char[6];
char test_array[] = {'t','e','s','t','\0'};
strcpy(char_array, test_array);
Or as suggested by Joachim you can use strdup() to duplicate a string - it will allocate the memory and copy the string into it.
In both cases, don't forget to free() (or delete[]) the resulting memory once you're done with it.
You can't do that unless you actually allocate a chunk of memory for char_array through malloc or new.
int length = 6;
char* char_array = (char*) malloc(sizeof(char) * length);
or
char* char_array = new char[6];
char * char_array = NULL;
void yourFunc(char your_array[]) {
if (NULL != char_array) {
free(char_array);
char_array = NULL;
}
char_array = (char *)malloc(sizeof(char) * strlen(your_array));
strcpy(char_array, your_array);
}
you stated you need a method/function that accepts a char[]/char *
you have stated your constraints ...
this does seem to be low level for instructional purpose
I assuming null terminated character array and valid source character array
//function accepts character array
char * charseqduplicate(char * s)
{
//low level c
const int len = strlen(s) + 1;;
char * copy = new char[len];
strcpy(copy, s);
//remember to delete or use something like unique_ptr
return copy;
}
void letsdothis()
{
//low level c
char test[] = {'y','e','s',char(0)};
char * dup = charseqduplicate(test);
cout << dup;
delete [] dup;
}