How can I convert vector<string> to char* arr[]? - c++

Recently I want to convert vector to char* array[].
So I had found the solution. But It was not safety way..
Here is my code
char** arr = new char* [4];
vector<string> vv;
// setting strings
for (int i = 0 ;i < 4; i++)
{
vv.emplace_back("hello world");
}
// convert
for (int i = 0; i < 4; i++)
{
arr[i] = new char[vv[i].size()];
memcpy(arr[i], vv[i].c_str(), vv[i].size());
}
// prints
for (int i = 0; i < 4; i++)
{
cout << arr[i] << endl;
}
// output
// hello world羲羲?솎솨
// hello world羲羲拂솽솨
// hello world羲羲
// hello world羲羲?펺솨
// delete memorys
for (unsigned index = 0; index < 4; ++index) {
delete[] arr[index];
}
delete []arr;
Why does it happen string crash??
Is there no safe way anymore?

When you use memcpy, arr[i] is not guaranteed to be a null-terminated string. To treat arr[i] as null terminated string, as in
cout << arr[i] << endl;
causes undefined behavior.
You need couple of minor changes.
Allocate one more byte of memory.
Use strcpy instead of memcpy.
arr[i] = new char[vv[i].size() + 1];
strcpy(arr[i], vv[i].c_str());

There's an easier way of doing this if you can maintain the lifetime of your initial vector.
for (int i = 0; i < 4; i++)
{
arr[i] = vv[i].c_str();
}
This way you won't allocate no additional memory, however, you'd have to keep in mind that once your initial vector gets destroyed, that array will be corrupted as well. But if you need such conversion for some simple synchronous api call within the same thread, that would do the trick.

In such cases I usually use this ugly construct.
arr[i] = new char[vv[i].size() + 1];
arr[i][vv[i].copy(arr[i], vv[i].size())] = 0;

Related

How to create and store string data in multidimensional array?

How can I create and store string data in a multidimensional array using pointers? My attempt is:
// I declaring row 3 and column 2
string** arr = new string*[3][2]; // I am having issue in here
// I am trying to add data
arr[0] = {"first", "second"};
If you want to be able to initialize a whole sub-array like that with {"first", "second"}, you most likely would need to use a std::vector or std::array instead of manually allocating the memory for the array. Unless you have very specific reasons for using pointers, here is how it could look with vectors:
using str_vec = std::vector<std::string>;
std::vector<str_vec> v(3, str_vec(2, ""));
v[0] = {"first", "second"};
But if you really need pointers, then you'll have to first allocate the memory for the "row" and then do separate allocations for each "column":
std::string** a = new std::string*[3];
for(int i = 0; i < 3; ++i) {
a[i] = new std::string[2];
}
After which you can fill the values one by one:
a[0][0] = "first";
a[0][1] = "second";
And don't forget about deleting all these arrays after you are done. In the reverse order, you first need to delete all columns and then the "row":
for(int i = 0; i < 3; ++i) {
delete[] a[i];
}
delete[] a;
There is mistake in the first line of initialization.
Initialize it like this if you want to avoid any error.
string** arr = new string*[3];
/* It will have count of rows of string you will have like in this statement 3 rows of string. */
// Now you will have to tell about columns for each row separately.
for(int i = 0; i < 3; i++) {
arr[i] = new string[2]; // Here you are initializing each row has 2 columns
}
// Now write your code below...
you can rewrite yours code as following :
string **arr = new string*[3]; // row 3
for(unsigned i = 0; i < 3; i++)
arr[i] = new string[2](); // column 2
arr[0][0] = "first"; arr[0][1] = "second";
for(unsigned i = 0; i < 3; i++){. // yours ans
for(unsigned j = 0; j < 2; j++)
cout << arr[i][j] << " ";
cout << '\n';
}

The program crashes sometimes and works perfectly fine sometimes. A variable array is declared and its size changes 2 times in the program

The program crashes sometimes and works perfectly fine sometimes. A variable array is declared and its size changes 2 times in the program. I am using visual studio. It is in c++.
This is the code in c++:
int sz; //size of array
std::cin >> sz; //getting size
int* arr = new int[sz]; //declaring variable array.
for (int i = 0; i < sz; i++)
{
arr[i] = i; //assigning values to all members of array
std::cout << arr[i] << std::endl; //printing the array
}
std::cin >> sz; //size changes again
for (int i = 0; i < sz; i++)
{
arr[i] = i; //assigning new values
std::cout << arr[i] << std::endl; //printing the array
}
On this line:
std::cin >> sz; //size changes again
The comment is not really correct. The variable representing the size is changed, but the array arr is not changed. So indexing into any position greater than or equal to the old size will invoke undefined behavior. This means the program may work sometimes, and not others.
To resize the arr array, after the above line you need to do:
delete [] arr;
arr = new int[sz];
If you want to resize arr you must delete the old one and allocate a new one
delete[] arr;
arr = new int [sz];
If you allocate a vector with new you should delete it after you no longer need it, and don't reuse it arbitrarily so your code would be better as:
int sz; //size of array
{
std::cin >> sz; //getting size
int* arr = new int[sz]; //declaring variable array.
for (int i = 0; i < sz; i++)
{
arr[i] = i; //assigning values to all members of array
std::cout << arr[i] << std::endl; //printing the array
}
delete [] arr; // << Delete old one here, missing in original
}
{
std::cin >> sz; //size changes again
int* arr = new int[sz];
for (int i = 0; i < sz; i++)
{
arr[i] = i; //assigning new values
std::cout << arr[i] << std::endl; //printing the array
}
delete [] arr; // <<--- Here as well, missing in original - less important, but leads to memory leak.
}
or just use std::vector<int> arr(sz); and you can ignore the delete. If you absolute need to re-use the array use arr.resize(sz);

I am having a bad access issue

I am trying to create a merge function for two array structures in c++ but am coming up with a bad access error that I don't know how to solve. The error comes up when I am trying to swap the element in the smaller array into the larger, merged array. The code doesn't even go through a single iteration. All three of i, j, and k remain at 0. Any help would be greatly appreciated! Here is the code:
struct Array
{
int *A;
int size;
int length;
};
void display(Array arr){
for (int i = 0; i < arr.length; i++)
std::cout << arr.A[i] << std::endl;
}
Array merge(Array arr1, Array arr2){
Array arr3;
arr3.length = arr1.length + arr2.length;
arr3.size = arr1.length + arr2.length;
int i = 0, j =0, k =0;
while(i <arr1.length && j < arr2.length){
if (arr1.A[i] < arr2.A[j])
{
arr3.A[k] = arr1.A[i]; //(The error is displayed here: Thread 1: EXC_BAD_ACCESS (code=1, address=0x28))
k++;
i++;
}
else if (arr2.A[j] < arr1.A[i])
{
arr3.A[k] = arr2.A[j];
k++;
j++;
}
}
for (; i< arr1.length; i++)
{
arr3.A[k]=arr1.A[i];
k++;
}
for (; i< arr2.length; j++)
{
arr3.A[k]=arr2.A[j];
k++;
}
return arr3;
}
int main() {
Array arr1;
arr1.size = 10;
arr1.length = 5;
arr1.A = new int[arr1.size];
arr1.A[0]= 2;
arr1.A[1]= 6;
arr1.A[2]= 10;
arr1.A[3]= 15;
arr1.A[4]= 25;
Array arr2;
arr2.size = 10;
arr2.length = 5;
arr2.A = new int[arr2.size];
arr2.A[0]= 3;
arr2.A[1]= 4;
arr2.A[2]= 7;
arr2.A[3]= 18;
arr2.A[4]= 20;
Array arr3 = merge(arr1, arr2);
display(arr3);
return 0;
}
Your Array arr3 does not allocate any memory for its int *A field. It's natural that it would not work.
Anyway, your implementation of Array is very poor. Don't reimplement arrays unless you have a good reason; use std::vector instead.
If you really need to implement an Array on your own, then learn about encapsulation, make a class with a constructor, and allocate/delete your data (*A) field properly. Remember, using pointers and heap memory without understanding them is a recipe for disaster.
Easy: arr3.A is not initialized. It's a pointer. What does it point to?
Suggestion: learn about dynamic memory allocation.

Deleting dynamic char** in C++

Disclosure: I'm trying to solve a challenge with strict time and memory limits. I would normally use vectors and strings, but here I need the fastest and smallest solution (with vectors it actually ran above the time limit), so I turned to dynamic arrays of char*.
The relevant parts of my code:
char** substrings(string s, int* n){
*n = 0;
...
////////////////////////////////
char** strings = new char*[*n];
////////////////////////////////
for (int i = 0; i < s.length(); i++){
for (int j = 1; j < s.length() - i + 1; j++){
...
strings[si] = tmp;
...
}
}
return strings;
}
int main(){
...
for (int ti = 0; ti < t; ti++){
cin >> s;
char** substr = substrings(s, &n);
...
for (int i = 0; i < n; i++){
delete substr[i];
}
}
return 0;
}
Everything runs just fine without deleting the array (of arrays), but that is unacceptable, so how do I go about this? I've tried a lot of variations that seemed logical but I get runtime errors.
It is similar to allocating, but in reverse order, and using delete[] instead of new[]:
for(int i = 0; i < LENGTH; i++)
delete[] strings[i]; // delete each pointer in char** strings
delete[] strings; // finally delete the array of pointers
I assumed here that LENGTH is the length of the array of pointers to char*. So it looks that you only perform the first round of de-allocation
for (int i = 0; i < n; i++){
delete substr[i]; // need delete[] substr[i] here
but with delete instead of delete[], you need delete[] substr[i] instead, as my guess is that substr[i] is a char* pointer pointing the first element of an array of chars allocated by new[]. You finally need the additional
delete[] substr;

How to make pointers to chars in the second array

I have an array of chars. n is array's length
char tab[n];
cin.get(tab, n);
cout<<tab<<"\0"<<endl;
then I create second array
char* t = new char[n];
for(int i = 0; tab[i] != '\0'; i++){
t[i] = tab[i];
}
I would like to have pointers to corresponding element. I mean t[2] contains addres of tab[2]. Then I would like to sort array t so tab stays as it was and only t shuffles but when I make change in the array t for example
t[2] = 'a';
I loose t[3]t[4]....
EDIT:
do{
for(int i = 0; i < n -1; i++){
if(t[i] > t[i+1]){
char* x = &t[i];
t[i] = t[i+1];
t[i+1] = *x
}
n--;
}
}while(n>1);
I would like to have pointers to corresponding element. I mean t2 contains addres of tab2.
So try this:
char** t = new (char*)[n];
for(int i = 0; tab[i] != '\0'; i++){
t[i] = tab+i; // or `&(tab[i])`
To sort the t array based on tab values, use *t[i] to access character values stored in location i of the t array.
See here and here for good tutorials about C pointers.