C++ Variable-sized arrays using stdin and stdout - c++

I'm trying to solve this problem on variable-sized arrays but I'm getting a compilation error. Not exactly sure where I went wrong.
Problem can be accessed in this PDF
My solution attempt is as follows:
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
/* Enter your code here. Read input from STDIN. Print output to STDOUT */
int n,q,size,elem,index,smallindex;
//input of n and q
cin>>n>>q;
//declare the array a
int* bigarr = new int[q];
//assign the individual arrays to each element of the array a
for (int i=0; i<n; ++i){
//input of size of the individual array
cin>>size;
int* smallarr = new int[size];
for (int j=0; j<size; ++j){
smallarr[j] = cin>>elem;
}
bigarr[i] = smallarr;
}
//obtain index queries
for (int k=0; k<n; ++k){
cin>>index;
cin>>smallindex;
cout<<bigarr[index][smallindex];
}
}

On this statement:
bigarr[i] = smallarr;
smallarr is an int* pointer, but bigarr is also an int*, ie an array of int, so bigarr[i] is a single int. You can't assign an int* pointer to an int value.
If you want bigarr to be an array of pointers to other arrays, you need to declare bigarr as int** instead of int*, and then use new int*[q] to allocate it.
int** bigarr = new int*[q];
Also, on this statement:
smallarr[j] = cin>>elem;
The expression cin>>elem returns an istream& reference to cin, it does not return the int value read into elem, like you are expecting. So you can't use the result of that expression directly in the assignment to smallarr[j]. You will have to read elem and assign it to smallarr in separate statements:
cin>>elem;
smallarr[j] = elem;
That said, note that your code is leaking all of the allocated arrays since there are no calls to delete[] anywhere. You need to add them:
int** bigarr = new int*[q];
...
for (int i=0; i<n; ++i){
...
int* smallarr = new int[size];
...
bigarr[i] = smallarr;
}
...
for (int i=0; i<n; ++i){
delete[] bigarr[i]; // <-- here
}
delete[] bigarr; // <-- here
Though, you really should be using std::vector instead of using new[]/delete[] manually at all (you already have #include <vector>):
std::vector<std::vector<int> > bigarr(q);
...
for (int i=0; i<n; ++i){
...
std::vector<int> smallarr(size);
for (int j=0; j<size; ++j){
...
smallarr[j] = elem;
}
bigarr[i] = smallarr;
/* alternatively:
bigarr[i].resize(size);
for (int j=0; j<size; ++j){
...
bigarr[i][j] = elem;
}
*/
}
I also see is that you are using q to allocate bigarr, but then you use n to loop through bigarr. You don't need two separate variables. Use either n or q for both tasks, and get rid of the other variable.
Unless you really intend to allocate more slots then you want to fill in. In which case, your outer loop needs to ensure that it doesn't exceed both n and q:
for (int i=0; (i<n) && (i<q); ++i){
Or:
for (int i=0; i<std::min(n,q); ++i){

Related

How convert 2d vector to 1d array in C++?

I need to be able to do this without using C++ smart pointers. I tried the following
double* VecToArr(std::vector<std::vector<double>> vec) {
double* newarr=new double(vec.size());
for (int i=0; i<vec.size(); i++) {
std::copy(vec[i].begin(), vec[i].end(), newarr);
newarr += vec[i].size();
}
std::cout<<"inside \n";
for (int i=0; i<vec.size(); i++) {
std::cout<<newarr[i]<<"\n";
}
return newarr;
}
int main(){
std::vector<double> x{1,2};
std::vector<double> y{3,4};
std::vector<std::vector<double>>vec;
vec.push_back(x);
vec.push_back(y);
double *arr=VecToArr(vec);
std::cout<<"outside \n";
for (int i=0; i<4; i++) {
std::cout<<arr[i]<<"\n";
}
}
But inside the VecToArr, the output is:
inside
4.54e-322 2.18e-317 4.34e-311 4.24e-314
not 1 2 3 4 like I expected
And outside it, I get the same garbage values. Why is this?
Also, since I used new to create newarr inside VecToArr, where how do I delete it? In main.cpp, after I print out the values, do I just do delete arr[]?
EDIT
When I change the function to:
double* VecToArr(std::vector<std::vector<double>> vec) {
double* newarr=new double[vec.size()*vec[0].size()];
for (int i=0; i<vec.size(); i++) {
std::copy(vec[i].begin(), vec[i].end(), newarr);
newarr += vec[i].size();
}
std::cout<<"inside \n";
for (int i=0; i<vec.size(); i++) {
std::cout<<newarr[i]<<"\n";
}
return newarr;
}
The output is now 3 4 (garbage) (garbage) instead of 1 2 3 4.
The three main problems are as others have mentioned in the comments and a bit more. Firstly, you're using the wrong type of new expression, new double(...) simply allocates memory for a single double and initializes it with the value of what was provided. You probably want new double[...] to allocate an array of the doubles.
Secondly, the size provided to this new is incorrect, only representing the first dimension of the vector (when it needs to be a sum of all the nested vectors' sizes).
Finally, you're returning newarr, which has been modified by the for loop inside the function and ends up pointing to the memory after where the allocation took place, you'll likely want to make a temporary copy of it at the start and return that instead.
With all the changes the final correct function may look like this:
double* VecToArr(std::vector<std::vector<double>> vec) {
std::size_t totalsize = 0;
for (int i=0; i<vec.size(); i++) {
totalsize += vec[i].size();
}
double* newarr=new double[totalsize];
double* walkarr=newarr;
for (int i=0; i<vec.size(); i++) {
std::copy(vec[i].begin(), vec[i].end(), walkarr);
walkarr += vec[i].size();
}
return newarr;
}
I'd also recommend passing the vector in by constant reference as currently it is being passed by value for (currently) no reason which may result in unnecessary overhead. Additionally, you should try to always use something like std::vector (or at least smart pointers) for allocation of memory rather than using new/delete directly (unless dealing with low level container implementation) as there is usually not much reason to at the expense of opening the program up to memory leaks.
There are issues with memory allocation, indexing and pointer arithmetic. I have pointed out those in your code.
#include <iostream>
#include <vector>
double* VecToArr(const std::vector<std::vector<double>>& vec) {
double* newarr=new double[vec.size() * vec[0].size()]; // <-- you have 4 elements (also notice square brackets)
double* newarr_ptr_copy = newarr;
for (int i=0; i<vec.size(); i++) {
std::copy(vec[i].begin(), vec[i].end(), newarr_ptr_copy);
newarr_ptr_copy += vec[i].size(); // don't lose track of newarr
}
std::cout<<"inside \n";
for (int i=0; i<vec.size(); i++) {
std::cout<<newarr[i]<<"\n";
}
return newarr;
}
int main(){
std::vector<double> x{1,2};
std::vector<double> y{3,4};
std::vector<std::vector<double>>vec;
vec.push_back(x);
vec.push_back(y);
double *arr=VecToArr(vec);
std::cout<<"outside \n";
for (int i=0; i<4; i++) {
std::cout<<arr[i]<<"\n";
}
delete [] arr; // make sure that you release the memory that you allocated
}
Look at this piece of code:
double* newarr=new double[vec.size()];
for (int i=0; i<vec.size(); i++) {
std::copy(vec[i].begin(), vec[i].end(), newarr);
newarr += vec[i].size();
}
A simple math fells violated here. You allocate your newarr to be the size of vec. So far so good. Now, for each element in vec you increment the pointer by vec[i].size - effectively leading to the used size of SUM(vec[i].size()). This is not right, you have undefined behavior in your program by accessing array outside of it's allocated bounds.
Please note, I also fixed a typo in your code - your original version of new double(vec.size()) allocated a single double, not an array of them.

Declaring and initializing a global 2D array

//gives the error expecting a declaration
int** my_array;
for (int i=0; i<200; i++)
{
my_array[i]= new int [200];
}
//initialize array with zeroes
for (int i = 0; i<200; i++)
{
for (int j = 0; j<200; j++)
{
my_array[i][j] =0;
}
}
In brief:
The 2D array is declared globally
It is initialized in the main. The main calls a function that saves 0's or 1's in specific cells of the array
The array is then printed by the main
Also advice whether the flow is correct?
If you want an array of an array of 200 bools, you could use std::array and std::bitset.
#include <bitset>
#include <array>
//...
std::array<200, std::bitset<200>> my_array;
Second, your code, even if you fix the syntax error is wrong. You would need to create my_array this way:
int** my_array;
//...
my_array = new int * [200];
for (int i = 0; i < 200; ++i )
my_array[i] = new int [200];
Then somewhere you have to delete this memory:
for (int i = 0; i < 200; ++i )
delete [] my_array[i];
delete [] my_array;
An alternate that creates a contiguous block and uses only two calls to new[]:
my_array = new int * [200];
int *pool = new int [200*200];
for (int i = 0; i < 200; ++i, pool += 200 )
my_array[i] = pool;
Then somewhere you have to delete this memory:
delete [] my_array[0];
delete [] my_array;
However I advise you use a container such as the std::array, std::bitset, std::vector, etc. instead of the int** approach.
Regarding your syntax error, it's probably due to something before the code you have shown.
The shown code,
int** my_array;
for (int i=0; i<200; i++)
{
my_array[i]= new int [200];
}
//initialize array with zeroes
for (int i = 0; i<200; i++)
{
for (int j = 0; j<200; j++)
{
my_array[i][j] =0;
}
}
compiles fine as the body of a function.
Regarding the logic, which is incorrect and which uses troublesome constructs,
do this:
auto my_array = vector<vector<bool>>( 200, vector<bool>( 200 ) );
where vector is std::vector from the <vector> header.
This avoids the raw pointers, the new-ing`, the loops, etc., all that you find problematic.
Alternatively you can declare it like this:
vector<vector<bool>> my_array( 200, vector<bool>( 200 ) );
Note that a global variable is usually troublesome, best avoided.

How can I create a dynamically sized array of linked lists?

I need to create an array of linked lists at runtime for a hash table assignment. The sample code that we are given only allows for creating arrays of static size, and I cannot figure out how to modify it to work with a variable, as everything I have tried has resulted in errors.
Sample Code:
typedef std::list<int> INT_LIST;
typedef INT_LIST* INT_LIST_POINTER;
int size = 13;
INT_LIST_POINTER myArray[size];
INT_LIST_POINTER tmpPtr;
// initialize the array to point to empty lists
for (int i=0; i<size; i++){
tmpPtr = new INT_LIST;
myArray[i] = tmpPtr;
}
My Current, nonworking Code:
typedef std::list<int> INT_LIST;
typedef INT_LIST* INT_LIST_POINTER;
INT_LIST_POINTER myArray = new INT_LIST[p];
INT_LIST_POINTER tmpPtr;
for (int i=0; i<n; i++){
INT_LIST* temp = new INT_LIST;
myArray[i] = temp;
}
The major problem seems to be with
myArray[i] = temp;
which says nothing matches those operands.
If this is C++, why not use std:
std::vector<std::list<MyClass> > x;
You allocate an array of size p:
INT_LIST_POINTER myArray = new INT_LIST[p];
and then proceed to initialize n elements:
for (int i=0; i<n; i++){
Unless p and n are the same thing, this doesn't look right.
P.S. Don't forget to delete[] myArray when you're done with it.

Dynamic 2D Array Initialization

I want to create and initialize a 2D array but the initialization is failed. I encounter "The program has unexpectedly finished." in Qt Creator.
What is wrong?
in .h file
private:
int pop;
int d;
float **uye;
in .cpp file
pop=50;
d=12;
uye = new float*[pop];
for(int i=0; i<d; i++) uye[i] = new float[d];
for(int n=0; n<pop; n++)
{
for(int m=0; m<d; m++)
{
uye[n][m] = (float) n*m;
}
}
The first loop for(int i=0; i<d; i++) should probably be for(int i=0; i<pop; i++). Otherwise, you are only reserving space for 12 elements, but later try to access 50.
Note that having raw pointer members is considered a very bad idea in modern C++, because you need to worry about copying semantics. Better use a flat std::vector<float> and do the 2D to 1D mapping manually, or use a std::vector<std::vector<float> > with convenient access syntax.
I would prefer the second version. Without seeing more context:
pop = 50;
d = 12;
uye = std::vector<std::vector<float> >(pop, std::vector<float>(d));
The nested for loops that follow work exactly the same, no changes required.
What is wrong?
You're not using std::vector (that's one of the things that's wrong, #FredO covered the other thing).
#include <vector>
int main(){
typedef std::vector<float> inner_vec;
typedef std::vector<inner_vec> outer_vec;
int pop = 50, d = 12;
// first parameter to vector is its size
// second is what every element should be initialized to
outer_vec uye(pop, inner_vec(d));
for(unsigned n = 0; n < uye.size(); ++n){
for(unsigned m = 0; m < uye[n].size(); ++m){
uye[n][m] = (float)n*m;
}
}
}

Using dynamic multi-dimensional arrays in c++

I am making a C++ program that checks if given aray is a latin square. I need to use a dynamic multi-dimensional array that stores given latin square. But I cant pass the array to a function that does the checking...
Currently I have such code for calling the function:
int squaretest(int **p, int n, int sum) {
//some code
};
And this code is for creating the array:
int main() {
//some code. n - length of one row, sum - sum of elements in one row.
int a;
int **lsquare;
lsquare = new int*[n];
for (int i=0;i<=n-1;i++) for (int j=0;j<=n-1;j++) {
cin >>a;
lsquare[i][j] = a;
}
blocktest(lsquare,n,sum);
//some code
};
The code compiles (i am using Geany IDE and G++ compiler) but when I run it in terminal, after the first imput, that has to be stored in block[0][0] I get Segmentation fault error. What's wrong with my code and what is the correct sollution?
To be able to do that.. You actually need to do this:
int **lsquare = new int*[n];
for (int i=0; i<n; ++i)
lquare[i] = new int[n];
for (int i=0; i<n; i++)
for (int j=0; j<n; j++)
cin >> lsquare[i][j];
blocktest(lsquare,n,sum);
The better system would be to do:
int *lsquare = new int[n*n];
for (int i=0; i<n; ++i)
for (int j=0; j<n; ++j)
cin >> lsquare[i + j*n];
blocktest(lsquare, n, sum);
You forgot to allocate memory for second dimension of the matrix.
int **lsquare;
lsquare = new int*[n];
for (int i=0; i<n; ++i){
lsquare[i] = new int[n];
....}
nobody writes
for (int i=0;i<=n-1;i++){...}
Do instead
for (int i=0; i<n; ++i){...}
You have an array of pointers in lsquare.
You might want to just do something like:
lsquare = new int[n * n];
That way you can then fill in this square, but the type is then:
int *lsquare
What you are actually creating an array of arrays. Not only do you need to allocate the array of arrays using new, but also you must allocate all n arrays. You'll want to have the outer loop of your nested for loop allocate each of the n sub-arrays.
lsquare = new int*[n];
for (int i=0;i<=n-1;i++)
{
lsquare[i] = new int[n];
for (int j = 0;j<=n-1;j++)
{
//...
You made yourself a pointer pointer that can be used as a matrix, allocated one row for it, then proceeded to act like you'd allocated an entire n*n matrix. You will indeed get a segfault if you run that.
You need to allocate enough space for n*n elements, not just n of them.
A less error-prone solution might be to use a std::vector of std::vectors.
You have to allocate space for the second dimension too, add this after you allocate lsquare:
for(int i = 0; i < n; ++i)
{
lsquare[i] = new int[n];
}