Reading 2D array from a file and passing it to another function - c++

I wrote down this code in C++ to read a 2D array from a file. Now I'd like to organize better my code with functions. The issue I'm having is that I can't figure out how to pass the 2D array I loaded to memory to another function in the same program.
This is the code I need to organize into functions:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
#define M 4
#define N 4
int main(){
int i, j;
float A[M][N];
string line;
ifstream matrix("matrix.txt");
if (matrix.is_open())
{
do
{
for(i=0; i<M; i++)
{
for(j=0; j<N; j++)
matrix >> A[i][j];
}
}
while (getline(matrix,line));
matrix.close();
}
else cout << "Unable to open file";
float sumline[M]={0};
for(i=0;i<M;i++)
{
for(j=0;j<N;j++)
sumline[i]+=A[i][j];
}
float sumcolumn[N]={0};
for(j=0;j<N;j++)
{
for(i=0;i<M;i++)
sumcolumn[j]+=A[i][j];
}
for (i=0; i<M; i++){
for (j=0; j<N; j++){
if(sumline[i]<sumcolumn[j]){
cout << "Error, total sum of column "<<j<<" is greater than the sum of the line"<<i<<endl;
return 0;
}
}
}
int mincol=sumcolumn[0];
for (i=0; i<N; i++){
if(mincol>sumcolumn[i])
mincol==sumcolumn[i];
}
float avgline = 0.0;
for (i=0; i<M; i++){
avgline=avgline+sumline[i];
}
avgline = avgline/M;
if (avgline * 3 > mincol) {
cout << "Conditions verified"<<endl;
}
else{
cout << "Error, triple of the avg of line is less than the lowest sum of column"<<endl;
return 0;
}
return 0;
}
The code basically does some math on the 2D array. I'd also like to keep as simple as possible so even if using namespace std; it's not really good practice or the way I'm reading the array from the file is really basic I need it to be like that. Thanks a lot.

Instead of using c-array
float A[M][N];
You may instead use
using MyArrayType = std::array<std::array<float>, M>, N>;
MyArrayType A;
Now you can pass by reference (MyArrayType& or const MyArrayType& )
That being said: a c array can be passed as with the more difficult syntax: (float (&a)[M][N]); - it is strongly recommended to use std::array instead where possible.

Related

input float in C++?

I code a program to calculate all possibilities, but with integers and now I have to do it for floats, how can I change the program to input floats instead of integers?
This is just a part but if I can do it for the fist switch I can do it for all:
#include <fstream>
using namespace std;
ifstream in("multimi.in");
ofstream out("produs.out");
void input(int *v)
{
for(int i=1; i<=2; i++)
in>>v[i];
}
int main()
{
float a[3],b[3],c[3],d[3],e[3],s[3];
int num_tot;
in>>num_tot;
switch(num_tot)
{
case 2:
input(a);
input(b);
for(int i=1; i<=2; i++)
for(int j=1; j<=2; j++)
out<<a[i]<<","<<b[j]<<endl;
break;
This is the code with int which works:
#include <fstream>
using namespace std;
ifstream in("multimi.in");
ofstream out("produs.out");
void input(int *v)
{
for(int i=1; i<=2; i++)
in>>v[i];
}
int main()
{
int a[3],b[3],c[3],d[3],e[3],s[3];
int num_tot;
in>>num_tot;
switch(num_tot)
{
case 2:
input(a);
input(b);
for(int i=1; i<=2; i++)
for(int j=1; j<=2; j++)
out<<a[i]<<","<<b[j]<<endl;
break;
If you want to parse a float value in your input function you'll have to have a compatible parameter, as you are passing an array of floats as an argument (which becomes a pointer to the first element of the array), you'll need a pointer to float instead of pointer to int.
void input(float *v){ ... }
I should also note that you are bypassing the first element in the array, the indexes start at [0].
Another thing I would do is to avoid using global variables, if you want to use your in stream in the function you can pass it by reference as an argument of the function, provided that you know its lifetime will outlive the reference:
All things considered you would have something like this:
void input(float *v, ifstream& in)
{
for (int i = 0; i < 2; i++)
in >> v[i];
}
int main()
{
ifstream in("test.txt");
ofstream out("produs.out");
float a[2], b[2];
int num_tot;
if (in.is_open() && out.is_open()) //it's important to check for successful file opening
{
in >> num_tot;
switch (num_tot)
{
case 2:
input(a, in);
input(b, in);
for (int i = 0; i < 2; i++)
{
out << a[i] << ", " << b[i] << endl;
}
break;
}
}
}
If you want something that works for both int and float you can make a function that can take both types using templates, I'll admit that this may be too much for now but it's somenthing that you may consider when you are more comfortable with the language:
template<typename T> void input(T& v, ifstream& in)
{
for (int i = 0; i < 2; i++)
in >> v[i];
}
Here T can take both int or float, with the added advantage that it can also be passed by reference. Of course you can still use pointers if you wish to do so, but passing by reference is preferable as it's safer.
Footnote
Consider not using using namespace std; you can follow this link to know the reasons for it, when it's safe to use and alternatives.

Some test cases aren't passing

#include <iostream>
#include <vector>
int i=0; //points at the current stack that we are working with
int box=0; //no. of boxes held by the crane
int64_t H; //max. height of the stacks given in the que.
int main()
{
int n, value; //storing no. of stacks and creating an additional variable value to store operations
std::cin>> n >> H;
int64_t arr[n]; //storing the no. of boxes each stack has in an array
std::vector<int> arr2; //storing the operations we have to perform in a vector
for(int j=0; j<n; j++){std::cin>> arr[j];} //getting arr
while(std::cin>>value) //getting arr2
{
arr2.push_back(value);
}
for(int xy=0; xy<n; xy++){if(arr[xy]>H){return 0;}} //ensuring that all stacks have no.of boxes less than max. height
if(arr2.size()<1 || arr2.size()>10e5 || n<1 || n>10e5 || H<1 || H>10e8){return 0;} //constraints given in the que.
int k=0; //creating a variable to keep count of how many programs we have already executed
while(k<arr2.size()){
if(arr2[k] == 1){MoveLeft();}
else if(arr2[k]==2){MoveRight(n);}
else if(arr2[k]==3){PickBox(arr, i);}
else if(arr2[k]==4){Dropbox(arr, i);}
else if(arr2[k]==0){k=arr2.size();}
k++;
}
for(int j=0; j<n; j++){std::cout<< arr[j] << " ";} //printing the arr after executing the code
return 0;
}
This is a question from a past year ZCO. And the above code is what I wrote to solve the prob.
The four functions Moveleft, MoveRight, Pickbox, Dropbox have been defined in the same file but aren't shown here because I think there's no issue with them.
When I submit the code, all test cases passed except 2. I don't know what is the problem with my code. Pls help me.
I have tried my best to make the code readable. Sorry if the code looks messy.
With the method you're trying to define an array with a user-input length is unfortunately invalid in C++.
But fortunately, there are basically two methods use to allocate arrays dynamically.
Method 1: Using Vectors
Vector is an important part of C++. It has a lot of features (e.g. its size don't need to be defined static unlike a normal array does, can redefine array size, etc.) An example's given:
#include <iostream>
#include <vector>
int main(void) {
std::vector<int> vArray; // vector<> declaration
int size = 0;
int getInput = 0;
std::cout << "Enter an array size: ";
std::cin >> size;
for (int i = 0; i < size; i++) {
std::cout << "Enter a value: ";
std::cin >> getInput;
vArray.push_back(getInput); // inserts one+ container and data in it
}
for (int i = 0; i < vArray.size(); i++) {
// retrieving contained data...
std::cout << vArray[i] << std::endl;
}
return 0;
}
Method 2: Using 'new' Keyword with Pointed Variable
The simple use of new will help you to achieve your requirement. It's less recommended since already there's concept of vectors which actually works efficiently than arrays. Let's take a look into a simple program:
#include <iostream>
int main(void) {
int *pArray;
int size;
std::cout << "Enter an array size: ";
std::cin >> size;
pArray = new int[size]; // initializing array with dynamic size
for (int i = 0; i < size; i++) {
std::cout << "Enter value: ";
std::cin >> pArray[i];
}
for (int i = 0; i < size; i++) {
std::cout << pArray[i] << std::endl;
}
delete[] pArray;
return 0;
}
Both are nice options to work with, but it's recommended by most using vector<>.

Error when setting and getting values from my two dimensional array

When I put a number in flag[1][2], I will automatically put that same number in flag[2][0].
Why?
#include <iostream>
using namespace std;
void inicializarFlag(void);
void imrpimeflag(void);
int flag[2][2];
int main(){
int i, j, escolha;
inicializarFlag();
cout<<"digite as posicoes e o valor: "<<endl;
cin>>i;
cin>>j;
cin>>escolha;
flag[i][j] = escolha;
imrpimeflag();
return 0;
}
void inicializarFlag(void){
for (int i=0; i<=2; i++){
for(int j=0; j<=2; j++){
flag[i][j] = 0;
}
}
}
void imrpimeflag(void){
for (int i=0; i<=2; i++){
for(int j=0; j<=2; j++){
cout<<"["<<i<<"]["<<j<<"]: "<<flag[i][j]<<endl;
}
}
}
When you initialize the array int flag[2][2], you are initializing a 2x2 array, not a 3x3 array. Since arrays are zero indexed, flag[2][0] places an int in the zeroth column of the third row of the 2x2 flags array, which is out of bounds. The behavior of placing an element out of the bounds of an array is undefined, and can lead to problems like you describe.
Declare int flag[3][3] and the code should work.

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.

Weird Array Stuff (Array indexes getting values without me setting it)

I am trying to write a sudoku solver.
I got the input almost done, but something strange started happening. On the index [i][9] of int sudoku[i][9], there are numbers present that I have never put there.
For example, when I run the code below with the input that is commented below using namespace std;, the output is:
410270805
085146097
070580040
927451386
538697412
164328759
852704900
090802574
740965028
Of course, I only need 0 through 8, but I was wondering what is causing integers to appear at the 9th index.
This is the code:
#include <iostream>
#include <math.h>
#include <cstdlib>
using namespace std;
/*
410270805
085146097
070580040
927451386
538697412
164328759
852704900
090802574
740965028
*/
int main()
{
int sudoku[9][9];
int solving[9][9][9];
int input;
for (int i=0; i<=8; i++) {
cin >> input;
int j;
int k;
for (j=8, k=1; j>=0; j--, k++) {
int asdf = input/pow(10,k-1);
sudoku[i][j] = asdf % 10;
}
}
cout << endl;
for (int i=0; i<=8; i++) {
for (int j=0; j<=9; j++) {
cout << sudoku[i][j];
}
cout << endl;
}
return 0;
}
Accessing elements outside of the defined region of an array is Undefined Behavior (UB).
That means it could:
Allow you to access uninitialized space (what yours is doing hence the random numbers)
Segfault
Any number of other random things.
Basically don't do it.
In fact stop yourself from being able to do it. Replace those arrays with std::vectors and use the .at() call.
for example:
std::vector<std::vector<int>> sudoku(9, std::vector<int>(9, 0));
for (int i=0; i<=8; i++) {
for (int j=0; j<=9; j++) {
cout << sudoku.at(i).at(j);
}
cout << endl;
}
Then you will get a thrown runtime exception that explains your problem instead of random integers or segfaults.
I think I found your problem, at your very last for loop you used j <= 9 instead of j <= 8. You then tried to write (j) leaving the possibility of it writing 9 wide open. Try replacing that 9 with 8.