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';
}
Related
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.
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;
I try to build a function which deletes the last element of an array. So I need an input array and its dimension, then delete the last term and obtain a new output array. I don't want that. My goal is to somehow make the output array the new input array. In other words, I want to overwrite the input array with the output array.
So if dimension is 4, I don't want to have a 4-dim array in the memory but only 3-dim table after the deletion.
void del (int* ptr_array, int dim) {
int* temp = ptr_array; //Hold the very first address of the input array.
ptr_array = new int[dim - 1]; // Let the address of the input array be
// the address of new output array. Overwritting.
for (int i = 0; i < dim - 1; i++) {
ptr_array = (temp+i); // Will it remember what is temp+1 if I have
// already overwritten the arrays?
ptr_array++;
}
//delete[] ptr_array; - this one is out of the questions - deletes now the input table.
}
Can you tell me what is wrong with this code? - in fact it doesn't change anything
in you function
for (int i = 0; i < dim - 1; i++) {
ptr_array = (temp+i); // Will it remember what is temp+1 if I have
// already overwritten the arrays?
ptr_array++;
}
does nothing, you wanted
for (int i = 0; i < dim - 1; i++) {
ptr_array[i] = temp[i];
}
Note the delete in your comment is invalid because you do not delete the result of a new[] but a pointer inside the allocated array
If the call is like
int * v = ...;
del(v);
// here v is unchanged
probably you wanted to modify v, in that case you can return the new array or to use an input-output variable using a reference
First possibility :
int* del (int* ptr_array, int dim) {
int* new_array = new int[dim - 1];
for (int i = 0; i < dim - 1; i++) {
new_array[i] = ptr_array[i];
}
delete[] ptr_array;
return new_array;
}
with
int * v = ...;
v = del(v);
Second possibility
void del (int*& ptr_array, int dim) {
int* new_array = new int[dim - 1];
for (int i = 0; i < dim - 1; i++) {
new_array[i] = ptr_array[i];
}
delete[] ptr_array;
ptr_array = new_array;
}
with
int * v = ...;
del(v);
// here v is the new array
Warning these codes suppose the input array has at least one element
However the use of an std::vector<int> does all of that for you and is more practical to use
std::vector<int> v;
...
v.resize(v.size() - 1);
or
std::vector<int> v;
...
v.pop_back();
I get very frustrating error in following piece of code. Thats my array.
int **tab2 = new int*[3];
I allocate this like it.
for(i = 0; i < 10; i++) {
tab2[i] = new int[3];
tab2[i][0] = 40;
tab2[i][1] = 10;
tab2[i][2] = 100;
}
Then after using it i want to destroy it.
for(i = 0; i < 10; i++) {
delete [] tab2[i];
}
delete [] tab2;
And this causes core dump every single time. I tried many different ways to destroy it and every time get this error. What im making wrong here ?
This
int **tab2 = new int*[3];
does not do what you think it does.
You want an array that will contain TEN (10) pointers, each to an array of THREE ints.
new int*[3] is an array that contain THREE pointers.
What you want is this (live at coliru):
#include <iostream>
int main() {
int **tab2 = new int*[10];
for(int i = 0; i < 10; i++) {
tab2[i] = new int[3];
tab2[i][0] = 40;
tab2[i][1] = 10;
tab2[i][2] = 100;
}
for(int i = 0; i < 10; i++) {
delete [] tab2[i];
}
delete [] tab2;
}
With
int **tab2 = new int*[3];
you allocate an array of pointers of size 3. But than with
for(i = 0; i < 10; i++) {
tab2[i] = new int[3];
//...
}
you access it with up to index 9. That will surely go wrong.
The deletion process looks fine to me. To fix it, you should allocate an array of pointers with size 10instead of 3, e.g.
int **tab2 = new int*[10];
Looks like what you're trying to do is to create an N by M array, where N is known at runtime and M is fixed (in this case, 3).
Why not just do this?
{
std::array<int, 3> defaults = {{ 40, 10, 100 }};
std::vector<std::array<int, 3>> thing(10, defaults);
}
The vector, thing is automatically deallocated when it goes out of scope, and its size can be set at runtime. You still access the structure in the same way:
thing[1][2] = 3
Manual memory management can be easily avoided by using standard containers and smart pointers. Doing so will keep you code cleaner, and have fewer opportunities for dangling pointers and memory leaks.
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.