Initialize all elements in matrix with variable dimensions to zero - c++

I'm trying to initialize an int matrix in C++, with user-inputted dimensions, with every element set to zero. I know there are some elegant ways to do that with a one-dimensional array so I was wondering if there are any similar ways to do it with a two-dimensional array without using for loops and iterating through every element.
I found a source that gave several different ways, including std::fill (I've modified the code so that the dimensions are read with cin):
#include <iostream>
using namespace std;
int main() {
int x;
cin >> x;
int matrix[x][x];
fill(*matrix, *matrix + x * 3, 0);
for (int i = 0; i < x; i++) {
for (int j = 0; j < 3; j++) {
cout << matrix[i][j] << " ";
}
cout << endl;
}
}
But why does this work, and why would the pointer to the matrix in the arguments for fill be necessary if it's not necessary for a one-dimensional array? That source said it was because matrixes in C++ are treated like one-dimensional arrays, which would make sense, but that is why I don't understand why the pointer is needed.
I don't know if this is relevant, but in case it can help, I've described my previous attempts below.
At first I thought I could initialize all elements to zero like in a one-dimensional array. For the matrix, this worked fine when the side lengths were not read with cin (i.e. when I declared the matrix as int matrix[3][3] = {{}}; as answered here) but when I tried getting the side lengths from cin I started getting errors.
This was my code:
#include <iostream>
using namespace std;
int main() {
int x;
cin >> x;
int matrix[x][x] = {{}};
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
cout << matrix[i][j] << " ";
}
cout << endl;
}
}
And when I tried to compile it, it threw this error:
matrix_test.cpp:7:14: error: variable-sized object may not be initialized
int matrix[x][x] = {{}};
^
1 error generated.

Why you're getting the error
c-style arrays (such as int matrix[3][3]) must have size specified at the point you declare it. They can't vary in size in C++.
What you could do instead.
If you use std::vector, there's a really elegant way to do it:
#include <vector>
#include <iostream>
int main() {
using namespace std;
int x;
cin >> x;
auto matrix = vector<vector<int>>(x, vector<int>(x, 0));
// This is how we can print it
for(auto& row : matrix) {
for(auto& elem : row) {
cout << elem << ' ';
}
cout << '\n';
}
}
In C++17, you can shorten this even further:
auto matrix = vector(x, vector(x, 0));
What vector(number, thing) means is "Create a vector of number, where each element is thing".

The second dimension of two-dimension array must be a compile time constant, but in your code x is not.
Actually if you write a function with a two-dimension parameter, the second dimension must also be a compile time constant. That's because the array is stored linearly in the memory and the compiler must know the second dimension to calculate the offset correctly.

Related

How to debug why the compiler crashes on my C++ program?

Code 1: supposed to take a matrix (m by n) size and then find the min value in each row. Doesn't show any errors, runs but the black screen (devc++) for the compiler simply crashes without doing anything and has a ridiculously high return value (3221225725 to be exact).
I'm not sure how to fix or improve it, also it works when the size of the matrix is constant, like instead of cin to get size a simple number makes it work. I am not sure why; I'm new to programming.
#include <iostream>
#include <stdlib.h>
using namespace std;
int main()
{
int m,n;
int B[m][n];
int A[m+1][n+1] = {0};
cin>>m;
cin>>n;
for (int x = 0; x < m; ++x)
{
for (int y = 0; y < n; ++y)
{
cout<< "Enter in value for row " << x << ", column " << y << ".\n";
cin>> A[x][y];
}
}
cout << "Input:" <<endl;
for (int x = 0; x < m; ++x)
{
for (int y = 0; y < n; ++y)
{
cout<< A[x][y] << "\t";
}
cout << "\n";
}
for (int x = 0; x < m; ++x)
{
for (int y = 0; y < n; ++y)
{
A[x][4] = A[x][1];
if (A[x][4] > A[x][y])
A[x][4] = A[x][y];
}
}
cout <<"Output:"<<endl;
for (int x = 0; x < m+1; ++x)
{
for (int y = 0; y < n+1; ++y)
{
cout << A[x][y] << "\t";
}
cout<<"\n";
}
getchar ();
return 0;
}
And this is code 2:
#include <iostream>
#include <math.h>
using namespace std;
int main ()
{
int i,j,R,C,Too;
double a[i][j];
float f;
Too=0;
cin>>R;
cin>>C;
for (int i=0; i<R; i++)
for (int j=0; j<C; j++)
{
f=i+j/2;
a[i][j]=sin(f);
if (a[i][j]>0)
{
Too=Too+1;
}
cout << "a[" << i << "][" << j << "]: ";
cout << a[i][j]<< endl;
}
cout<<Too<<" Shirheg eyreg element bn"<<endl;
}
the elements in this matrix is generated by the formula f=i+j/2; a[i][j]=sin(f);
and simply outputs how many positive elements are there. for some odd reason the elements are always double like the output is something like:
0
0
0.841471
0.841471
and one other number then gets getting double and then a number and then double.
how to fix?
Strange return values and crashes when working in C++ are often a sign of uninitialized values. For example, consider the following:
int main() {
int m,n; // <-- declare 'm' and 'n', but we don't initialize them to have a value
int B[m][n]; // <-- use the values in 'm' and 'n' to allocate memory for 'B'
...
cin >> m; // <-- only now are you setting m to a value, but you already used it.
cin >> n; // <-- same thing with n.
...
}
The above code is wrong because it uses the variables identified by 'm' and 'n' before it sets them to have a particular value, so until you set their value (with cin) they just have whatever value happened to be sitting in memory at the time they were created.
Assigning a value to them is called "initialization" or initializing them the first time you do it. Before that they just hold that value from memory.
Ultimately, each line of code is using some variables and may be making assignments to other variables. So make sure each variable that is being used has already been initialized before you reach that line of code.
You will have to debug your own code in order to learn effectively, and the above example is not the only error or issue here, but a few basic tips to help you along the way:
Always look out for anything using uninitialized values like m and n
If it makes sense, initialize values as soon as they are created
i and j and k as variable names are usually declared only in a loop, because you usually only need them to exist inside the loop.
If you declare int i in a function, you should not declare int i in a loop within that function. The two i's now mean different things, which is confusing.
put spaces around your << and >> operators. It will make the code easier to read.
If you're having trouble, try printing out the value of a variable with cout and see if it makes sense. If not, there is a problem before that point in the program.
If you're having trouble, try working on one section of the code at a time until it behaves the way you expect.

C++ Passing Dynamic Array Determined by Parameter

This function has been asked a few times on here but I am interested in a particular case. Is it possible to have the size of the array passed defined by an additional argument?
As an example, let's say I want a function to print a 2D array. However, I the array may not have the same dimensions every time. It would be ideal if I could have additional arguments define the size of that array. I am aware that I could easily switch out the n for a number here as needed but if I have more complex functions with separate header files it seems silly to go and edit the header files every time a different size array comes along. The following results in error: use of parameter 'n' outside function body... which I understand but would like to find some workaround. I also tried with g++ -std=c++11 but still the same error.
#include <iostream>
using namespace std;
void printArray(int n, int A[][n], int m) {
for(int i=0; i < m; i++){
for(int j=0; j<n; j++) {
cout << A[i][j] << " ";
}
cout << endl;
}
}
int main() {
int A[][3] = {
{1,2,3},
{4,5,6},
{7,8,9},
{10,11,12}
};
printArray(3, A, 4);
return 0;
}
Supposedly, this can be done with C99 and also mentioned in this question but I cannot figure out how with C++.
This works:
template<size_t N, size_t M>
void printArray( int(&arr)[M][N] ) {
for(int i=0; i < M; i++){
for(int j=0; j < N; j++) {
std::cout << A[i][j] << " ";
}
std::cout << std::endl;
}
}
if you are willing to put the code in a header file. As a bonus, it deduces N and M for you.

c++ error: invalid types 'int[int]' for array subscript

Trying to learn C++ and working through a simple exercise on arrays.
Basically, I've created a multidimensional array and I want to create a function that prints out the values.
The commented for-loop within Main() works fine, but when I try to turn that for-loop into a function, it doesn't work and for the life of me, I cannot see why.
#include <iostream>
using namespace std;
void printArray(int theArray[], int numberOfRows, int numberOfColumns);
int main()
{
int sally[2][3] = {{2,3,4},{8,9,10}};
printArray(sally,2,3);
// for(int rows = 0; rows < 2; rows++){
// for(int columns = 0; columns < 3; columns++){
// cout << sally[rows][columns] << " ";
// }
// cout << endl;
// }
}
void printArray(int theArray[], int numberOfRows, int numberOfColumns){
for(int x = 0; x < numberOfRows; x++){
for(int y = 0; y < numberOfColumns; y++){
cout << theArray[x][y] << " ";
}
cout << endl;
}
}
C++ inherits its syntax from C, and tries hard to maintain backward compatibility where the syntax matches. So passing arrays works just like C: the length information is lost.
However, C++ does provide a way to automatically pass the length information, using a reference (no backward compatibility concerns, C has no references):
template<int numberOfRows, int numberOfColumns>
void printArray(int (&theArray)[numberOfRows][numberOfColumns])
{
for(int x = 0; x < numberOfRows; x++){
for(int y = 0; y < numberOfColumns; y++){
cout << theArray[x][y] << " ";
}
cout << endl;
}
}
Demonstration: http://ideone.com/MrYKz
Here's a variation that avoids the complicated array reference syntax: http://ideone.com/GVkxk
If the size is dynamic, you can't use either template version. You just need to know that C and C++ store array content in row-major order.
Code which works with variable size: http://ideone.com/kjHiR
Since theArray is multidimensional, you should specify the bounds of all its dimensions in the function prototype (except the first one):
void printArray(int theArray[][3], int numberOfRows, int numberOfColumns);
I'm aware of the date of this post, but just for completeness and perhaps for future reference, the following is another solution. Although C++ offers many standard-library facilities (see std::vector or std::array) that makes programmer life easier in cases like this compared to the built-in array intrinsic low-level concepts, if you need anyway to call your printArray like so:
printArray(sally, 2, 3);
you may redefine the function this way:
void printArray(int* theArray, int numberOfRows, int numberOfColumns){
for(int x = 0; x < numberOfRows; x++){
for(int y = 0; y < numberOfColumns; y++){
cout << theArray[x * numberOfColumns + y] << " ";
}
cout << endl;
}
}
In particular, note the first argument and the subscript operation:
the function takes a pointer, so you pass the name of the multidimensional array which also is the address to its first element.
within the subscript operation (theArray[x * numberOfColumns + y]) we access the sequential element thinking about the multidimensional array as an unique row array.
If you pass array as argument you must specify the size of dimensions except for the first dim. Compiler needs those to calculate the offset of each element in the array. Say you may let printArray like
void printArray(int theArray[][3], int numberOfRows, int numberOfColumns){
for(int x = 0; x < numberOfRows; x++){
for(int y = 0; y < numberOfColumns; y++){
cout << theArray[x][y] << " ";
}
cout << endl;
}
}

C++ passing Dynamically-sized 2D Array to function

I'm trying to figure out how to pass 2D array, which is constructed dynamically to a function.
I know that number of columns must be specified, but it my case it depends on user input.
Are there any workarounds?
Example:
// Some function
void function(matrix[i][j]) {
// do stuff
}
// Main function
int N;
cout << "Size: ";
cin >> N;
int matrix[N][N];
for (int i=0;i<N;i++) { //
for (int j=0;j<N;j++) {
cin >> matrix[N][N];
}
}
sort(matrix);
You get the idea :)
If you're on C++, the reasonable options are to:
use boost::multi_array (recommended), or
make your own 2D array class. Well, you don't have to, but encapsulating 2D array logic in a class is useful and makes the code clean.
Manual 2D array indexing would look like this:
void func(int* arrayData, int arrayWidth) {
// element (x,y) is under arrayData[x + y*arrayWidth]
}
But seriously, either wrap this with a class or enjoy that Boost already has that class ready for you. Indexing this manually is tiresome and makes the code more unclean and error-prone.
edit
http://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html says that C99 has one more solution for you:
void func(int len, int array[len][len]) {
// notice how the first parameter is used in the definition of second parameter
}
Should also work in C++ compilers, but I haven't ever used this approach.
In C++, the compiler can figure out the size, since it's part of the type. Won't work with dynamically sized matrices though.
template<size_t N, size_t M>
void function(int (&matrix)[N][M])
{
// do stuff
}
EDIT: In GCC only, which is required for your code defining the array, you can pass variable-length arrays directly:
void func(int N, int matrix[N][N])
{
//do stuff
}
See the gcc documentation
/*******************************************************\
* *
* I am not claiming to be an expert, but I think I know *
* a solution to this one. Try using a Vector Container *
* instead of an array. Here is an example below: *
* *
* Load the target file with a Multiplication Table *
* *
* *
\*******************************************************/
// reading a text file
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
std::string user_file;
int user_size = 2;
void array_maker(int user_size, std::string user_file);
int main () {
std::cout << "Enter the name of the file for your data: ";
std::cin >> user_file;
std::cout << std::endl;
std::cout << "Enter the size for your Multiplication Table: ";
std::cin >> user_size;
// Create the users Multiplication data
array_maker(user_size, user_file);
return (0);
}
void array_maker(int user_size, std::string user_file)
{
// Open file to write data & add it to end of file
std::ofstream target_file(user_file,std::ios::out | std::ios::app);
// Declare the vector to use as a runtime sized array
std::vector<std::vector<int>> main_array;
// Initialize the size of the vector array
main_array.resize(user_size+1); // Outer Dimension
for (int i=0; i <= user_size; ++i) // Inner Dimension
{
main_array[i].resize(user_size+1);
}
for (int i=0; i<=user_size; ++i)
{
for (int j=0; j<=user_size; ++j)
{
main_array[i][j] = i * j;
// output line to current record in file
target_file << i << "*"
<< j << "="
<< main_array[i][j] << " "
<< "EOR" // End of Record
<< std::endl;
} // Close Inner For
} // Close Outer For
// close file
target_file.close();
} // Close array_maker function
You can do
void function (int** __matrix, int32_t __row, int32_t __column)
__row - max rows
__column - max columns.
You will need those params to find out the limits of the array.
Just add another parametrs to your function - row_number and column_number. Arrays are not object in C++ so they don't store any additional information about themselfs.
If you pass in the array identifier (as a pointer to a pointer) you will need to use pointer arithmetic:
void function(int** matrix, int num_rows, int num_cols) {
Assert(matrix!=NULL && *matrix!=NULL && num_rows>0 && num_cols>0);
for(int i=0; i<num_rows; i++) {
for(int j=0; j<num_cols; j++) {
// cannot index using [] like matrix[i][j]
// use pointer arithmetic instead like:
// *(matrix + i*num_cols + j)
}
}
}
to pass multi dimensional arays into method the compiler needs to know the depth of each field, so one solution is to use templates and call method in a normal way and the compiler will guess the size of each field.
template <size_t m>
void method(int M[][m])
{
for(int i=0; i<m; ++i)
for(int j=0; j<m; ++j)
{
// do funny stuff with M[i][j]
}
}
int main()
{
int M[5][5] = { {1,0,1,1,0}, {0,1,1,1,0}, {1,1,1,1,1}, {1,0,1,1,1}, {1,1,1,1,1} };
method(M);
// also you can call with method<5>(M)
// if you have different sizes for each dimension try passing them in args
return 0;
}
int r, c
int *matrix = new int[r,c];
for (int i = 0; i < r; i++)
{
/*cout << "Enter data" << endl;*/
for (int j = 0; j < c; j++)
{
cin >> matrix[i,j];
}
}
void function(int &matrix[][] )

C++ Program Apparently Printing Memory Address instead of Array

#include <iostream>
using namespace std;
int main(){
int findMax(int *);
const int MAX = 100;
int values[MAX];
char ivals[256];
// Get the space-separated values from user input.
cin.getline(ivals, 256, '0');
char *helper;
// Clean input array and transfer it to values.
for(int i = 0; i < (MAX) && ivals[i] != 0; i++){
helper = ivals[i * 2];
values[i] = atoi(helper);
}
int mval = findMax(values);
cout << values << endl << mval;
return 0;
}
//Function to find the maximum value in the array
int findMax(int arr[]){
int localmax = 0;
for(int i = 0; i < (sizeof(arr)/sizeof(int)); i++){
if(arr[i] > localmax){
localmax = arr[i];
}
}
return localmax;
}
The purpose of this program is for the user to input a space-separated series of values ended by a 0. That array is then to be analyzed to find the max. I figured out how to convert what is originally a char[] into an int[] so that I can use the findMax() function on it without error but the sorting loop seems to have a problem of its own and when "cout << values << endl << mval;" is called, it returns only a memory address instead of what should be a non-spaced sequence of ints. Can anybody explain what I am doing wrong? It seems that I may have made some mistake using the pointers but I cannot figure out what.
Printing values won't print the contents of the array as you expect, it will print the memory location of the first element of the array.
Try something like this instead:
#include <iterator>
#include <algorithm>
// ...
copy(&values[0], &values[MAX], ostream_iterator(cout, " "));
Sorry I can't post actual working code, but your original post is a mess with many syntax and syntactic errors.
EDIT: In the interest of being more complete and more approachable & understandable to beginners, I've written a small program that illustrates 4 ways to accomplish this.
Method 1 uses copy with an ostream_iterator as I've done above.
Method 2 below is probably the most basic & easiest to understand.
Method 3 is a C++0x method. I know the question is tagged C++, but I thought it might be educational to add this.
Method 4 is a C++ approach using a vector and for_each. I've implemented a functor that does the dumping.
Share & Enjoy
#include <iostream>
#include <iterator>
#include <algorithm>
#include <functional>
#include <vector>
using namespace std;
struct dump_val : public unary_function<int,void>
{
void operator()(int val)
{
cout << val << " ";
}
};
int main(){
int vals[5] = {1,2,3,4,5};
// version 1, using std::copy and ostream_iterator
copy(&vals[0], &vals[5], ostream_iterator<int>(cout, " "));
cout << endl;
// version 2, using a simple hand-written loop
for( size_t i = 0; i < 5; ++i )
cout << vals[i] << " ";
cout << endl;
// version 3, using C++0x lambdas
for_each(&vals[0], &vals[5], [](int val)
{
cout << val << " ";
}
);
cout << endl;
// version 4, with elements in a vector and calling a functor from for_each
vector<int> vals_vec;
vals_vec.push_back(1);
vals_vec.push_back(2);
vals_vec.push_back(3);
vals_vec.push_back(4);
vals_vec.push_back(5);
for_each( vals_vec.begin(), vals_vec.end(), dump_val() );
cout << endl;
}
When you pass around an array of X it's really a pointer to an array of X that you're passing around. So when you pass values to cout it only has the pointer to print out.
You really should look into using some of the standard algorithms to make your life simpler.
For example to print all the elements in an array you can just write
std::copy(values, values+MAX, std::ostream_iterator<int>(std::cout, "\n"));
To find the max element you could just write
int mval = *std::max_element(values, values+MAX);
So your code becomes
#include <iostream>
using namespace std;
int main(){
const int MAX = 100;
int values[MAX];
char ivals[256];
// Get the space-separated values from user input.
cin.getline(ivals, 256, '0');
char *helper;
// Clean input array and transfer it to values.
for(int i = 0; i < (MAX) && ivals[i] != 0; i++){
helper = ivals[i * 2];
values[i] = atoi(helper);
}
copy(values, values+MAX, ostream_iterator<int>(cout, "\n"));
cout << *std::max_element(values, values+MAX);
return 0;
}
Doing this removes the need for your findMax method altogether.
I'd also re-write your code so that you use a vector instead of an array. This makes your code even shorter. And you can use stringstream to convert strings to numbers.
Something like this should work and is a lot less code than the original.
int main(){
vector<int> values;
char ivals[256];
// Get the space-separated values from user input.
cin.getline(ivals, 256, '0');
int temp = 0;
stringstream ss(ivals);
//read the next int out of the stream and put it in temp
while(ss >> temp) {
//add temp to the vector of ints
values.push_back(temp);
}
copy(values.begin(), values.end(), ostream_iterator<int>(cout, "\n"));
cout << *std::max_element(values.begin(), values.end());
return 0;
}
Array of int is promoted to a pointer to int when passed to a function. There is no operator << taking ordinary array. If you want to use operator << this way, you need to use std::vector instead.
Note: it is possible technically to distinguish array when passed to a function using template, but this is not implemented for standard operator <<.
for(int i = 0; i < (sizeof(arr)/sizeof(int)); i++){
sizeof(arr) here is the size of the pointer to the array. C++ will not pass the actual array, that would be grossly inefficient. You'd typically only get one pass through the loop. Declare your function like this:
int findMax(int* arr, size_t elements) {
//...
}
But, really, use a vector.
Oh, hang on, the question. Loop through the array and print each individual element.