Better way to use a pointer? - c++

I'm trying to create a program that will display bar graphs with * the maximum number of * can be 40. I have everything working but had a question with the code. Is there a better way as you can see I have to go back to the original address twice using:
p_bar_length = p_bar_length - size;
Is there a better way to do this?
#include <iostream>
using namespace std;
const int MAX_SPLATS = 40;
void bar_chart(double values[], int size)
{
double largest = values[0]; //assign first element to be the largest
//Find the largest value
for (int i = 1; i < size; i++)
{
if (largest < values[i]) // check to see if there is something larger
{
largest = values[i];
}
}
// Find the number of spalts to use
// with the precent based on the largest value
int* p_bar_length = new (nothrow) int[size];
for (int i = 0; i < size; i++)
{
*p_bar_length = (values[i] / largest) * MAX_SPLATS;
p_bar_length++; // Go to next memory address
}
// Go back to the orignal memory address
p_bar_length = p_bar_length - size;
// Pritnt the correct number of splats
for (int i = 0; i < size; i++)
{
for (int j = 0; j < *p_bar_length; j++)
{
cout << "*";
}
p_bar_length++;
cout << endl;
}
// Go back to the orignal memory address
p_bar_length = p_bar_length - size;
delete[] p_bar_length;
}
int main()
{
double values[6] = { 22, 40, 28, 26, 14, 46};
int val_size = 6;
bar_chart(values, val_size);
system("pause");
return 0;
}

Since this is C++, the best way is not to use pointers; instead, use a std::vector.
That said, you can also always treat a pointer as an array and just access p_bar_length[i] for a given position 0 <= i < length instead of incrementing the pointer.

Rather than incrementing the pointer, use the array index:
p_bar_length[i] = (values[i] / largest) * MAX_SPLATS;
or use pointer arithmetic:
*(p_bar_length + i) = (values[i] / largest) * MAX_SPLATS;

You do not need the first for loop if you use std::max_element from <algorithm>.
You do not need the second for loop if you calculate the bar length in the third for loop.
Something like this:
void bar_chart(double values[], int size)
{
//Find the largest value
double largest = *std::max_element(values, values + size);
// Print the correct number of splats
for (int i = 0; i < size; i++)
{
int p_bar_length = (values[i] / largest) * MAX_SPLATS;
cout << string(p_bar_length, '*') << endl;
}
}
That way you don't need the p_bar_length array at all. It is only a simple int.
Edit: And you could even replace the inner for loop (example modified)

Since you tagged this as C++ I would recommend using the standard library.
Your program is more C than C++, but if c is ok for you there is not much to improve.
On the other hand, using vector and algorithm you don't need to mess around with pointers. And using C++11 it removes the rough edges previously associated with templates and iterators.
A quick shot:
#include <iostream>
#include <vector>
#include <algorithm>
const int MAX_SPLATS = 40;
template <typename C>
void bar_chart(const C& values)
{
if (std::distance(values.begin(), values.end())<1)
return; // do some error handling
auto largest = *std::max_element(values.begin(), values.end());
// Find the number of splats to use with the percent based on
// the largest value
std::vector<int> bars(values.size());
std::transform(values.begin(), values.end(), bars.begin(),
[=] (double d) { return (d/largest)*MAX_SPLATS; });
// Print the correct number of splats
std::for_each(bars.begin(), bars.end(),
[](int val){ std::cout << std::string(val, '*') << std::endl; });
}
int main()
{
std::vector<double> values = { 22, 40, 28, 26, 14, 46 };
bar_chart(values);
std::cin.get();
return 0;
}

Make another copy of the pointer to use within your loop. Much less error prone.
int* p_bar_length = new (nothrow) int[size];
int* p = p_bar_length;
for (int i = 0; i < size; i++)
{
*p = (values[i] / largest) * MAX_SPLATS;
p++; // Go to next memory address
}
P.S. Why are you using nothrow? Since you're not checking the value you get back from new, an exception will be much nicer than the mess you'll have when you get back a NULL pointer.

You could treat p_bar_length as an array and just use consistent notation
int* p_bar_length = new (nothrow) int[size];
for (int i = 0; i < size; i++)
{
p_bar_length[i] = (values[i] / largest) * MAX_SPLATS;
}

How about two in one?
int* p_bar_length = new (nothrow) int[size];
for (int i = 0; i < size; i++)
{
*p_bar_length = (values[i] / largest) * MAX_SPLATS;
for (int j = 0; j < *p_bar_length; j++) cout << "*";
cout << endl;
p_bar_length++; // Go to next memory address
}

This is rather similar to the post from #mkaes, but goes one step further. Instead of using std::transform to create a vector of the proper lengths, then std::for_each to create a string the proper length from each of those, this creates a string directly from the input, and writes the strings directly from std::transform:
#include <iostream>
#include <array>
#include <algorithm>
#include <string>
#include <iterator>
const int MAX_SPLATS = 40;
template <typename C>
void bar_chart(const C& values)
{
if (std::distance(values.begin(), values.end())<1)
return; // do some error handling
auto largest = *std::max_element(values.begin(), values.end());
std::transform(values.begin(), values.end(),
std::ostream_iterator<std::string>(std::cout, "\n"),
[=](double d) { return std::string((d/largest)*MAX_SPLATS, '*');} );
}
int main() {
std::array<double, 6> values = {22, 40, 28, 26, 14, 46};
bar_chart(values);
return 0;
}
Since it's using C++11 anyway, I decided to also use an std::array since it seems to fit nicely for the job at hand.

Related

Swap array elements depending on function (given as argument) return

I have a problem with function that takes: array, size of that array and function (or lambda), and then sort given array depending of what function given in argument returns. For example:
int a1[] = {1,2,3,4,5,6};
part(a1,6,isEven); // where isEven is simple function for checking if element is even
Should return:
[ 2 4 6 1 5 3 ]
I already write this like that, where im retur new, sorted array:
template <typename T, typename FUN>
size_t part(T* arr, size_t size, FUN f) {
T new_arr[size] = {};
int first = 0;
int last = size - 1;
int index = 0;
bool changed = false;
for(int i = 0; i < size; i++){
if(f(arr[i])){
new_arr[first] = arr[i];
first++;
} else {
if(!changed){index = i;}
new_arr[last] = arr[i];
last--;
}
}
for(int j = 0; j < size; j++){
std::cout << new_arr[j] << " ";
}
return new_arr;
}
But I have to do this without using any other array. And it has to be done in one loop.
You were nearly there.
You must not use an additional array. But in line T new_arr[size] = {}; you try to do this. And, this will not work, because this is a VLA (Variable Lenth Array). VLAs are not part of the C++ language. Some compilers accept VLAs as extension, but, if you tell them to compile C++, then also those will reject it. In C++ the size of an array must be known at compile time. It must be a constant.
So, since you anyway work with pointers, you can also use new to allocate temporary memory. Then simply replace the above line with T* new_arr = new T[size]{};
And, you must not forget to delete the allocated memory. Or, you could copy the new data at the end of the function to the original and then delete the temporaray memory there.
So, in my opinion not the best approach. Anyway, the C++ standard library has the functions partition and stable_partition.
Anyway. Please see below:
#include <iostream>
#include <algorithm>
template <typename T, typename FUN>
T* part(T* arr, size_t size, FUN f) {
T* new_arr = new T[size]{};
int first = 0;
int last = size - 1;
int index = 0;
bool changed = false;
for (int i = 0; i < size; i++) {
if (f(arr[i])) {
new_arr[first] = arr[i];
first++;
}
else {
if (!changed) { index = i; }
new_arr[last] = arr[i];
last--;
}
}
return new_arr;
}
int main() {
int data[]{ 1,2,3,4,5,6 };
int *p = part(data, (sizeof(data) / sizeof(data[0])), [](const int i) {return i % 2 == 0; });
for (int i = 0; i < (sizeof(data) / sizeof(data[0])); ++i)
std::cout << p[i] << ' ';
delete[]p;
}

How to find the minimun of an array?

I was trying to solve this question
but codechef.com says the answer is wrong.
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
int t, n, diff, mindiff;
cin >> t;
cin >> n;
int val[n];
while(t--)
{
mindiff = 1000000000;
for(int i = 0; i<n; i++)
{
cin >> val[i];
}
int a = 0;
for(a = 0; a<n ; a++)
{
for(int b=a+1; b<n ; b++)
{
diff = abs(val[a] - val[b]);
if(diff <= mindiff)
{
mindiff = diff;
}
}
}
cout << mindiff << endl;
}
return 0;
}
The results are as expected (for at least the tests I did) buts the website says its wrong.
There are a few things in your code that you should change:
Use std::vector<int> and not variable-length arrays (VLA's):
Reasons:
Variable length arrays are not standard C++. A std::vector is standard C++.
Variable length arrays may exhaust stack memory if the number of entries is large. A std::vector gets its memory from the heap, not the stack.
Variable length arrays suffer from the same problem as regular arrays -- going beyond the bounds of the array leads to undefined
behavior. A std::array has an at() function that can check boundary access when desired.
Use the maximum int to get the maximum integer value.
Instead of
mindif = 1000000000;
it should be:
#include <climits>
//...
int mindiff = std::numeric_limits<int>::max();
As to the solution you chose, the comments in the main section about the nested loop should be addressed.
Instead of a nested for loop, you should sort the data first. Thus finding the minimum value between two values is much easier and with less time complexity.
The program can look something like this (using the data provided at the link):
#include <iostream>
#include <vector>
#include <climits>
#include <algorithm>
int main()
{
int n = 5;
std::vector<int> val = {4, 9, 1, 32, 13};
int mindiff = std::numeric_limits<int>::max();
std::sort(val.begin(), val.end());
for(int a = 0; a < n-1 ; a++)
mindiff = std::min(val[a+1] - val[a], mindiff);
std::cout << mindiff;
}
Output:
3
To do this you can use a simple for():
// you already have an array called "arr" which contains some numbers.
int biggestNumber = 0;
for (int i = 0; i < arr.size(); i++) {
if (arr[i] > biggestNumber) {
biggestNumber = arr[i];
}
}
arr.size will get the array's length so that you can check every value from the position 0 to the last one which is arr.size() - 1 (because arrays are 0 based in c++).
Hope this helps.

How do I delete a particular element in an integer array given an if condition?

I'm trying to delete all elements of an array that match a particular case.
for example..
if(ar[i]==0)
delete all elements which are 0 in the array
print out the number of elements of the remaining array after deletion
what i tried:
if (ar[i]==0)
{
x++;
}
b=N-x;
cout<<b<<endl;
this works only if i want to delete a single element every time and i can't figure out how to delete in my required case.
Im assuming that i need to traverse the array and select All instances of the element found and delete All instances of occurrences.
Instead of incrementing the 'x' variable only once for one occurence, is it possible to increment it a certain number of times for a certain number of occurrences?
edit(someone requested that i paste all of my code):
int N;
cin>>N;
int ar[N];
int i=0;
while (i<N) {
cin>>ar[i];
i++;
}//array was created and we looped through the array, inputting each element.
int a=0;
int b=N;
cout<<b; //this is for the first case (no element is deleted)
int x=0;
i=0; //now we need to subtract every other element from the array from this selected element.
while (i<N) {
if (a>ar[i]) { //we selected the smallest element.
a=ar[i];
}
i=0;
while (i<N) {
ar[i]=ar[i]-a;
i++;
//this is applied to every single element.
}
if (ar[i]==0) //in this particular case, we need to delete the ith element. fix this step.
{
x++;
}
b=N-x;
cout<<b<<endl;
i++;
}
return 0; }
the entire question is found here:
Cut-the-sticks
You could use the std::remove function.
I was going to write out an example to go with the link, but the example form the link is pretty much verbatim what I was going to post, so here's the example from the link:
// remove algorithm example
#include <iostream> // std::cout
#include <algorithm> // std::remove
int main () {
int myints[] = {10,20,30,30,20,10,10,20}; // 10 20 30 30 20 10 10 20
// bounds of range:
int* pbegin = myints; // ^
int* pend = myints+sizeof(myints)/sizeof(int); // ^ ^
pend = std::remove (pbegin, pend, 20); // 10 30 30 10 10 ? ? ?
// ^ ^
std::cout << "range contains:";
for (int* p=pbegin; p!=pend; ++p)
std::cout << ' ' << *p;
std::cout << '\n';
return 0;
}
Strictly speaking, the posted example code could be optimized to not need the pointers (especially if you're using any standard container types like a std::vector), and there's also the std::remove_if function which allows for additional parameters to be passed for more complex predicate logic.
To that however, you made mention of the Cut the sticks challenge, which I don't believe you actually need to make use of any remove functions (beyond normal container/array remove functionality). Instead, you could use something like the following code to 'cut' and 'remove' according to the conditions set in the challenge (i.e. cut X from stick, then remove if < 0 and print how many cuts made on each pass):
#include <iostream>
#include <vector>
int main () {
// this is just here to push some numbers on the vector (non-C++11)
int arr[] = {10,20,30,30,20,10,10,20}; // 8 entries
int arsz = sizeof(arr) / sizeof(int);
std::vector<int> vals;
for (int i = 0; i < arsz; ++i) { vals.push_back(arr[i]); }
std::vector<int>::iterator beg = vals.begin();
unsigned int cut_len = 2;
unsigned int cut = 0;
std::cout << cut_len << std::endl;
while (vals.size() > 0) {
cut = 0;
beg = vals.begin();
while (beg != vals.end()) {
*beg -= cut_len;
if (*beg <= 0) {
vals.erase(beg--);
++cut;
}
++beg;
}
std::cout << cut << std::endl;
}
return 0;
}
Hope that can help.
If you have no space bound try something like that,
lets array is A and number is number.
create a new array B
traverse full A and add element A[i] to B[j] only if A[i] != number
assign B to A
Now A have no number element and valid size is j.
Check this:
#define N 5
int main()
{
int ar[N] = {0,1,2,1,0};
int tar[N];
int keyEle = 0;
int newN = 0;
for(int i=0;i<N;i++){
if (ar[i] != keyEle) {
tar[newN] = ar[i];
newN++;
}
}
cout<<"Elements after deleteing key element 0: ";
for(int i=0;i<newN;i++){
ar[i] = tar[i];
cout << ar[i]<<"\t" ;
}
}
Unless there is a need to use ordinary int arrays, I'd suggest using either a std::vector or std::array, then using std::remove_if. See similar.
untested example (with c++11 lambda):
#include <algorithm>
#include <vector>
// ...
std::vector<int> arr;
// populate array somehow
arr.erase(
std::remove_if(arr.begin(), arr.end()
,[](int x){ return (x == 0); } )
, arr.end());
Solution to Cut the sticks problem:
#include <climits>
#include <iostream>
#include <vector>
using namespace std;
// Cuts the sticks by size of stick with minimum length.
void cut(vector<int> &arr) {
// Calculate length of smallest stick.
int min_length = INT_MAX;
for (size_t i = 0; i < arr.size(); i++)
{
if (min_length > arr[i])
min_length = arr[i];
}
// source_i: Index of stick in existing vector.
// target_i: Index of same stick in new vector.
size_t target_i = 0;
for (size_t source_i = 0; source_i < arr.size(); source_i++)
{
arr[source_i] -= min_length;
if (arr[source_i] > 0)
arr[target_i++] = arr[source_i];
}
// Remove superfluous elements from the vector.
arr.resize(target_i);
}
int main() {
// Read the input.
int n;
cin >> n;
vector<int> arr(n);
for (int arr_i = 0; arr_i < n; arr_i++) {
cin >> arr[arr_i];
}
// Loop until vector is non-empty.
do {
cout << arr.size() << endl;
cut(arr);
} while (!arr.empty());
return 0;
}
With a single loop:
if(condition)
{
for(loop through array)
{
if(array[i] == 0)
{
array[i] = array[i+1]; // Check if array[i+1] is not 0
print (array[i]);
}
else
{
print (array[i]);
}
}
}

How to Delete all the element which are at some index of first array and the index is taken from second array?

I want to Write a function which takes 2 arrays-
One array is the source array and the other array is the array of indices.
I want to delete all those elements present at the indices of the source array taking the indices from the second array.
Suppose First array is : {12,5,10,7,4,1,9} and index array is : {2,3,5}.
Then the elements at index 2,3,5. i.e. 10, 7 and 1 are deleted from first array.
So first array becomes : {12,5,4,9}.
If the indices array is sorted,then my O(N) solution is:
#include<iostream>
using namespace std;
int main()
{
int arr[]={12,5,10,7,4,1,9},n=7,indices[]={2,3,5},m=3;
int j=0,k=0;
for(int i=0;i<n,k<m;i++)
{
if(i!=indices[k])
arr[j++]=arr[i];
else
k++;
}
for(i=0; i<j; i++)
cout<<arr[i]<<" ";
return 0;
}
How to do it in O(n) if the indices array is not sorted ?
According to the comments:
Is there any value that will never appear in arr but is representable by int?
You can take that as int max.
Now you can use removeIndices
#include<iostream>
#include<limits>
int removeIndices(int* arr, int n, int* indices, int m){
const int NEVER_IN_ARRAY = std::numeric_limits<int>::max();
for(int i = 0; i < m; i++)
arr[indices[i]] = NEVER_IN_ARRAY;
for(int from = 0, to = 0; from < n; from++)
if(arr[from] != NEVER_IN_ARRAY)
arr[to++] = arr[from];
return n - m;
}
int main(){
int arr[] = {12, 5, 10, 7, 4, 1, 9}, n = 7, indices[] = {2, 3, 5}, m = 3;
int newSize = removeIndices(arr, n, indices, m);
for(int i = 0; i < newSize; i++)
std::cout << arr[i] << " ";
return 0;
}
Edit: With
#include<algorithm>
#include<functional>
We can do:
int removeIndices(int* arr, int n, int* indices, int m){
const int NEVER_IN_ARRAY = std::numeric_limits<int>::max();
std::for_each(indices, indices + m, [arr](int index){ arr[index] = NEVER_IN_ARRAY; });
int* p = std::remove_if(arr, arr + n, std::bind2nd(std::equal_to<int>(), NEVER_IN_ARRAY));
return p - arr;
}
loop thru filter array and mark dead elements with tombstones
create a new array, and copy step-by-step while skipping tombstones
if it's possible use a tombstone value, for example if it is guranteed that -1 doesn't appear in the input then -1 can be the tombstone value
if this is not possible use an array of boolean markers, init them to false
in-place filtering after marking:
for(int i=0,j=0;j<n;i++,j++){
if( a[j] == TOMBSTONE ){
i--; // the loop will add +1
continue;
}
if(i==j)
continue; // skip, no need to write
arr[i]=arr[j];
}
arr input length: n
arr new length: i
May be you want something like this:
#include<iostream>
#define INVALID 99999 //to mark the elements who will disappear
using namespace std;
int main()
{
int arr[] = {0,1,2,3,4,5,6,7,8,9,10};
int indices = {3,1,5};
int indices_len = 3;
int arr_len = 3;
for(int i=0; i<indices_len; i++){
arr[indices[i]] = INVALID;
}
int invalid_count=0;
for(int i=0; i<arr_len; i++){
if(arr[i] == INVALID){
invalid_count++;
}
arr[i-invalid_count] = arr[i];
}
return 0;
}
You must add the result to a new array 1-just iterate over all all elements if the index is in the to delete array continue else copy it to the new array, you can look at the CArray class from MFC it has RemoveAt method
PseudoCode
int old_arr[MAX_SIZE], new_arr[MAX_SIZE];
bool to_del[MAX_SIZE] = {0};
int index_to_del[MAX_SIZE];
for (size_t i = 0; i < MAX_SIZE; ++i)
to_del[index_to_del[i]] = true;
size_t new_size = 0;
for (size_t i = 0; i < MAX_SIZE; ++i)
if (!to_del[i])
new_arr[new_size++] = old_arr[i];
Edit
The above snippet consumes extra space.
If we had to do it in-place, then every time, we delete an element we will have to shift all consecutive elements by 1. In worst case, this could be O(n**2). If you want to do it in-place without yourself copying array elements, you could use vector.
If deletes outnumber reads, then consider using multiset
Here is a solution that does it in-place, does not allocate memory on the heap, does not require flag values, and does it in O(N+M) time:
#include <cstddef>
template<std::size_t N>
std::size_t removeIndices( int(&src)[N], std::size_t srcSize, int const* removal, std::size_t removeSize )
{
bool remove_flags[N] = {false};
for( int const* it = removal; it != removal+removeSize; ++it ) {
remove_flags[*it] = true;
}
int numberKept = 0;
for( int i = 0; i < srcSize; ++i ) {
if( !remove_flags[i] ) {
if (numberKept != i)
src[numberKept] = src[i];
++numberKept;
}
}
return numberKept;
}
Note that it needs full access to the source array, because I create a temporary stack buffer of bool that is the same size. In C++1y, you'll be able to do this without that compile time knowledge using variable length arrays or similar types.
Note that some compilers implement VLAs via (hopefully partial) C99 compatibility already.

How to implement infinite multidimensional array?

I want to use the code below and I want to use it for "unknown size of input". For example there is an array int cac[1000][1000]. I can use vector<vector<int> > array;, then how can i initialize it with -1 ? Any suggestions?
#include <sstream>
#include <iostream>
#include <vector>
#include <cstdlib>
#include <memory.h>
using namespace std;
int cac[1000][1000];
string res[1000][1000];
vector<string> words;
int M;
int go(int a, int b){
if(cac[a][b]>= 0) return cac[a][b];
if(a == b) return 0;
int csum = -1;
for(int i=a; i<b; ++i){
csum += words[i].size() + 1;
}
if(csum <= M || a == b-1){
string sep = "";
for(int i=a; i<b; ++i){
res[a][b].append(sep);
res[a][b].append(words[i]);
sep = " ";
}
return cac[a][b] = (M-csum)*(M-csum);
}
int ret = 1000000000;
int best_sp = -1;
for(int sp=a+1; sp<b; ++sp){
int cur = go(a, sp) + go(sp,b);
if(cur <= ret){
ret = cur;
best_sp = sp;
}
}
res[a][b] = res[a][best_sp] + "\n" + res[best_sp][b];
return cac[a][b] = ret;
}
int main(int argc, char ** argv){
memset(cac, -1, sizeof(cac));
M = atoi(argv[1]);
string word;
while(cin >> word) words.push_back(word);
go(0, words.size());
cout << res[0][words.size()] << endl;
}
What you can do is to use a associative array, where the key is a pair (rowPosition, ColumnPosition). When you want to set array[i][j] you just add or update the value assoArray[Pair(i,j)]. You can assume that any element which is not in the associative array has the initial value.
In general infinite multidimensional arrays are used for theoretical purpose.I hope i didn't misunderstood the question.
Using std::vector from the STL is much more straightforward than the following solution, which was pointed out in the comments for this post. I find that this site explains that topic effectively: http://www.learncpp.com/cpp-programming/16-2-stl-containers-overview/
An array of infinite size is not actually possible. However, you can achieve basically that effect using dynamic allocation. Here's some sample code:
int counter = 0;
int* myArray = new int[1000];
Fill the array with data, incrementing counter each time you add a value. When counter reaches 1000, do the following:
int* largerArray = new int[2000];
for( int i = 0; i < 1000; i++ )
{
largerArray[i] = myArray[i];
}
delete[] myArray;
myArray = largerArray;
With this method, you create the closest thing possible to an infinitely sized array, and I don't believe performance will be an issue with the copy piece