C++ Array copying/shift - c++

We had a project that asked us to Write a program that allows a user to enter a series of numbers "read numbers into an array for further processing, user signals that they are finished by entering a negative number (negative not used in calculations), after all numbers have been read in do the following, sum up the #'s entered, count the #'s entered, find min/max # entered, compute average, then output them on the screen. So the working version of this that I made looks like so
/* Reads data into array.
paramater a = the array to fill
paramater a_capacity = maximum size
paramater a_size = filled with size of a after reading input. */
void read_data(double a[], int a_capacity, int& a_size)
{
a_size = 0;
bool computation = true;
while (computation)
{
double x;
cin >> x;
if (x < 0)
computation = false;
else if (a_size == a_capacity)
{
cout << "Extra data ignored\n";
computation = false;
}
else
{
a[a_size] = x;
a_size++;
}
}
}
/* computes the maximum value in array
paramater a = the array
Paramater a_size = the number of values in a */
double largest_value(const double a[], int a_size)
{
if(a_size < 0)
return 0;
double maximum = a[0];
for(int i = 1; i < a_size; i++)
if (a[i] > maximum)
maximum = a[i];
return maximum;
}
/* computes the minimum value in array */
double smallest_value(const double a[], int a_size)
{
if(a_size < 0)
return 0;
double minimum = a[0];
for(int i = 1; i < a_size; i++)
if (a[i] < minimum)
minimum = a[i];
return minimum;
}
//computes the sum of the numbers entered
double sum_value(const double a [], int a_size)
{
if (a_size < 0)
return 0;
double sum = 0;
for(int i = 0; i < a_size; i++)
sum = sum + a[i];
return sum;
}
//keeps running count of numbers entered
double count_value(const double a[], int a_size)
{
if (a_size < 0)
return 0;
int count = 0;
for(int i = 1; i <= a_size; i++)
count = i;
return count;
}
int _tmain(int argc, _TCHAR* argv[])
{
const int INPUT_CAPACITY = 100;
double user_input[INPUT_CAPACITY];
int input_size = 0;
double average = 0;
cout << "Enter numbers. Input negative to quit.:\n";
read_data(user_input, INPUT_CAPACITY, input_size);
double max_output = largest_value(user_input, input_size);
cout << "The maximum value entered was " << max_output << "\n";
double min_output = smallest_value(user_input, input_size);
cout << "The lowest value entered was " << min_output << "\n";
double sum_output = sum_value(user_input, input_size);
cout << "The sum of the value's entered is " << sum_output << "\n";
double count_output = count_value(user_input, input_size);
cout << "You entered " << count_output << " numbers." << "\n";
cout << "The average of your numbers is " << sum_output / count_output << "\n";
string str;
getline(cin,str);
getline(cin,str);
return 0;
}
That went fine, the problem I am having now is part 2. Where we are to "copy the array to another and shift an array by N elements". I'm not sure where to begin on either of these. I've looked up a few resources on copying array's but I was not sure how to implement them in the current code I have finished, especially when it comes to shifting. If anyone has any thoughts, ideas, or resources that can help me on the right path it would be greatly appreciated. I should point out as well, that I am a beginner (and this is a beginners class) so this assignment might not be the 'optimal' way things could be done, but instead incorporates what we have learned if that makes sense.

for(int i = 0; i < n; ++i){
int j = (i - k)%n;
b[i] = a[j];
}
Check it. I'm not sure
If this works you could improve it to
for(int i = 0; i < n; ++i)
b[i] = a[(i - k)%n];//here can be (i +/- k) it depends which direction u would shift

If you only want to copy the array into another array and shift them
ex : input = 1, 2, 3, 4, 5; output = 3, 4, 5, 1, 2
The cumbersome solution is
//no template or unsafe void* since you are a beginner
int* copy_to(int *begin, int *end, int *result)
{
while(begin != end){
*result = *begin;
++result; ++begin;
}
return result;
}
int main()
{
int input[] = {1, 2, 3, 4, 5};
size_t const size = sizeof(input) / sizeof(int);
size_t const begin = 2;
int output[size] = {0}; //0, 0, 0, 0, 0
int *result = copy_to(input + begin, input + size - begin, output); //3, 4, 5, 0, 0
copy_to(input, input + begin, result); //3, 4, 5, 1, 2
return 0;
}
How could the stl algorithms set help us?
read_data remain as the same one you provided
#include <algorithm> //std::minmax_element, std::rotate_copy
#include <iostream>
#include <iterator> //for std::begin()
#include <numeric> //for std::accumulate()
#include <string>
#include <vector>
int main(int argc, char *argv[]) //don't use _tmain, they are unportable
{
const int INPUT_CAPACITY = 100;
double user_input[INPUT_CAPACITY];
int input_size = 0;
double average = 0;
cout << "Enter numbers. Input negative to quit.:\n";
read_data(user_input, INPUT_CAPACITY, input_size);
auto const min_max = std::minmax_element (user_input, user_input + input_size); //only valid for c++11
std::cout << "The maximum value entered was " << min_max.second << "\n";
std::cout << "The lowest value entered was " << min_max.first << "\n";
double sum_output = std::accumulate(user_input, user_input + input_size, 0);
cout << "The sum of the value's entered is " << sum_output << "\n";
//I don't know the meaning of you count_value, why don't just output input_size?
double count_output = count_value(user_input, input_size);
cout << "You entered " << count_output << " numbers." << "\n";
cout << "The average of your numbers is " << sum_output / count_output << "\n";
int shift;
std::cout<<"How many positions do you want to shift?"<<std::endl;
std::cin>>shift;
std::vector<int> shift_array(input_size);
std::rotate_copy(user_input, user_input + shift, user_input + input_size, std::begin(shift_array));
//don't know what are they for?
std::string str;
std::getline(std::cin,str);
std::getline(std::cin,str);
return 0;
}
if your compiler do not support c++11 features yet
std::minmax_element could replace by
std::min_element and std::max_element
std::begin() can replace by shift_array.begin()
I don't know what is the teaching style of your class, in my humble opinion, beginners should
start with those higher level components provided by c++ like vector, string, algorithms
and so on.I suppose your teachers are teaching you that way and you are allowed to use the
algorithms and containers come with c++(Let us beg that your class are not teaching you "c with classes" and say something like "OOP is the best thing in the world").
ps : You could use vector to replace the raw array if you like

Related

How do I calculate the sum of all the array numbers after the first negative?

Can you help me with this problem? All I could do was count all the negative numbers.
Here is my code:
using namespace std;
int main()
{
const int SIZE = 10;
int arr[SIZE]{};
int number=0;
srand(time(NULL));
cout << "Your array is: " << endl;
for (int i=0; i<SIZE; i++)
{
int newValue = rand()%20-10;
arr[i] = newValue;
cout << arr[i] << " ";
if (arr[i] < 0)
{
for (int j=-1; j<SIZE; j++)
{
number = arr[i];
sum += fabs(number);
break;
}
}
}
cout << endl;
cout << "Sum of elements after first element < 0 is: " << sum;
cout << endl;
}
One way is to have a flag that is zero to start with that is switched on after the first negative:
int flag = 0;
int sum = 0;
for (std::size_t i = 0; i < SIZE; ++i){
sum += flag * arr[i];
flag |= arr[i] < 0;
}
This approach carries the advantage that you don't need an array at all: substituting the next number from standard input for arr[i] is sufficient.
In your specific case, there are numerous simple and efficient solutions, like that offered by Bathsheba.
However, for a more general case of summing elements in an array after the first value satisfying a given condition, you can use the std::find_if and std::accumulate functions from the STL, providing appropriate lambda functions to do the test (checking for negative) and summation (the sum += fabs(number) in your code implies that you want to sum the absolute values of the remaining elements1).
Here's a possible implementation:
#include <cstdlib> // std::abs, std::rand
#include <ctime> // std::time
#include <algorithm> // std::find_if
#include <numeric> // std::accumulate
#include <iostream>
using std::cout, std::endl;
int main()
{
const int SIZE = 10;
int arr[SIZE]{};
// Generate random array...
std::srand(static_cast<unsigned int>(time(nullptr)));
cout << "Your array is: " << endl;
for (int i = 0; i < SIZE; i++) {
int newValue = std::rand() % 20 - 10;
arr[i] = newValue;
cout << arr[i] << " ";
}
// Sum all abs values after first negative ...
auto is_neg = [](int i) { return i < 0; };
auto fn = std::find_if(std::begin(arr), std::end(arr), is_neg);
auto sum_abs = [](int a, int b) { return a + std::abs(b); };
// Set the sum to ZERO if the first negative is the last element...
int sum = (fn == std::end(arr)) ? 0 : std::accumulate(++fn, std::end(arr), 0, sum_abs);
cout << endl;
cout << "Sum of elements after first element < 0 is: " << sum;
cout << endl;
return 0;
}
1 If this is not the case, and you just want the sum of the actual values, then you can omit the 4th (sum_abs) argument in the call to std::accumulate (and the definition of that lambda).

Prompt input until a mimimum number of values is entered

I am writing a small program in which I have to search for smallest and largest element entered.
The thing is I have made an array 10 elements wide and the user should enter at least 5 element.
If the user enter less than 5 elements I want to prompt insufficient elements.
This is the code I have written but it's not working:
#include <iostream>
using namespace std;
int main()
{
int arr[10], largest, smallest, i = 1, j = 1;
cout << "Enter the values in array at least 5 and maximum 10 " << endl;
for (int i = 0; i < 10; i++)
{
cin >> arr[i];
}
while (arr[i] >= 5)
{
largest = arr[0];
smallest = arr[0];
if (largest <= arr[j])
{
largest = arr[j];
}
if (smallest > arr[j])
{
smallest = arr[j];
}
j++;
i++;
}
getch();
return 0;
}
This code demonstrates how you'd find the min and max of a std::vector. The same principles apply to arrays. This piece of code does not allow a variable number of inputs.
#include <algorithm> // std::min_element() & std::max_element
#include <iostream>
#include <random>
#include <vector>
int main() {
// Set up; Fills vector with 10 random digits in range [1, 10]
std::mt19937 prng(std::random_device{}());
std::uniform_int_distribution<int> dist(1, 10);
std::vector<int> numbers(10);
for (unsigned int i = 0; i < numbers.size(); ++i) {
numbers[i] = dist(prng);
}
// Find minimum and maximum, the easy way
auto min = std::min_element(numbers.begin(), numbers.end());
auto max = std::max_element(numbers.begin(), numbers.end());
// Find minimum and maximum, the hard way
int minIdx = 0;
int maxIdx = 0;
for (unsigned int i = 0; i < numbers.size(); ++i) {
if (numbers[i] < numbers[minIdx]) minIdx = i;
if (numbers[i] > numbers[maxIdx]) maxIdx = i;
}
// Print all numbers to verify
for (auto i : numbers) {
std::cout << i << ' ';
}
// This print goes with the std::min_element approach
std::cout << "\nMin: " << *min << "\nMax: " << *max << '\n';
// This print goes with the for loop approach
std::cout << "\nMin: " << numbers[minIdx] << "\nMax: " << numbers[maxIdx]
<< '\n';
}
Output:
1 5 2 10 2 8 6 7 6 7
Min: 1
Max: 10
Min: 1
Max: 10
In both methods, WHERE the min and max are stored are what's recorded. The first method returns an iterator, and the for-loop method records the index. It's more valuable to know where your min and max are versus just knowing the value.
The deal with a variable number of inputs and requiring a minimum is that things get complicated very quickly. The easiest, but not greatest (subjective) approach is to use a sentinel value. It's something the user must type to indicate that they are done typing. The wrinkle here that throws that out a bit is the fact that the user can enter the number 10. So I kind of pull out some bigger guns to handle this. A nice thing about the big guns is that they don't require a sentinel value. The user can just press Enter.
The code below uses a C-array like you, and it is a lot more tedious because of it. std::vectors know their size, and you can just add elements to it. With a C-array, you have to track the size separately, make sure it's always correct, etc. I lose the ability to use range-based for loops since the array may be only partially utilized.
#include <algorithm> // std::min_element() & std::max_element
#include <iostream>
#include <iterator>
#include <random>
#include <string>
int main() {
constexpr int capacity = 10;
int numbers[capacity];
int size = 0;
std::string tmp;
while (size < capacity && std::getline(std::cin, tmp)) {
if (tmp == "" && size >= 5) {
break;
}
if (tmp == "" && size < 5) {
std::cerr << "Need at least 5 elements.\n";
continue;
}
std::size_t pos;
int num;
try {
num = std::stoi(tmp, &pos);
} catch (...) {
std::cerr << "Exception thrown.\n";
continue;
}
if (pos != tmp.length()) {
std::cerr << "Bad Value.\n";
continue;
}
if (num >= 0 && num <= 10) {
numbers[size] = num;
++size;
}
}
// Find minimum and maximum, the easy way
auto min = std::min_element(std::begin(numbers), std::begin(numbers) + size);
auto max = std::max_element(std::begin(numbers), std::begin(numbers) + size);
// Find minimum and maximum, the hard way
int minIdx = 0;
int maxIdx = 0;
for (int i = 0; i < size; ++i) {
if (numbers[i] < numbers[minIdx]) minIdx = i;
if (numbers[i] > numbers[maxIdx]) maxIdx = i;
}
// Print all numbers to verify
for (int i = 0; i < size; ++i) {
std::cout << numbers[i] << ' ';
}
// This print goes with the std::min_element approach
std::cout << "\nMin: " << *min << "\nMax: " << *max << '\n';
// This print goes with the for loop approach
std::cout << "\nMin: " << numbers[minIdx] << "\nMax: " << numbers[maxIdx]
<< '\n';
}
You can tell how much extra work is required just for basic ASCII input. If you make some assumptions, a lot of the code can be cut out, but where user input is concerned, those assumptions are rarely safe, and are more of a convenience for quick testing or learning purposes.

Check for multiplicity 3

I have a little problem with check for multiplicity for 3. It says that my arr must be integer, but in objective I need to have a float massive. How to make this check "arr[i] % 3 == 0" for float numbers.
thanks.
#include <iostream>
#include <cmath>
using namespace std;
float minElement(float arr[], int length) {
float minElement = arr[0];
for (int i = 0; i < length; i++)
{
if (minElement > arr[i])
minElement = arr[i];
}
return minElement;
}
float multiplyArr(float arr[], int length) {
float multiply = 1;
for (int i = 0; i < length; i++)
{
if (arr[i] != 0 && arr[i] % 3 == 0)
multiply *= arr[i];
}
return multiply;
}
int main()
{
float length;
cout << "Enter integer value: ";
cin >> length;
float* p_darr = new float[length];
cout << "Enter values: " << endl;
for (int i = 0; i < length; i++) {
cin >> p_darr[i];
}
cout << "Max. element: " << minElement(p_darr, length) << endl;
cout << "Multiply: " << multiplyArr(p_darr, length) << endl;
delete[] p_darr;
return 0;
}
Assuming
float massive
to mean "large value". You cannot perform this operation, as it would be meaningless. Comments (and other answers) will suggest fmod. I'll advise against.
If I give you the value 3.6x10^12 and ask you what's the remainder after division by 3, you can't give me a meaningful answer.
3600000000000 % 3 is 0. 3600000000001 % 1 is 1. 3600000000002 % 2 is 2.
But all three values are 3.6x10^12.
If you need integer modulo values, it typically means you need integer precision. Float values won't offer it.
Rather, you should read your input as a string, parse it character by character, and compute the modulo so far. This is a typical first assignment in a computer theory class (as I used to TA).

C++ Vector Subscript Issues

I was making an app that calculates the mean, median, and range of any integers, but I ran into the issue: Vector subscript out of range. I've looked at some other posts about this, and still haven't been able to fix it.
Here's my code:
#include <iostream>
#include <Algorithm>
#include <Windows.h>
#include <vector>
using namespace std;
int main() {
//Variables
int sze;
int mraw = 0;
double mean;
double median;
double range;
int fullnum = 0;
int lastnum = 1;
vector<int> med;
cout << "How many numbers do you have? ";
cin >> sze;
int *arr = new int[sze];
for (int i = 0; i < sze; i++) {
med.push_back(arr[i]);
}
//Getting numbers
for (int i = 0; i < sze, i++;) {
system("cls");
cout << "Enter number #" << i + 1 << ": ";
cin >> arr[i];
}
//Mean
for (int i = 0; i < sze; i++){
fullnum += arr[i];
}
mean = fullnum / sze;
//Median
sort(med.begin(), med.end());
int mvs = sze;
while (med.size() >= 2) {
med.erase(med.begin());
med.erase(med.begin() + med.size() - 1);
mvs--;
}
if (mvs == 2) {
mraw = med[1] + med[2];
median = mraw / 2;
}
else {
median = mvs;
}
//Range
vector<int> rnge;
for (int i = 0; i < sze; i++) {
rnge.push_back(arr[i]);
lastnum++;
}
sort(rnge.begin(), rnge.end());
int bigsmall[2];
bigsmall[1] = rnge[1];
bigsmall[2] = rnge[lastnum];
range = bigsmall[2] - bigsmall[1];
//Outputs
cout << "Mean: " << mean << "\nMedian: " << median << "\nRange: " << range;
system("cls");
return 0;
}
You have what would be an off-by-one error if lastnum was initialized to 0.
When rnge is empty, presumably lastnum is 0. This means access rnge[lastnum] is in error, as rnge is empty.
Applying an inductive argument shows that lastnum is the count of number of elements, and not the index of the last element. Thus, rnge[lastnum] is always out of range.
In actuality, you have initialized lastnum to 1, so your bug is actually off-by-two.

C++ max of an array using recursion issue

I have this program that finds the largest integer in an array using recursion, but it keeps returning the last number entered no matter what the value instead of the largest number. How do i fix this?
#include <iostream>
using namespace std;
int maximum(int digits[], int size, int largest, int i);
void main()
{
const int size = 3;
int digits[size];
int n = 0, x = 0;
for(int a = 0; a < size; a++)
{
cout << "Enter an integer <" << ++x << " out of " << size << ">: ";
cin >> digits[n];
}
cout << "\nThe largest digit is, " << maximum(digits, size, 0, 0) << ", thank you!\n";
cout << endl;
}
int maximum(int digits[], int size, int largest, int i)
{
if ( i < size )
{
if ( largest < digits[i])
largest = digits[i];
maximum( digits, size, largest, i + 1);
}
return largest;
}
First use the index variable properly in main()
for(int a = 0; a < size; a++)
{
cout << "Enter an integer <" << ++x << " out of " << size << ">: ";
cin >> digits[a];//-->Use the index varible correctly.
}
int maximum(int digits[], int size, int largest, int i)
{
if(i==size-1)
return digits[i]; //The base case is specified here.
if ( i < size )
{
int temp= maximum( digits, size, largest, i + 1);
if ( digits[i] < temp)
largest =temp;
else
largest=digits[i];
}
return largest;
}
Please check out the changes. Carefully read the code. You will understand your mistakes.
When designing recursion think of few things first-
The base condition. (This stops the recursion).
The recursive step. (Where you will calculate something based on previous calculation)
Combine step- You have to combine them (value at this stage and value got from recusive step) to get the correct answer. This step is not required in some cases.
It should be return maximum( digits, size, largest, i + 1);
Live example.
int biggestOne(int integerArray[], int lengthOfArray, int max)
{
if (lengthOfArray==0) return max;
if (max < integerArray[lengthOfArray-1]) max = integerArray[lengthOfArray-1];
return biggestOne(integerArray,lengthOfArray-1,max);
}
int main()
{
int array[] = {7,2,9,10,1};
int arrSize = sizeof(array)/sizeof(array[0]); //returns length of the array
cout <<"Biggest number in the array: " << biggestOne(array,arrSize,0) << endl;
return 0;
}