Copying, printing and inputing an array in C++ - c++

For a class assignment I am required to create 4 functions to test in a program. I must use the copyArray function, PrintArray function and InputArray function. The problem that I am having the most trouble with is the copyArray portion. I have completed most of the code on my own but I need to know if I am close to the solution or not close at all.The code, I'm sure, is a mess. If someone could help me get in the right direction of how to finish this I will be very grateful.
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
using std::istream;
using std::ostream;
void inputArray(istream &, int[], int*);
void printArray(ostream &, const int[], int);
float a[4] = { 0, 1, 2, 3 };
float b[4];
void copyArray(const int orig[], int dup[], int);
void main()
{
int a[4] = { 7, 14, 9, 10 };
int b[4];
cout << "The input data : " << endl;
inputArray(cin, a, b);
cout << "The printArray data : " << endl;
printArray(cout, b, 4);
}
//----------------------------------------------------------------------------
void inputArray(istream & in, int t[], int howMany)
{
for (int i = 0; i < howMany; i++)
in >> t[i];
return;
}
//-----------------------------------------------------------------------------
void printArray(ostream & out, const int r[], int cnt)
{
for (int i = 0; i< cnt; i++)
out << r[i] << endl;
return;
}
void copyArray(const int orig [], int dup [], int);
for (int i = 0; i < 4; i++){
b[i] = a[i];
}
}

Of course it would be better to define function copyArray as a template function. For example
template <typename T, size_t N>
void copyArray( T ( &dst )[N], const T ( &src )[N] )
{
for ( size_t i = 0; i < N; i++ ) dst[i] = src[i];
}
As for your function declaration then its definition can look like
void copyArray( int dst[], const int src[], size_t n )
for ( size_t i = 0; i < n; i++ ) dst[i] = src[i];
}
In the function definition shown by you you have to remove the semicolon after the closing parenthesis and to use function parameters instead of the global variables.
Take into account that there are standard algorithms std::copy, std::copy_n, std::copy_if, std::copy_backward declared in header <algorithm> that can be used for coping arrays.

Related

Argument of type int(*)[] is incompatible with parameter of type "int**"

I was creating a function that would give me random values of a matrix. I know how to make it in the main function but I want a separate one. I also tried with void and the same thing happened, and I keep getting the same error. I am beginner and I understand that the issue is something to do with pointers but I still don't know what should I do to make it work and fix it. I already Googled it but I can't make this work.
#include<stdlib.h>
#include<iostream>
#include<time.h>
int row, coll;
int random(int *mat[])
{
srand(time(0));
for(int i=0; i<row; i++)
{
for(int j=0; j<coll; j++)
{
mat[i][j] = rand()%10;
}
}
}
main()
{
std::cin >> row >> coll;
int mat[row][coll];
random(mat);
}
You are trying to mix features of two different languages in one program.
The presented program is not a valid C++ program nor a valid C program.
For example variable length arrays as in your program
std::cin >> row >> coll;
int mat[row][coll];
is not a standard C++ feature.
The function main shall have the return type int.
Your function random
int random(int *mat[])
has the return type int but returns nothing.
The argument has the type (if to assume that variable length arrays are supported)
int ( * )[coll]
but the function parameter type is
int **.
If you are going to write a C++ program then instead of a variable length array use the standard container std::vector<std::vector<int>>.
For example
std::cin >> row >> coll;
std::vector<std::vector<int>> mat( row, std::vector<int>( coll ) );
Otherwise write a C program that can look like
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void random( size_t row, size_t col, int mat[row][col], int limit )
{
srand( ( unsigned int )time( NULL ) );
for ( size_t i = 0; i < row; i++ )
{
for ( size_t j = 0; j < col; j++ )
{
mat[i][j] = rand() % limit;
}
}
}
int main( void )
{
size_t row, col;
scanf( "%zu %zu", &row, &col );
int mat[row][col];
random( row, col, mat, 10 );
return 0;
}
I wrote a simple struct of matrix for you to carry the data around functions. Also, a output overload to make it easier to demo. Please look over it, and don't hesitate to ask, if you need more elaborations.
#include<stdlib.h>
#include<iostream>
#include<time.h>
#include <iomanip>
struct Matrix
{
int *arr;
const int row, col;
Matrix() = delete;
Matrix(const int i, const int j): row(i), col(j)
{
arr = new int [i*j];
}
~Matrix() { delete [] arr; }
int operator()(const int i, const int j) const {return arr[i*col+j];}
int&operator()(const int i, const int j) {return arr[i*col+j];}
};
std::ostream& operator<<(std::ostream&osm, const Matrix&M)
{
for (int i=0; i<M.row; i++) {
for (int j=0; j< M.col; j++) osm << std::setw(8) << M(i,j);
osm << std::endl;
}
return osm;
}
void random(Matrix& amtx)
{
srand(time(0));
for(int i=0; i<amtx.row; i++)
{
for(int j=0; j<amtx.col; j++)
{
amtx(i,j) = rand()%10;
}
}
}
int main()
{
int r, c;
std::cout << "Input row and column : ";
std::cin >> r >> c;
Matrix mtx(r, c);
random(mtx);
std::cout << mtx;
return 0;
}
and the test run:
Input row and column : 5 5
6 3 1 9 3
6 5 1 4 1
1 2 7 5 5
9 3 2 8 1
7 4 8 3 5

C++ non recursive function with variable number of args

I have a Matrix template class and I need a function to set it's elements with variable number of args.
I should be able to call it like this:
aghMatrix<string> matrix;
matrix.setItems(2, 3, "torzmiae", "jestdnaci", "tablickore", "wyrazobed", "oelmntai", "rozmiaecy");
Where first integer is rows number, second is columns and rest (R * C) arguments are elements that I should put into matrix.
It should work with any data types, not only primitive ones.
For now, my function looks like this:
template<typename T>
template<typename... ARGS>
void aghMatrix<T>::setItems(const int rows, const int cols, ARGS... args) {
array<T, sizeof...(args)>unpacked_args {args...};
int row = 0;
int col = 0;
for (T arg : unpacked_args)
{
this->matrixPtr[row][col] = arg;
col++;
if (col == this->cols) {
row++;
col = 0;
}
}
return;
}
I assumed my matrix object is able to hold all elements. It does compile with many warnings about casting everything to unsigned int, but the program doesn't work anyway (it freezes on start).
Class declaration:
template<typename T>
class aghMatrix {
public:
[...]
template<typename... ARGS> void setItems(const int rows, const int cols, ARGS... args);
[...]
private:
T **matrixPtr;
int rows;
int cols;
void createMatrix(const int row, const int col);
bool checkRowCol(const int row, const int col) const;
};
Github project
EDIT: Oops! I just noticed you said "non recursive," so I presume the following pattern doesn't work for you. I'll still leave it hanging here for now, but I have provided also a non recursive solution below (which is based on va_list and hence only works with POD types)
If I understand correctly what you want to do, then you probably want the recursive variadic argument unpacking pattern; something like this seems to do the trick...
#include <iostream>
using namespace std;
// Helper for build_matrix, taking zero variadic arguments.
// This serves as the termination in the recursive unpacking of the args.
template<typename T>
void build_matrix_helper(T**, size_t, size_t, size_t, size_t) { return; }
// Helper for build_matrix, taking at least one variadic argument.
template <typename T, typename ...ARGS>
void build_matrix_helper(T** matrix, size_t curr_row, size_t curr_col,
size_t row, size_t col, const T& first, ARGS...rest) {
if (curr_col < col) {
matrix[curr_row][curr_col] = first;
++curr_col;
return build_matrix_helper<T>(matrix, curr_row, curr_col, row, col, rest...);
}
else {
++curr_row;
curr_col = 0;
return build_matrix_helper<T>(matrix, curr_row, curr_col, row, col, first, rest...);
}
return;
}
// Bare bones implementation.
template<typename T, typename ...ARGS>
T **build_matrix(size_t row, size_t col, ARGS...elements) {
T **new_mat = new T*[row];
for (size_t j = 0; j < row; ++j)
new_mat[j] = new T[col];
build_matrix_helper<T>(new_mat, 0, 0, row, col, elements...);
return new_mat;
}
int main() {
int **nm = build_matrix<int>(2, 3, 1, 2, 3, 4, 5, 6);
for (size_t i = 0; i < 2; ++i) {
cout << "[" << i + 1 << "]: ";
for (size_t j = 0; j < 3; ++j)
cout << nm[i][j] << " ";
cout << endl;
}
delete[] nm;
return 0;
}
In general, you want to avoid any direct manipulation of memory as much as possible. Also avoid as much as possible any casting voodoo unless you absolutely need it (which also ties in with direct memory manipulation).
Anyway, can use a non recursive solution below, using std::va_list.
NOTE Since this uses va_list, it does not work with non POD types.
#include <iostream>
#include <cstdarg>
using namespace std;
template <typename T>
T **build_matrix(size_t row, size_t col, ...) {
va_list args;
T **matrix = new T*[row];
va_start(args, col);
for (size_t i = 0; i < row; ++i) {
matrix[i] = new T[col];
for (size_t j = 0; j < col; ++j)
matrix[i][j] = va_arg(args, T);
}
va_end(args);
return matrix;
}
int main() {
int **nm = build_matrix<int>(2, 3, 1, 2, 3, 4, 5, 6);
for (size_t i = 0; i < 2; ++i) {
cout << "[" << i + 1 << "]: ";
for (size_t j = 0; j < 3; ++j)
cout << nm[i][j] << " ";
cout << endl;
}
delete[] nm;
return 0;
}
EDIT Initializer lists
As has been suggested in the comments to your OP, it is better to use initializer lists. I know this isn't what you asked for originally, but maybe it's worth considering:
#include <iostream>
#include <stdexcept>
using namespace std;
template <typename T>
T **build_matrix(size_t row, size_t col, initializer_list<T> il) {
if (il.size() != row*col)
throw out_of_range("Number of elements does not match matrix dimensions!");
size_t curr_row = 0;
size_t curr_col = 0;
T **nm = new T*[row];
nm[0] = new T[col];
for (T elm : il) {
if (curr_col == col) {
++curr_row;
nm[curr_row] = new T[col];
curr_col = 0;
}
nm[curr_row][curr_col] = elm;
++curr_col;
}
return nm;
}
int main() {
int **nm = build_matrix<int>(2, 3, {1, 2, 3, 4, 5, 6});
for (size_t i = 0; i < 2; ++i) {
cout << "[" << i + 1 << "]: ";
for (size_t j = 0; j < 3; ++j)
cout << nm[i][j] << " ";
cout << endl;
}
delete[] nm;
return 0;
}

C++: Pass two-dimensional array to function

This is probably so simple, but I can't figure out why this won't compile.
void display(int);
const int rows = 2;
const int cols = 2;
int main()
{
int ray[rows][cols] = {{1,2 },
{3,4}};
display(ray);
return 0;
}
void display(const int ray[][cols]){
for(int i = 0; i < 2; i ++){
for(int j = 0; j < 2; j ++){
cout << ray[i][j] << endl;
}
}
}
invalid conversion from ‘int (*)[2]’ to ‘int’ [-fpermissive]|
This code will work
const int rows = 2;
const int cols = 2;
void display( const int ray[][cols]);
int main()
{
int ray[rows][cols] = {{1,2 },
{3,4}};
display(ray);
return 0;
}
void display( const int ray[][cols]){
for(int i = 0; i < 2; i ++){
for(int j = 0; j < 2; j ++){
cout << ray[i][j] << endl;
}
}
}
Your function definition and function declaration do not match, one of them is of type int while the other is type void
Your function declaration is
void display(int);
and the definition is
int display(const int ray[0][cols])
and
int display(const int ray[0][cols])
^
0 ?
I think I see the problem here
The prototype is wrong. If you want a 2D array arg, it's more like this
int display(const int ray**);
The forward declaration of display is wrong. Either fix forward declaration or change order of functions:
#include <iostream>
using namespace std;
const int rows = 2;
const int cols = 2;
int display(const int ray[0][cols]){
for(int i = 0; i < 2; i ++){
for(int j = 0; j < 2; j ++){
cout << ray[i][j] << endl;
}
}
}
int main()
{
int ray[rows][cols] = {{1,2 },
{3,4}};
display(ray);
return 0;
}
Live Example
Since you use global variables anyway, the easy thing is to change your declaration of display:
Declare display like this:
void display(int** array)
{...}
In this case you will actually be able to send your 2D array to the function because the type will match. A 2D array is an array of arrays and an array is just a pointer associated with some memory.
I am not giving the appropriate answer to this question. But an alternative.
As C++ suggests to use std::string inplace of char* . It also suggests to use vectors instead of array wherever applicable.
#include <iostream>
#include <vector>
void display( std::vector<std::vector<int>> );
int main()
{
std::vector<std::vector<int>> int_vec{ { 1 , 2 } , { 3 , 4 } };
display( int_vec );
system("PAUSE");
return EXIT_SUCCESS;
}
void display( std::vector<std::vector<int>> integer_vector )
{
for( auto& i : integer_vector )
{
for( auto& j : i )
{
std::cout << j << std::endl;
}
}
}
The global variables as rows and cols are gone :).

C++ Returning two values in Array

I am almost done with my code; however, one part is not working well. Simply, reading from a file that contains only numbers(ex. cars sold). by using an array, trying to get the total of those numbers, max, and the number of the max index. My question is: how can I return the two values from my MaxSold function? it returns only the max added to the index which is not correct. the result should point to the employee number then the max.
This is my code so far:
#include <iostream>
#include <fstream>
/*#include <vector>
#include <iomanip>*/
void Read(int arryList[], int size);
void Print(int arryList[], int size);
int total(int arryList[], int size);
int MaxSold(int arryList[], int size, int& number);
using namespace std;
ifstream inFile("C:\\cars.dat");
int main()
{
int cars[7];
int i;
Read(cars,7);
Print(cars,7);
cout<<"The total of sold cars is: "<<total(cars, 7)<< "\n";
cout<<"The Max "<< MaxSold(cars, 7, i);
}
void Read(int arryList[], int size){
for(int i = 0; i < 7; i++)
{
inFile >> arryList[i];
}
return;
}
void Print(int arryList[], int size){
for (int i = 0; i < 7; i++){
cout << i + 1 << "-"<< arryList[i] << "\n";
}
return ;
}
int total(int arryList[], int size){
int sum = 0;
for (int i = 0; i < size; i++){
sum +=arryList[i];
}
return sum;
}
int MaxSold(int arryList[], int size, int& number){
int Maximum= 0;
int relate=0;
for( int i=0 ; i<7 ; i++){
if (arryList[i] > Maximum){
Maximum = arryList[i];
relate = i+1;
}
}
return Maximum, relate;
}
Use std::pair
#include<utility>
//..
std::pair<int,int> MaxSold(int arryList[], int size, int& number)
{
//...
return std::make_pair( Maximum, relate );
}
Then,
std::pair<int,int> p = MaxSold(cars, 7, i) ;
std::cout<< p.first ; //maximum
std::cout<< p.second ; //relate
You cannot return more than one value from a function. Of course, that value can be a container for multiple values. It can be your own custom type, but the simplest way would be to return a std::pair<int,int>.
std::pair<int, int> MaxSold(int arryList[], int size, int& number)
{
// ...
return std::make_pair(Maximum, relate);
}

C++ 2D array of pointers segmentation fault

I am facing an issue with a 2D array of pointers. It compiles with no errors, however when I try to run the file, all I get is a single line saying I have a segmentation fault.
My header file:
#ifndef __TWODARRAY_H__
#define __TWODARRAY_H__
template <typename T>
class TwoDArray {
private:
T** theArray;
int numRows;
int numCols;
T defSpace;
public:
TwoDArray<T> (int r, int c, T def);
~TwoDArray<T>();
void insert(int r, int c, T value);
T access(int r, int c);
void remove(int r, int c);
void print();
int getNumRows();
int getNumCols();
};
#endif
My Methods:
#include "TwoDArray.h"
#include <iostream>
#include <assert.h>
#include <string>
//initializes the 2D Array
template <typename T>
TwoDArray<T>::TwoDArray(int r, int c, T def) {
assert(r > 0 && c > 0);
numRows = r;
numCols = c;
defSpace = def;
theArray = new T*[r];
for(int i=0; i<r; i++) {
theArray[i] = new T[c];
}
//sets all values to the default
for(int i=0; i<r; i++) {
for(int j=0; j<c; j++) {
theArray[i][j] = defSpace;
}
}
}
//deletes the 2D Array
template<typename T>
TwoDArray<T>::~TwoDArray() {
for(int i=0; i<numRows; i++) {
delete[] theArray[i];
}
delete[] theArray;
}
//inserts value v at row r and column c
template<typename T>
void TwoDArray<T>::insert(int r, int c, T value) {
assert(r < numRows && c < numCols);
assert(value != defSpace);
theArray[r][c] = value;
}
//get value at row r, column c
template<typename T>
T TwoDArray<T>::access(int r, int c) {
assert(r < numRows && c < numCols);
T result = theArray[r][c];
return result;
}
//set value at row r and column c back to default
template<typename T>
void TwoDArray<T>::remove(int r, int c) {
assert(r < numRows && c < numCols);
assert(theArray[r][c] != defSpace);
theArray[r][c] = defSpace;
}
//print the 2D Array
template<typename T>
void TwoDArray<T>::print() {
for(int i=0; i<numRows; i++) {
for(int j=0;j<numCols; i++) {
std::cout << theArray[i][j];
std::cout << " ";
}
std::cout << std::endl;
}
}
//gets number of rows for test
template<typename T>
int TwoDArray<T>::getNumRows() {
return numRows;
}
//gets number of columns for test
template<typename T>
int TwoDArray<T>::getNumCols() {
return numCols;
}
template class TwoDArray<int>;
template class TwoDArray<std::string>;
And my main:
#include <iostream>
#include <string>
#include "TwoDArray.h"
using std::cout;
using std::endl;
int main() {
TwoDArray<int>* i = new TwoDArray<int>(5, 5, 0);
TwoDArray<std::string>* s = new TwoDArray<std::string>(5, 5, "o");
i->insert(1, 1, 1);
i->insert(1, 3, 1);
i->insert(3, 2, 8);
i->insert(2, 0, 3);
i->insert(2, 4, 3);
i->insert(3, 2, 8);
i->print();
s->insert(0, 2, "North");
s->insert(4, 2, "South");
s->insert(2, 4, "East");
s->insert(2, 0, "West");
s->print();
return 0;
}
Any ideas why I'm getting a segmentation fault?
This is a mistake:
template<typename T>
void TwoDArray<T>::print() {
for(int i=0; i<numRows; i++) {
for(int j=0;j<numCols; i++) { // should be j++, not i++
std::cout << theArray[i][j];
std::cout << " ";
}
std::cout << std::endl;
}
}
as i is being incremented in both the outer and inner for and will eventually lead to i equalling numRows and going one past the end of the array, which is undefined behaviour and a possible cause of the segmentation fault.
As there is a dynamically allocated member in TwoDArray you need to prevent copying of instances of TwoDArray or implement the assignment operator and copy constructor (see What is The Rule of Three?).
If this is not a learning exercise you could use a vector<vector<T>> instead.
Also, as the dimensions of the array are compile time constants it is possible to make them template parameters also and avoid dynamic memory completely:
template <typename TType, int TRows, int TCols>
class TwoDArray {
private:
TType theArray[TRows][TCols];
TType defSpace;
....
TwoDArray<int, 5, 5> i(0);
see http://ideone.com/dEfZn5 for full demo.