Dynamic Arrays and user input c++ - c++

I'm writing a program for my C++ class that takes the user input for the size of a int and char array, fills the arrays with random values (numbers 0-100, letters A-Z) then sorts, reverses, and displays both arrays.
For the most part the program works and I understand the logic I used here, but...
After running and debugging the code multiple times. I noticed that when the arrays were being filled with values, the first element, even though it was actually being given a value, it would not print the assigned value it was given in ascending order, but would in a descending order? I don't understand this at all.
NOTE: I have to use template functions for the sorting, reversing and display of the arrays.
template <class T>
void sort(T *arr, int a) {
T temp;
for (int i = 0; i < a; i++) {
for (int j = a; j > 0; j--) {
if (arr[i] > arr[j]) {
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
}
template <class T>
void reverse(T *arr, int a) {
T temp;
for (int i = 0; i < a / 2; i++) {
temp = arr[i];
arr[i] = arr[a - i];
arr[a - i] = temp;
}
}
template <class T>
void display(T *arr, int a) {
for (int i = 0; i < a; i++) {
cout << arr[i] << ", ";
}
cout << endl;
}
template<class T>
void save(T *arr, int a) {
sort(arr, a);
display(arr, a);
reverse(arr, a);
display(arr, a);
}
int main() {
int x, y;
cout << "Please enter a number for an array of data type \"int\"" << endl;
cin >> x;
cout << "Please enter a number for an array of data type \"char\"" << endl;
cin >> y;
int *arr1 = new int[x];
char *arr2 = new char[y];
for (int i = 0; i < x; i++)
cout << (arr1[i] = rand() % 100 + 1);
srand(time(nullptr));
for (int i = 0; i < y; i++)
cout << (arr2[i] = rand() % 26 + 65);
system("cls");
save(arr1, x);
save(arr2, y);
delete[]arr1;
delete[]arr2;
system("pause");
return 0;
}

You are using the complete length here:
save(arr1, x);
save(arr2, y);
So in reverse
arr[i] = arr[a - i];
arr[a - i] = temp;
you need to -1 on the length or you'll get an invalid index when i == 0
arr[i] = arr[a - 1 - i];
arr[a - 1 - i] = temp;
Like R Sahu says, in sort
for (int j = a; j > 0; j--) {
you need to -1 because a is the length which will be an invalid index.
for (int j = a-1; j > 0; j--) {
As a side note, you can declare Temp t inside of the for loop in reverse and inside of the if in sort because it is only used in those scopes.
EDIT:
Also I overlooked, in sort you need to change
j>0
to
j >= 0
that way you access the first element of the array as well.

You have a off-be-one error in couple of places.
for (int j = a; j > 0; j--) {
is incorrect. a is an invalid index for the array. Change that line to use j = a-1:
for (int j = a-1; j > 0; j--) {
You have a similar, off-by-one, error in reverse. Instead of
arr[i] = arr[a - i];
arr[a - i] = temp;
you need to use:
arr[i] = arr[a - i - 1];
arr[a - i - 1] = temp;
Your implementation of sort is not correct. I don't want to get into the algorithmic details here but changing the order of the values used for j seems to fix the problem.
for (int i = 0; i < a; i++) {
for (int j = i+1 ; j < a ; j++) {
// The swapping code.
}
}

You are using bubble sort that is O(n^2) time complexity. Consider using faster algorithm. If you don't want to implement it on your own, use sort() function. It's complexity is about O(n log n), which is very good.
http://www.cplusplus.com/reference/algorithm/sort/
#include <iostream>
#include <algorithm>
using namespace std;
bool comp(int i1, int i2) { // comp function is to compare two integers
return i1 < i2;
}
int main() {
int x[30];
int n;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> x[i];
}
sort(x, x + n, comp); // if you don't provide comp function ( sort(x, x+n) ), sort() function will use '<' operator
for (int i = 0; i < n; i++) {
cout << x[i] << " ";
}
return 0;
}

Related

Rotate a 2-D array by 90 degrees

How can I take the array size input from the user and pass it to the function. I tried #define inside the function, it doesn't work since the array definition needs the array bound at compile time. I tried global variable too, it says to define a integer constant which is not feasible in my case since I want to get the size from the user. How can I solve this issue?
#include <iostream>
using namespace std;
// reverse the transposed matrix as step 2
void reverseColumns(int arr[N][N])
{
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N / 2; j++)
{
int temp = arr[i][j];
arr[i][j] = arr[i][N - j - 1];
arr[i][N - j - 1] = temp;
}
}
}
// take the transpose of matrix as step 1
void transposeMatrix(int arr[N][N])
{
for (int i = 0; i < N; i++)
{
for (int j = i; j < N; j++)
{
int temp = arr[i][j];
arr[i][j] = arr[j][i];
arr[j][i] = temp;
}
}
}
void rotateMatrix(int mat[N][N])
{
transposeMatrix(mat);
reverseColumns(mat);
}
// printing the final result
void displayMatrix(int mat[N][N])
{
int i, j;
for (i = 0; i < N; i++)
{
for (j = 0; j < N; j++)
cout << mat[i][j] << "\t";
cout << "\n";
}
cout << "\n";
}
int main()
{
int T, N;
cin >> T;
while (T > 0)
{
cin >> N;
int mat[N][N];
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
cin >> mat[i][j];
}
}
int res[N][N];
rotateMatrix(mat);
displayMatrix(mat);
}
return 0;
}
One way to make it work is get the input of rows and cols from user and make a one dimensional array dynamically.
for example:
Let ROWS and COLS be the values you got via cin.
Then the array can be declared as
int* arr = new int[ROWS * COLS];
Instead of writing arr[i][j] you have to write
arr[i * COLS + j]
Also you have to delete the array using
delete[] arr;
You are using C++ so you should take advantages of it. As kiner_shah commented the fast way to fix your code is just by use of std::vector<std::vector<int>>.
This is better solution but stil poor:
#include <iostream>
#include <vector>
using namespace std;
using Matrix = std::vector<std::vector<int>>;
Matrix makeSquereMatrix(size_t N)
{
return {N, std::vector<int>(N)};
}
// reverse the transposed matrix as step 2
void reverseColumns(Matrix& arr)
{
auto N = arr.size();
... // no changes here
}
// take the transpose of matrix as step 1
void transposeMatrix(Matrix& arr)
{
auto N = arr.size();
... // no changes here
}
void rotateMatrix(Matrix& mat)
{
transposeMatrix(mat);
reverseColumns(mat);
}
// printing the final result
void displayMatrix(const Matrix& mat)
{
for (auto& row : mat)
{
for (auto x : row)
cout << x << "\t";
cout << "\n";
}
cout << "\n";
}
void readMatrix(Matrix& m)
{
for (auto& row : m)
{
for (auto& x : row)
{
cin >> x;
}
}
}
int main()
{
int T, N;
cin >> T;
while (T > 0)
{
cin >> N;
auto mat = makeSquereMatrix(N);
readMatrix(mat);
rotateMatrix(mat);
displayMatrix(mat);
--T;
}
return 0;
}
Live demo
Better solution would be introducing a class containing std:::vector with methods performing required actions.
BTW some time ago I've made some matrix code for C. Here is live demo

Applying selection sort on an array of integers

int arr[] = {7,4,10,8,3,1};
int size = sizeof(arr) / sizeof(arr[0]);
for(int i = 0; i<size-1; i++){
int temp = arr[i];
for(int j = i+1; j < size; j++){
if(arr[j] < temp){
temp = arr[j];
}
}
swap(temp, arr[i]);
}
I am trying to apply the selection sort algorithm on the given array, but the output I am getting is only [1,1,1,1,1,1], I am finding the minimum element through the inner loop, Ican't figure out what is going wrong?
Slightly modified your code;
You need to pass reference(address) to both elements to take place of swapping contents
int arr[] = { 7, 1, 10, 8, 3, 11, 0, 12, 5, 8 };
int size = sizeof(arr) / sizeof(arr[0]);
for(int i = 0; i < size; i++)
{
auto temp = std::min_element( arr + i, arr + size );
std::swap( arr[i], *temp );
}
You have to add algorithm header to use std::min_element
int arr[] = {7,4,10,8,3,1};
int size = sizeof(arr) / sizeof(arr[0]);
for(int i = 0; i<size-1; i++){
int temp = arr[i];
int pos = i;
for(int j = i+1; j < size; j++){
if(arr[j] < temp){
temp = arr[j];
pos = j;
}
}
if(pos != i)
std::swap(arr[pos], arr[i]);
}
This should work.
It is suggested not to use using namespace std;. There is a plethora of reasons why you should not; that I will not mention.
By the way I tried to keep some of your variables the same but to be honest, I didn't. It is better to create variable names that explain what the code is doing. It makes your code a lot more legible and readable.
So opt out of one letter variables. It is fine in for loops, however this is a special case.
Now, here is another alternative suggested by #user4581301 & #Swift -Friday Pie. This method is using std::size using c++17.
For example:
#include <iostream>
#include <utility> // to use the swap() function.
#include <iterator> // to use std::size() function.
int main()
{
int arr[] = { 7,4,10,8,3,1 };
// This --> int size = sizeof(arr) / sizeof(arr[0]); is archaic.
const int length = static_cast<int>(std::size(arr)); // Call this something other than "size"; you can run into issues.
// We use static_cast<int> as a implicit conversion, and the obvious std::size(arr)).
// Going through the elements
for (int StartOfIndex = 0; StartOfIndex < length - 1; ++StartOfIndex)
{
// smallest is the index of the smallest element we’ve encountered this iteration
int smallest = StartOfIndex;
// Looking for a smaller element..
for (int current = StartOfIndex + 1; current < length; ++current)
{
// if we found an element smaller than our last; take note.
if (arr[current] < arr[smallest])
smallest = current;
}
// swap StartOfIndex with smallest.
std::swap(arr[StartOfIndex], arr[smallest]);
}
//Prints array.
for (int index = 0; index < length; ++index)
std::cout << arr[index] << " ";
std::cout << "\n";
return 0;
}
Output: 1 3 4 7 8 10
The first mistake you made in writing for loop's condition, don't use swap(temp, array[i]); yet try to get the basics first.
#include <iostream>
using namespace std;
int findsmall(int arr[], int i, int size){
int s, pos, j;
s = arr[i];
pos = i;
for(j = i+1; j < size; j++){
if(arr[j] < s){
s = arr[j];
pos = j;
}
}
return pos;
}
int main() {
int arr[] = {7,4,10,8,3,1};
int size = sizeof(arr) / sizeof(arr[0]);
int smallnum;
int temp;
int count = 0;
cout << "Original array: ";
for(int i = 0; i < size; i++){
if(i < size - 1){
cout << arr[i] << ", ";}
else{
cout << arr[i];
}
}
cout << endl;
for(int i = 0; i < size; i++){
smallnum = findsmall(arr,i, size);
temp = arr[i];
arr[i] = arr[smallnum];
arr[smallnum] = temp;
count++;
}
cout << "Sorted array: ";
for(int i = 0; i < size; i++){
if(i < size - 1){
cout << arr[i] << ", ";}
else{
cout << arr[i];
}
}
cout << endl;
return 0;
}
void swap(int *xp, int *yp)
{
int temp = *xp;
*xp = *yp;
*yp = temp;
}
void selectionSort(int arr[], int n)
{
int i, j, min_idx;
// One by one move boundary of unsorted subarray
for (i = 0; i < n-1; i++)
{
// Find the minimum element in unsorted array
min_idx = i;
for (j = i+1; j < n; j++)
if (arr[j] < arr[min_idx])
min_idx = j;
// Swap the found minimum element with the first element
swap(&arr[min_idx], &arr[i]);
}
}
selectionSort(arr,size);
This should work.

Finalize the magic square generator

This code that runs only for odd N. The problem is that there are no ideas how to add support for even values N
#include "stdafx.h"
#include <iostream>
using namespace std;
int main()
{
setlocale(0, "");
int n;
cout << "Enter the size of the magic square - ";
cin >> n;
int **matrix = new int *[n];
for (int i = 0; i < n; ++i)
{
matrix[i] = new int[n];
}
int nsqr = n * n;
int i = 0, j = n / 2;
for (int k = 1; k <= nsqr; ++k)
{
matrix[i][j] = k;
i--;
j++;
if (k % n == 0)
{
i += 2;
--j;
}
else
{
if (j == n)
{
j -= n;
}
else if (i < 0)
{
i += n;
}
}
}
cout << "\n\nMagic square size - " << n << "\n\n";
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
cout << matrix[i][j] << "\t";
}
cout << endl;
}
for (i = 0; i < n; i++)
delete[] matrix[i];
delete[] matrix;
system("pause >> null");
return 0;
}
I would be grateful for tips on troubleshooting.
If i'm not mistaken, the problem is in this line:
int i = 0, j = n / 2;
But i don't know how to change the code to support even values
I would assume that you meant normal magic square (where the number are restricted to 1,2..n^2)
First of all, it's impposible to construct such magic square for n=2.
2nd, you would need an whole new algorithm for it, which is much more complicated. The problem (constructing magic square for any even number) is solved in this paper and while there isn't any psaudo code there, the implementation from the explenation is quite straightforward (long one though).
the problem is here:
i = 0;
int j = n / 2;
for (int k = 1; k <= nsqr; ++k)
{
matrix[i][j] = k;
i--;
}
look how you decrement i inside the loop and making it as an index of the array so:
matrix[-3][j] = k; // will be in your code
you are messing deliberately with the indexes of the array
I found answer on my question in this artcile
I made full revision my algorithm based on this article. Later posted listing the resulting program

A function which will display the contents of an array being sorted c++ using insertion sort

I have error, which is highlighted "cout << array[i] << endl;" in this section. The line is under array[i]. The error is "argument list for class template "std::array" is missing ". i need a function to display the contents of an array, using an insertion sort. If this code is incorrect, does anyone know the code to output the contents of the array, using linear search.
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main()
{
int numbers[SIZE] = { 6,3,1,9,4,12,17,2 };
for (int i = 0; i < 8; i++)
{
cout << array[i] << endl;
}
system("pause");
}
const int SIZE = 8;
void insertionSort(int numbers[], int arraySize)
{
int i, j, insert;
for (i = 1; i < arraySize; i++)
{
insert = numbers[i];
j = i;
while ((j > 0) && (numbers[j - 1] > insert))
{
numbers[j] = numbers[j - 1];
j = j - 1;
}
numbers[j] = insert;
}
}
You didn't call your function insertionSort(int numbers[], int arraySize) in main(). Therefore nothing will happen to the original array.
Note that you need a return 0; statement inside int main(). And that you need to use numbers[i] instead of array[i]. And you need to set your insertionSort() to return "something" or to pass your numbers[] as a reference. Also not to forget about the function prototype before main().
This should work:
const int SIZE = 8;
void insertionSort(int [], int);
int main()
{
int numbers[SIZE] = { 6,3,1,9,4,12,17,2 };
insertionSort(numbers, SIZE);
for (int i = 0; i < 8; i++)
cout << numbers[i] << endl;
system("pause");
return 0;
}
void insertionSort(int MyArray[], int size)
{
int i, j, insert;
for (i = 1; i < size; i++){
insert = MyArray[i];
j = i;
while ((j > 0) && (MyArray[j - 1] > insert)){
MyArray[j] = MyArray[j - 1];
j = j - 1;}
MyArray[j] = insert;}
}

Incorrect Result from Selection Sort Algorithm

#include <iostream>
using namespace std;
// Selection Sort function.
// Parameter 'a' is the size of the array.
void ss(int AR[] , int a) {
int small;
for (int i = 0 ; i <a ; i++) {
small = AR[i];
for (int j = i+1 ; j <a ; j++) {
if (AR[j]< small) {
int k = AR[j];
AR[j] = AR[i];
AR[i] = k;
}
}
}
}
int main() {
cout << "Enter the size of Your Aray";
int a;
cin >> a;
int AR[a];
cout << endl;
for (int i = 0; i < a; i++) {
cin >> AR[i];
cout << endl;
}
ss(AR, a);
cout << "The Sorted Array is";
for (int i=0; i < a; i++) {
cout << AR[i] << " ";
cout << endl;
}
}
When I enter the following:
15
6
13
22
23
52
2
The result returned is:
2
13
6
15
22
23
52
What is the bug preventing the list from being sorted numerically as expected?
The function can look like
void ss ( int a[], size_t n )
{
for ( size_t i = 0 ; i < n ; i++ )
{
size _t small = i;
for ( size_t j = i + 1; j < n ; j++ )
{
if ( a[j] < a[small] ) small = j;
}
if ( i != small )
{
int tmp = a[small];
a[small] = a[i];
a[i] = tmp;
}
}
}
It doesn't seem to be the SelectionSort I know. in the algorithm I know during every loop I look for the smallest element in the right subarray and than exchange it with the "pivot" element of the loop. Here's the algorithm
void selectionSort(int* a, int dim)
{
int posMin , aux;
for(int i = 0; i < dim - 1; ++i)
{
posMin = i;
for(int j = i + 1; j < dim; ++j)
{
if(a[j] < a[posMin])
posMin = j;
}
aux = a[i];
a[i] = a[posMin];
a[posMin] = aux;
}
}
and it seems that you change every smaller element you find, but also change the position of the "pivot". I hope the answer is clear.
Everything is ok in the original function, only that the small variable need to be refreshed when two vector elements will be switched.
Also in if statement set the small variable to the new value of AR[i].