Can a function return a 2d Array? - c++

#include <stdio.h>
#include <stdlib.h>
double matrixMultiply(double a[100][100],double b[100][100], int rowA,int colB,int colArowB){
double c[100][100];
int i,j,k;
for(i=0;i<rowA;i++)
for(j=0;j<colB;j++){
for(k=0;k<colArowB;k++)
c[i][j]=c[i][j]+a[i][k]+b[k][j];}
return c;
}
int main()
{
double a[100][100],b[100][100];
int n,m,o,p,i,j;
printf("%s \n", "Nr. linii A:");
scanf("%d",&n);
printf("%s \n", "Nr. coloane A:");
scanf("%d",&m);
printf("%s \n", "Nr. linii B:");
scanf("%d",&o);
printf("%s \n", "Nr. coloane B:");
scanf("%d",&p);
printf("%s \n", "A=");
for(i=0;i<n;i++)
for(j=0;j<m;j++)
scanf("%d", &a[i][j]);
printf("%s \n", "B=");
for(i=0;i<o;i++)
for(j=0;j<p;j++)
scanf("%d", &b[i][j]);
if(m==o){
printf("Matricile se pot inmulti");
cout<<matrixMultiply(a,b,n,m,p);
return 0;}
else printf("Matricile nu se pot inmulti");
return 0;
}
I should multiply 2 matrices A & B, but I don't know how to return the matrix C, can somebody help?
There is an error returning the matrix C,also do I need a for to print the matrix C?

I should multiply 2 matrices A & B, but I don't know how to return the matrix C, can somebody help?
return c;
will not work since the array decays to a pointer. Not only that, the pointer becomes invalid as soon as the function returns since c is a function local variable.
If the size of the matrix is known at compile time, you may use std::array. If the size of the matrix is known at run time only, you should use std::vector of std::vector.
std::array<std::array<int, 100>, 100> matrixMultiply(...) {}
or
std::vector<std::vector<int>> matrixMultiply(...) {}

As others have stated you could use the std::vector<std::vector<int>> but if you still want to use a 2D, array you need to dynamically allocate the 2D array in the function using a malloc and return a double* matrixMultiply(double a[100][100],double b[100][100], int rowA,int colB,int colArowB) or you could also allocate in the main function and just pass the address reference cout<<matrixMultiply(&a,&b,n,m,p);

vector maybe a better choice for this case in C++.
the function maybe looks like the following, and the entire program for this question is here
using namespace std;
typedef vector<double> MatrixRow;
typedef vector<MatrixRow> Matrix;
Matrix matrix_multiply(const Matrix &left, const Matrix &right)
{
// Validate conditions of multiplication of matrices
if (left.empty())
{
cerr << "Left matrix is empty." << endl;
exit(-1);
}
if (right.empty())
{
cerr << "Right matrix is empty." << endl;
exit(-1);
}
const int leftRowCount = left.size();
const int leftColumnCount = left.front().size();
const int rightRowCount = right.size();
const int rightColumnCount = right.front().size();
if (leftColumnCount != rightRowCount)
{
cerr << "The number of columns of the left matrix is not the same as the number of columns of the right matrix." << endl;
exit(-1);
}
cout << "Calculate steps" << endl
<< "=====" << endl;
// Calculation
Matrix matrix(leftRowCount);
for (int i = 0; i < leftRowCount; i++)
{
matrix.at(i).resize(rightColumnCount);
for (int j = 0; j < rightColumnCount; j++)
{
matrix.at(i).at(j) = 0;
cout << "M(" << i << "," << j << ") = ";
for (int k = 0; k < leftColumnCount; k++)
{
cout << "L(" << i << "," << k << ") + R(" << k << "," << j << ")";
if (k < leftColumnCount - 1)
{
cout << " + ";
}
matrix.at(i).at(j) += left.at(i).at(k) * right.at(k).at(j);
}
cout << endl;
}
}
cout << endl;
return matrix;
}
More about identifier naming:
In declarations
An identifier can be used to name objects, references,
functions, enumerators, types, class members, namespaces, templates,
template specializations, parameter packs, goto labels, and other
entities, with the following exceptions:
the identifiers that are keywords cannot be used for other purposes;
the identifiers with a double underscore anywhere are reserved; the
identifiers that begin with an underscore followed by an uppercase
letter are reserved;
the identifiers that begin with an underscore are
reserved in the global namespace.
more about identifier naming in C++, visit here for details.

Related

Can't read char array

The basic problem is that we (in pairs) have been tasked with creating a program to - amongst other things - read in a txt file and display it as a sudoku board as part of our introduction to coding at Uni.
We have completed most of the code and have got it working sufficiently well. However, we are struggling with what I would consider to be a basic aspect of this. The code reads in the file and saves it to the classes private char 9*9 matrix. We have run a debugging print-out to check that the values are being saved to the matrix and this is indeed the case. The issue is with the getMatrixVal(int x, int y) function which we think is returning a pointer rather than the character. We have tried returning a pointer from the function and have tried saving to a pointer and then to a char variable. Unfortunately, we am not excellent on pointer's.
With the recent suspensions to University timetables, we are temporarily unable to get the advice and support we require and, hence, we are applying here for advice.
Also, we are using the qt programming software on a raspberry pi - could this have anything to do with our problems?
#include "grid.h"
#include <QDebug>
#include <QChar>
#include <QFile>
grid::grid(char matrix_value, const int x, const int y) {
matrix[x][y] = matrix_value;
//char c = matrix[x][y];
//qDebug() << QChar(c);
}
void grid::load_file() {
QFile file("/home/pi/Documents/ELEC1204/P6/SUDOKU.txt");
char character, c;
int i, j;
if(!file.open(QFile::ReadOnly)) {
qDebug() << "Error in opening file";
return;
} //Print error if message if unable to open file
for(i = 0; i < 9; i++) {
for(j = 0; j < 9; j++) {
SKIP: //Related to 'goto'
file.read(&character, sizeof(char)); //Read ini individual characters
if(character == '\xd' || character == '\xa')
goto SKIP;
//Skip character related to new lines
//Goes to 'SKIP' point in program
else if(character == 'X')
grid('_', i, j);
//Save 'X's as '_'
else
grid(character, i, j);
//Save numbers as they are
c = getMatrixVal(i, j);
qDebug() << "i = " << i << "| j = " << j << "| Character is: " << QChar(character) << "| Matrix character is: " << QChar(c);
//Print-out for debugging
}
}
file.close();
//Close file
}
// Possibly useful source:
// https://doc.qt.io/qt-5/qfile.html
// https://forum.qt.io/topic/60240/reading-file-byte-by-byte/5
char grid::getMatrixVal(const int x, const int y) {
char c = matrix[x][y];
//qDebug() << "Matrix[" << x << "][" << y << "] is: " << QChar(c);
return c;
}
void grid::printMatrix() {
for(int i = 0; i < 9; i++) {
for(int j = 0; j < 9; j++) {
qDebug() << matrix[i][j];
}
}
}
//Prints out matrix
//Debugging function
There is nothing wrong with getMatrixVal: it returns a character from the right place in matrix.
Your call grid(character, i, j) constructs a new grid instance that is unrelated to the current one.
Instead, just assign directly to matrix: (or use a setter function)
matrix[i][j] = character;

Reading into an Array Multiple Times

I'm having a little trouble with my code. It's pretty much supposed to open two files, and compare the first twenty line of the file "StudentAnswers.txt" [inputted as a char into a char array] against a char value in (each line of another file) "CorrectAnswers.txt" in another array at the same position (index). It's like a linear search, but the same position in the arrays. Then a report should be displayed, detailing which question the student missed, the given answer, the correct answer, and if the student passed (got >= 70%) or not, like the following:
Report for Student X:
2 (A/D), 3 (C/D), 5(D/A)
This student passed the exam!
Then it should clear the SAArray, and feed the next twenty lines from StudentAnswers.txt, and start the process all over again. I guess the program has to determine the number of students from (lines of 'StudentAnswers.txt' file / 20).
I'm having trouble displaying the report, and having the array clear itself after the program. I'm guessing this can be done with a while loop and an accumulator for the number of students (to be determined by above equation).
Also, Visual Studio seems to go to "Missed __ questions for a total of ___ %", and then keep looping -858993460.
Any help would be appreciated.
#include <iostream>
#include <fstream>
#include <string>
#include <array>
#include <algorithm>
using namespace std;
void GradeReturn(char[], char[], int, int, int);
string PassFail(float);
int main()
{
ifstream SA("StudentAnswers.txt");
ifstream CA("CorrectAnswers.txt");char CAArray[20];
char SAArray[20];
// char SA2Array[20];
bool isCorrect;
int correct;
int incorrect;
int counter;
correct = 0;incorrect = 0;
counter = 0;
cout << endl;
if (!SA.fail())
{
cout << "'StudentAnswers.txt' file opened successfully." << endl;
cout << "'CorrectAnswers.txt' file opened successfully." << endl << endl;
int a = 0;
int b = 0;
while (a < 20)
{
CA >> CAArray[a];
a++;
} // while loop to feed char into the array
while (b < 20)
{
SA >> SAArray[b];
b++;
}
} // while loop to feed char into array
CA.close(); // closing "CorrectAnswers.txt"
SA.close(); // closing "StudentAnswers.txt"
GradeReturn(&CAArray[counter], &SAArray[counter], correct, incorrect, counter);
return 0;
}
void GradeReturn(char CAArray[], char SAArray[], int correct, int incorrect, int counter)
{
float percent;
float hundred;
int student;
int catcher[20];
int writeCatcher; int starter;
int catcher_size;
student = 0;
writeCatcher = 0;
catcher_size = ((sizeof catcher) / 4);
while (counter < 20)
{
if ((CAArray[counter]) == (SAArray[counter]))
{
correct++;
cout << "Good job!" << endl;
} // correct handling
else
{
incorrect++;
cout << "You got question " << counter << " wrong." << endl;
counter >> catcher[writeCatcher];
writeCatcher++;
} // incorrect handling
counter++;
} // while loop to determine if a student got a question right or wrong
static_cast <float> (incorrect); // float conversion
cout << endl; // for cleanliness
percent = ((static_cast <float> (correct)) / 20); // percentage
hundred = percent * 100;
PassFail(percent);
if (PassFail(percent) == "pass")
{
student++;
cout << "Report for Student " << student << ":" << endl;
cout << "-----------------------------" << endl;
cout << "Missed " << incorrect << " questions out of 20 for ";
cout << hundred << " % correct." << endl << endl;
starter = 0;
while (starter < (sizeof catcher)
{
if(1=1)
{
catcher_size
}
else
{
cout << "";
starter++;
}
}
}
else if (PassFail(percent) == "fail")
{
student++;
cout << "Missed " << incorrect << " questions out of 20 for ";
cout << hundred << " % correct." << endl << endl;
while (starter < catcher_size)
{
if ((catcher[starter]) == -858993460)
{
starter++;
}
else
{
cout << "";
starter++;
}
}
}
return;
}
string PassFail(float percent)
{
if (percent >= 0.70) // if <pass>
{
return "pass";
}
else // if <fail>
{
return "fail";
}
cout << endl;
}
To get a loop you should keep streams open instead of closing them after reading 20 lines.
As pseudo code that would be:
a = 0;
while(streams_not_empty)
{
CA >> CAArray[a];
SA >> SAArray[a];
++a;
if (a == 20)
{
GradeReturn(&CAArray[counter], &SAArray[counter], correct, incorrect, counter);
a = 0; // Reset a
}
}
CA.close(); // closing "CorrectAnswers.txt"
SA.close(); // closing "StudentAnswers.txt"
You would also need to pass correct, incorrect, counter by reference so that the GradeReturn can change their value and their by do the accumulation.
Like:
void GradeReturn(char CAArray[], char SAArray[], int& correct, int& incorrect, int& counter)
Further you shouldn't rely on being able to read exactly Nx20 lines from the files every time. A file could have, e.g. 108 (5x20 + 8) lines, so you code should be able to handle the with only 8 lines. In other words, don't hard code 20 in your function like while (counter < 20). Instead pass the number of lines to be handled and do while (counter < number_to_handle).
Something like this as pseudo code:
a = 0;
while(streams_not_empty)
{
CA >> CAArray[a];
SA >> SAArray[a];
++a;
if (a == 20)
{
GradeReturn(&CAArray[counter], &SAArray[counter], correct, incorrect, counter, a);
// ^
a = 0; // Reset a
}
}
if (a != 0)
{
// Process the rest
GradeReturn(&CAArray[counter], &SAArray[counter], correct, incorrect, counter, a);
}
CA.close(); // closing "CorrectAnswers.txt"
SA.close(); // closing "StudentAnswers.txt"
One problem you have is you're trying to compare C-style strings with the == operator. This will compare them essentially as if they were pointers to char, i.e. compare whether they point at the same location in memory, not compare the contents of the string. I urge you to look up array-decay and c-string variables to understand more.
Specifically, if (PassFail(percent) == "pass") isn't going to do what you want it to. strcomp doc, strncmp doc using std::string variables instead of c-style strings would all work, but it would be better simply to compare percent to a value, i.e. if(percent >= 0.70 directly instead of calling PassFail and comparing a string.
There are many other issues here also, you at one point call PassFail but do nothing with the return value. The only side affect of PassFail is cout << endl, if that's what you intend, it's a poor decision and hard to read way to put a newline on the console.
Try asking your compiler for more warnings, that's often helpful in finding these types of issues. -Wall -Wextra work for gcc, you may have to read your compiler manual...

C++ Vector subscript out of range Line 1201

I am working on a program that takes in grades from the user and returns the max, min, avg, median, and standard deviation. I keep encountering this error whenever I try to run my code:
File: c:\program files (x86)\microsoft visual studio 12.0\vc\include\vector
Line: 1201
Expression: Vector subscript out of range
Could someone tell me what I'm doing wrong? No matter what I do, I can't seem to fix it. Completely new to coding in C++, so if you could explain in-depth that would be extremely helpful.
This is the block of code it is referring to in the vector file:
#if _ITERATOR_DEBUG_LEVEL == 2
if (size() <= _Pos)
{ // report error
_DEBUG_ERROR("vector subscript out of range");
_SCL_SECURE_OUT_OF_RANGE;
}
Specifically pointing to this line:
_DEBUG_ERROR("vector subscript out of range");
My code:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
void enterGrades()
{
int count = 0;//initialize count
int grade;//initialize grade variable
int maxGrade = 0;
vector<int> gradeList;//initialize vector
vector<int>::iterator gradeListIt;//initialize iterator
do {
cout << "Enter grades [0 to exit]: ";//enter grades
cin >> grade;//user input
count += 1;//for each grade, increase count
gradeList.push_back(grade);//append grades to vector
} while (grade != 0);
};
int maxNum(vector<int> gradeList)
{
int largest = gradeList[0];//initialize largest number
int length = gradeList.size();
gradeList.resize(length);
for (int value = 0; value < length; value++)//traverse vector
{
if (gradeList[value] > largest)//if current value > largest
largest = gradeList[value];//set largest to that value
}
return largest;//return largest
};
int minNum(vector<int> gradeList)
{
int smallest = gradeList[0];
int length = gradeList.size();
gradeList.resize(length);
for (int value = 0; value < length; value++)
{
if (gradeList[value] < smallest)
smallest = gradeList[value];
}
return smallest;
};
int avgNum(vector<int> gradeList)
{
int total = 0;
int length = gradeList.size();
gradeList.resize(length);
for (int value = 0; value < length; value++)
{
total += value;
}
return total / length;
};
//int stdDev (vector<int>& gradeList)
//{
// int variance = 0;
// int avg = avgNum(vector<int>& gradeList);
// int length = gradeList.size();
// for(int value = 1; value < length; value++)
// {
// variance = variance + pow(value - avg, 2);
// }
// variance = pow(variance / length, 0.5);
// return variance;
//
//};
int main()
{
vector<int> gradeList;//initialize vector
vector<int>::iterator gradeListIt;//initialize iterator
enterGrades();//
cout << "Maximum grade is: " << maxNum(gradeList) << endl;
cout << "Minimum grade is: " << minNum(gradeList) << endl;
cout << "Average grade is: " << avgNum(gradeList) << endl;
}
Also, in my main function; can I call other functions like I did in my output statements?
Giving things the same name doesn't make them the same thing.
After enterGrades returns, the vector named "gradeList" in main is still empty.
When you try access the first element of an empty vector, you get an error.
Your main should look like this:
int main()
{
std::vector<int> gradeList = enterGrades();
cout << "Maximum grade is: " << maxNum(gradeList) << endl;
cout << "Minimum grade is: " << minNum(gradeList) << endl;
cout << "Average grade is: " << avgNum(gradeList) << endl;
}
Changing the implementation of enterGrades to fit is left as an exercise.
Also, this thing that you keep doing:
int length = gradeList.size();
gradeList.resize(length);
doesn't make sense, as it's resizing a vector to the size it already had.
Remove it.
You're also repeatedly declaring an iterator for no reason at all.
You also probably want to review what average you're supposed to calculate, as you're calculating the average index in a vector, not the average value.
And watch out for those integer divisions.

Is it a similar function in C++11 as in C11 for the twodimensional matrix?

I have noticed that in gcc C11 you can pass any matrix to a function fn(int row, int col, int array[row][col]). How to translate my below placed (in a link to an another stackoverflow answer) program in C11 to a program in C++11?
C - allocating a matrix in a function
As you can see I can pass to functions static and dynamic allocated arrays in C11. Is it possible in C++11?
I have made an exemplary program based on different stackoverflow answers, but all functions work for array1 and none of them works for array2, where double array1[ROW][COL] = { { } } and auto array2 = new double[ROW][COL]() ?
How to make a function for both arrays as is made in C11 fn(int row, int col, int array[row][col])?
#include <iostream>
#include <utility>
#include <type_traits>
#include <typeinfo>
#include <cxxabi.h>
using namespace std;
const int ROW=2;
const int COL=2;
template <size_t row, size_t col>
void process_2d_array_template(double (&array)[row][col])
{
cout << __func__ << endl;
for (size_t i = 0; i < row; ++i)
{
cout << i << ": ";
for (size_t j = 0; j < col; ++j)
cout << array[i][j] << '\t';
cout << endl;
}
}
void process_2d_array_pointer(double (*array)[ROW][COL])
{
cout << __func__ << endl;
for (size_t i = 0; i < ROW; ++i)
{
cout << i << ": ";
for (size_t j = 0; j < COL; ++j)
cout << (*array)[i][j] << '\t';
cout << endl;
}
}
// int array[][10] is just fancy notation for the same thing
void process_2d_array(double (*array)[COL], size_t row)
{
cout << __func__ << endl;
for (size_t i = 0; i < row; ++i)
{
cout << i << ": ";
for (size_t j = 0; j < COL; ++j)
cout << array[i][j] << '\t';
cout << endl;
}
}
// int *array[10] is just fancy notation for the same thing
void process_pointer_2_pointer(double **array, size_t row, size_t col)
{
cout << __func__ << endl;
for (size_t i = 0; i < row; ++i)
{
cout << i << ": ";
for (size_t j = 0; j < col; ++j)
cout << array[i][j] << '\t';
cout << endl;
}
}
int main()
{
double array1[ROW][COL] = { { } };
process_2d_array_template(array1);
process_2d_array_pointer(&array1); // <-- notice the unusual usage of addressof (&) operator on an array
process_2d_array(array1, ROW);
// works since a's first dimension decays into a pointer thereby becoming int (*)[COL]
double *b[ROW]; // surrogate
for (size_t i = 0; i < ROW; ++i)
{
b[i] = array1[i];
}
process_pointer_2_pointer(b, ROW, COL);
// allocate (with initialization by parentheses () )
auto array2 = new double[ROW][COL]();
// pollute the memory
array2[0][0] = 2;
array2[1][0] = 3;
array2[0][1] = 4;
array2[1][1] = 5;
// show the memory is initialized
for(int r = 0; r < ROW; r++)
{
for(int c = 0; c < COL; c++)
cout << array2[r][c] << " ";
cout << endl;
}
//process_2d_array_pointer(array2);
//process_pointer_2_pointer(array2,2,2);
int info;
cout << abi::__cxa_demangle(typeid(array1).name(),0,0,&info) << endl;
cout << abi::__cxa_demangle(typeid(array2).name(),0,0,&info) << endl;
return 0;
}
The feature that you are using in C11 was introduced in C99, and was specifically designed to allow efficient and easy handling of multidimensional arrays.
While C++ shares the basic syntax with C when it comes to (multidimensional) arrays, array types are significantly less powerfull in C++: In C++ the sizes of array types are required to be compile time constants. Here are a few examples:
void foo(int a, int b) {
int foo[2][3]; //legal C++, 2 and 3 are constant
int bar[a][3]; //Not C++, proposed for C++17: first dimension of an array may be variable
int baz[a][b]; //Not C++, legal in C99
int (*fooPtr)[2][3]; //legal C++
int (*barPtr)[a][3]; //Not C++, legal in C99
int (*bazPtr)[a][b]; //Not C++, legal in C99
typedef int (*fooType)[2][3]; //legal C++
typedef int (*barType)[a][3]; //Not C++, legal in C99
typedef int (*bazType)[a][b]; //Not C++, legal in C99
int (*dynamicFoo)[3] = new int[2][3]; //legal C++
int (*dynamicBar)[3] = new int[a][3]; //legal C++
int (*dynamicBar)[b] = new int[a][b]; //Not C++
}
As you see, almost everything that's possible in C with dynamic sized arrays is not possible in C++. Even the VLA extension that's proposed for the next C++ standard does not help much: it's restricted to the first dimension of an array.
In C++, you have to use std::vector<> to achieve what you can achieve with C99 variable length arrays. With all the consequences:
The data in an std::vector<std::vector<> > is not consecutive in memory. Your caches might not like this.
There is no guarantee with an std::vector<std::vector<> > that all line arrays have the same length. This can be useful, or a pain, depending on your use case.
If you have an iterator to an element in an std::vector<std::vector<> >, you can't advance it to the corresponding element in the next line.
C++ does not have VLA. It is proposed for C++17 but there's a lot of work to do yet because it is quite a big change to the type system, and using C-style arrays is discourated in C++ anyway.
As you have found, you can use templates when the size is known at compile-time. If the size is not known at compile-time then your best bet is to use a single-dimensional vector wrapped up in a class for accessing it in the way you want to access it.
The vector of vectors is also possible of course; that describes a jagged array. Whether you prefer that over the single large memory block depends on various things (complexity of coding, runtime speed / memory usage considerations etc).

RSA mpz_powm() in for-loop: seg fault

This is a follow-up question to a previous question (now that the actual issue is different):
int main()
{
mpz_t p, q, n, phi_n, e, d;
mpz_inits(p, q, n, phi_n, e, d, NULL);
generate_pq(p,q);
compute_n(n,p,q);
compute_phiN(phi_n,p,q);
mpz_clear(p,q,NULL);
select_e(e,phi_n);
compute_d(d,e,phi_n);
mpz_clear(phi_n);
mpz_t* m;
int size=0;
store_m(m,size);
mpz_t* c;
encrypt(c,m,size,e,n);
return 0;
}
Here are the relevant functions:
void store_m(mpz_t m[], int& size)
{ /* m = original message */
printf("\nMessage: ");
char* buffer = new char[128];
cin.getline(buffer,128);
size = strlen(buffer); //size = buffer
m = new mpz_t[size];
for(int i=0; i<size; i++) {
mpz_init(m[i]);
mpz_set_ui(m[i],(int)buffer[i]);
}
delete buffer;
}
void encrypt(mpz_t*& c, mpz_t m[], const int size,
const mpz_t e, const mpz_t n)
{ /* c = cipher */
cout << "1" << endl;
c = new mpz_t[size];
cout << "2" << endl;
for(int i=0; i<size; i++) {
cout << "3" << endl;
mpz_init(c[i]);
cout << "4" << endl;
mpz_powm(c[i],m[i],e,n);
cout << "5" << endl;
mpz_clear(m[i]);
cout << "6" << endl;
} /* c = m^e(mod n) */
cout << "7" << endl;
}
When I execute, the program goes into encrypt() but seg faults at the 4th cout.
Remember C++ is pass-by-value unless you explictly say you're passing by reference using the & operator. In store_m() you are allocating and assigning to m inside the function. That won't work since you're passing m by value. As a result the main() function never sees the assignment to m since store_m() has only a local copy of m. You are therefore passing an uninitialized variable to encrypt(). Either allocate m in main() or declare store_m() like so:
void store_m( mpt_t*& m, int& size);
BTW: You're not segfaulting at the 4th cout. You're segfaulting right after when the encrypt() function prepares to call mpz_powm(). The actual crash is the dereference m[i] (since m is unitialized).