This code is for a CS 235 class, but I'm new to C++ and I have no clue how they want me to do this. The grow function works by taking in an array and changing it to become twice as large. Coming from python, I guess this is the equivalent of mutating the array?
Anyway, I can't get it do the same for the insert function. I need it to check if the position that we're trying to insert an item at is outside the array bounds and make the array big enough that it can insert the value. Everything works....inside the function. The array does not maintain the changes outside the function. I've tried passing it in as a pointer, as a (reference to a pointer?) like *&array, and basically any combination I can think of.
void grow(int *&original_array, unsigned int & capacity){
int *temp = new int[capacity * 2];
for (int i=0; i<capacity*2; i++){
temp[i] = 0;
}
std::cout << "line 18: ";
print_array(temp, capacity*2);
for(int i=0; i<capacity; i++){
temp[i] = original_array[i];
}
std::cout << "line 23: ";
print_array(temp, capacity*2);
// delete[] original_array;
original_array = temp;
std::cout << "line 27: ";
print_array(original_array, capacity * 2);
capacity = capacity * 2;
}
bool insert (int array[], unsigned int & maxSize, unsigned int & nFilled, unsigned int pos, int value){
while (maxSize < pos){
grow(array, maxSize);
print_array(array, maxSize);
}
for(unsigned int i = nFilled - 1; i >= pos; i = i-1){
array[i+1] = array[i];
}
array[pos] = value;
print_array(array, maxSize);
return true;
}
Here's some sample input and what my program outputs right now:
int main() {
unsigned int my_size = 4;
int new_array[4] = {1,2,3,4};
unsigned int nFilled = 4;
insert(new_array, my_size, nFilled, 5, 15);
print_array(new_array, my_size);
return 0;
}
Output:
line 18: {0, 0, 0, 0, 0, 0, 0, 0}
line 23: {1, 2, 3, 4, 0, 0, 0, 0}
line 27: {1, 2, 3, 4, 0, 0, 0, 0}
{1, 2, 3, 4, 0, 0, 0, 0}
{1, 2, 3, 4, 0, 15, 0, 0}
{1, 2, 3, 4, -152629248, 32758, 0, 8}
the second to last line is inside the function and the last one is outside the function. I need these to be the same
Any help is appreciated - the TA's and professors are being unhelpful
Thanks
There's two problems with your code working as written, the first one is that you can't reassign the value of new_array in main as written. As written it is not dynamically allocated, and so it cannot be changed. You will need to change that to be dynamically allocated:
int* new_array = new int[4];
for(int x = 0; x < 4; ++x)
{
new_array[x] = x + 1;
}
That will address one issue, however the code still won't work, and that has to do with how variables are passed to insert and grow.
Your grow() function takes int*& a reference to a pointer to integer. This means that the underlying value passed in can be changed. However, your insert() function takes int[] an integer array that decays to to pointer to integer, and changes here will not be reflected at the call site of insert().
You can verify that by adding some more debugging statements:
bool insert (int array[],
unsigned int & maxSize,
unsigned int & nFilled,
unsigned int pos,
int value)
{
// unchanged above...
std::cout << "Inside insert: " << array << '\n';
return true;
}
int main()
{
// unchanged above...
std::cout << "After insert: " << new_array << "\n";
print_array(new_array, my_size);
return 0;
}
You will get output similar to this:
line 18: {0 0 0 0 0 0 0 0 }
line 23: {1 2 3 4 0 0 0 0 }
line 27: {1 2 3 4 0 0 0 0 }
{1 2 3 4 0 0 0 0 }
{1 2 3 4 0 15 0 0 }
Inside insert: 0x548ed0
After insert: 0x548eb0
{1 2 3 4 0 0 49 0 }
Note that the array "Inside insert" and "After insert" are different.
To fix this, you need to make sure you pass something to insert() that allows for changing the value, similar to what was done for grow().
That change is as simple as changing the signature of insert() as follows:
bool insert (int *&array,
unsigned int & maxSize,
unsigned int & nFilled,
unsigned int pos,
int value)
Note the first parameter to insert() was changed to match the type in grow() a reference to pointer to integer. Now when we pass the pointer new_array to insert() a reference to that pointer is passed (which allows the value to be changed), and that is also passed to grow() (if necessary), allowing this to propagate all the way to the call site.
Be aware though there are stylistic problems with this approach -- unclear ownership semantics, potential for memory leaks (present in the posted code) etc.
I will also caveat that "reinventing" this type of data structure instead of using std::vector is not a good practice, however it does have its uses in a teaching context.
Related
For my 2d array in C++, the 2d array needs to be flipped at a certain position. I have to write a function that flips the array
Foe instance,
Before:
double A[][2] = {{0,0}, {1,1}, {2,2}, {3,3}, {4,4}, {5,5}, {6,6}, {7,7}}
A B C D
call function invert(or flip): invert(A, 8, 3, 4);
after:
double A[][2] = { {0, 0}, {1, 1}, {2, 2},{6, 6}, {5, 5}, {4, 4}, {3, 3}, {7, 7}}
D C B A
Here is the attempt I have tried
#param A is the list of locations (x,y) of the cities in the current tour.
#param n is the number of cities in A.
#param start is the index of the beginning of the section to be inverted.
#param len is the length of the segment to invert(or flip).
void invert ( double A[][2], int n, int start, int len ) {
int(*tmp)[2] = new int[][2];
for(int i = 0; i >= A.length; i--){
for(int j = 0; j >= A[i].length; j--){
if( i > start)
tmp = A[i][j];
}
}
for(i = start; i < A.length; i++)
for(j = start; j < A[i].length; j++){
while (i <= end){
tmp = A[i][j];
}
}
}
The errors I have are
expressions must have class type
a value of type double cannot be assigned to an entity of type "double(*)[2]
cannot determine which instance of overload function "end" is intended
I am fully aware that most of the errors in my code are evident to find, but I needed to start somewhere.
I admit, I don't know how to do it with a 2D C-array. I can only tell you about the simple way to do it.
First, a general advice: Name your stuff. What if I had to read only your code to see that you are dealing with locations of cities, that have x and y coordinates, instead of having to read your text, wouldn't that be great?
Next, for resizable arrays, you can (/should) use std::vector instead of C-arrays. C-arrays decay to pointers when passed to functions. C-arrays have their size as part of their type, but it is inconvenient to access it (and impossible once decayed to a pointer). And manually resizing dynamic C-arrays isn't much fun either.
Eventually, the "simple way" is to use an existing algorithm. To reverse elements in a range it is std::reverse:
#include <iostream>
#include <vector>
#include <algorithm>
struct location {
int x;
int y;
};
int main() {
std::vector<location> cities{{0,0}, {1,1}, {2,2}, {3,3}, {4,4}, {5,5}, {6,6}, {7,7}};
for (const auto& loc : cities){
std::cout << loc.x << " " << loc.y << "\n";
}
std::cout << "\n";
std::reverse(cities.begin()+ 3,cities.begin() + 7);
for (const auto& loc : cities){
std::cout << loc.x << " " << loc.y << "\n";
}
}
Output:
0 0
1 1
2 2
3 3
4 4
5 5
6 6
7 7
0 0
1 1
2 2
6 6
5 5
4 4
3 3
7 7
Actually with a 1-D c-array it is almost the same. The major difference is that c-arrays do not have begin as member. This produces same output as above:
location cities2[] = {{0,0}, {1,1}, {2,2}, {3,3}, {4,4}, {5,5}, {6,6}, {7,7}};
for (const auto& loc : cities2){
std::cout << loc.x << " " << loc.y << "\n";
}
std::cout << "\n";
std::reverse(std::begin(cities2)+ 3,std::begin(cities2) + 7);
for (const auto& loc : cities2){
std::cout << loc.x << " " << loc.y << "\n";
}
And if you want to wrap it in a function you need to take care of the array decaying to a pointer:
void my_reverse(location* loc, size_t len, size_t first, size_t last){
std::reverse(loc + first, loc + last + 1);
}
(I choose last to be the last element to be reversed. Note that the algorithm takes an iterator to the element one past the last element to be reversed).
Complete example with all three variants: https://godbolt.org/z/WMdea7WP3
That's how I'd write the function if I knew it would always be used with 2 column arrays
void invert(double cities[][2], int size, int start, int len) {
if (size < 0 || len < 0)
return;
double tempCoordsX, tempCoordsY;
int endPos = start + len - 1;
for (int i = start; i < (start + len/2); i++) {
int mirroredPos = (endPos - (i - start)) % size;
tempCoordsX = cities[i][0];
tempCoordsY = cities[i][1];
cities[i][0] = cities[mirroredPos][0];
cities[i][1] = cities[mirroredPos][1];
cities[mirroredPos][0] = tempCoordsX;
cities[mirroredPos][1] = tempCoordsY;
}
}
I repeat: please name your stuff
I have known java for a while and I was trying to translate a java program i wrote to c++ but the copy function gives an odd result:
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
long gcd2(long a, long b) {
if ( a == 0 )
return b;
return gcd2(b%a,a);
}
long gcd(long nums[]) {
long ans = nums[0];
int len = sizeof(nums);
for (int i = 1; i < len; i++)
ans = gcd2( nums[i] , ans );
return ans;
}
string com(string s) {
s = s+",";
return (","+s);
}
void printa(long array[]) {
for (int i = 0 ; i < sizeof(array); i++)
cout << array[i] << ", ";
cout << "\n";
}
int main()
{
int length;
cin >> length;
long input[length];
for (int i = 0; i < length; i++)
cin >> input[i];
string possible = "";
int ans = 0;
for (int a = 0; a < length; a++) {
for (int b = length; b > a; b--) {
long arr[b-a];
std::copy(input+a,input+b,arr);
printa(arr);
long gcdans = gcd(arr);
if (possible.find( com(gcdans+"") ) == -1 ) {
possible += com(gcdans+"");
ans++;
}
}
}
cout << (ans);
return 0;
}
I give it the input of:
4
9 6 2 4
and it returns:
9, 6, 2, 4, 140725969483488, 4197851, 9, 6,
9, 6, 2, 4197851, 9, 6, 2, 4,
9, 6, 2, 4197851, 9, 6, 2, 4,
9, 4197851, 9, 6, 2, 4, 140725969483488, 4197766,
6, 2, 4, 4197851, 9, 6, 2, 4,
6, 2, 4, 4197851, 9, 6, 2, 4,
6, 4197851, 9, 6, 2, 4, 140725969483488, 4197766,
2, 4, 6, 4197851, 9, 6, 2, 4,
2, 4197851, 9, 6, 2, 4, 140725969483488, 4197766,
4, 4197851, 9, 6, 2, 4, 140725969483488, 4197766,
1
the number at the very end is what i want the program to output at the end, all the numbers above are me test printing the array to see its contents. Basically I am trying to copy a range of the array(for example (2,3,4) from (1,2,3,4,5,6)) But it gives weird numbers like 140725969483488 and 4197766 when the only numbers I input are 9 6 2 4
Variable length arrays is a C++ extension, not standard C++. If your compiler will allow them, then OK. However standard C++ would use an std::vector container which is dynamically sized at runtime, meaning you can initialise them with any size or numbers at runtime, and add anything you want at runtime.
Also note when passing an array in C++ to functions which take an array argument always (with the exception of explicitly declared sized reference to an array) gets passed as a pointer, so you can't know the size of the array once passed as an argument. So this:
void printa(long array[])
{
for (int i = 0 ; i < sizeof(array); i++) {}
// At this point of the code the sizeof(array) will return the size of
// a pointer, usually 4 or 8 bytes.
// It's a quirk that this happens, and is a holdover from C.
}
By taking an argument of std::vector you can know the size of the array. You can take the argument by value or by reference or pointer.
void printa(const std::vector<long>& array)
{
for (int i = 0 ; i < array.size(); i++)
{
cout << array[i] << ", ";
cout << "\n";
}
}
This is the better way to do it. If you want to use a C array or raw array the way you did, you will have to pass both the array and the size of the array as separate arguments.
Also, about the variable length array extension feature, I'm not sure whether it is reliable or not because I've never used the extension. Again, standard C++ requires that size of arrays are constant values, (known at compile time). Edit: actually (known at compile-time) is a bad description because:
int main()
{
int num = 6;
int myarray[num]; // In standard C++ this won't compile
//but
const int num = 6;
int myarray[num]; // Will
}
And one last thing, as SolutionMill pointed out, even if the sizeof(array) does give the right size and not the size of a pointer, it is the size given in bytes, not the number of elements, which was not you were wanting in:
for (int i = 0 ; i < sizeof(array); i++)
If the array is of 2 elements of 32 bit int, then the sizeof() operator will return size 8. A common but by no means pretty way to get the number of elements in an array is something like sizeof(array) / sizeof(array[0])
In my main() function I have declared an array of type int with the numbers 1 to 10. I then have two other functions of type int* that take this array and its size as parameters, perform some operations, and each returns a pointer to the new array. Where I'm having issues is with a third function that prints the contents of the array.
#include <iostream>
using namespace std;
const int SIZE_OF_ARRAY = 10;
int main() {
int array[SIZE_OF_ARRAY] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int *ptr1 = 0;
ptr1 = function1(array, SIZE_OF_ARRAY);
print(array, SIZE_OF_ARRAY);
cout << endl;
int *ptr2 = 0;
ptr2 = function2(array, SIZE_OF_ARRAY);
print(array, SIZE_OF_ARRAY);
return 0;
}
void print(int array[], const int SIZE_OF_ARRAY)
{
for (int i = 0; i < (SIZE_OF_ARRAY * 2); i++)
{
cout << array[i] << " ";
}
}
int* function1(int array[], const int SIZE_OF_ARRAY)
{
int *ptr = new int[SIZE_OF_ARRAY];
// Do stuff.
return ptr;
}
int* function2(int array[], const int SIZE_OF_ARRAY)
{
int *ptr2 = new int[SIZE_OF_ARRAY * 2];
// Create new array double in size, and set contents of ptr2
// to the contents of array. Then initialize the rest to 0.
return ptr2;
}
As expected here, the result of calling the print() function twice is something like:
1 2 3 4 5 6 7 8 9 10 465738691 -989855001 1483324368 32767 -1944382035 32767 0 0 1 0
1 2 3 4 5 6 7 8 9 10 465738691 -989855001 1483324368 32767 -1944382035 32767 0 0 1 0
But I want the result to be like this instead:
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10 0 0 0 0 0 0 0 0 0 0
How can I accomplish this? (Note that for this assignment I'm using C++98). Thanks in advance.
new int[SIZE_OF_ARRAY] allocates memory, but doesn't assign values to the array elements. What you are seeing is what was in that memory when it got allocated for the array. You can change your function2 to assign zeroes to array elements, if that's what you want.
First of all, you want to print different number of elements on the two calls to print, so you should not delegate deciding whether to multiply the size by two to the print, but rather do it on the calling side. Change the print function to only iterate up to SIZE_OF_ARRAY, and change the two places where you call it to:
print(ptr1, SIZE_OF_ARRAY);
and
print(ptr2, SIZE_OF_ARRAY * 2);
correspondingly.
Now, I assume that your second function does assign values to all 20 elements, but if it does not, the ones to which it did not assign values would continue containing garbage. To get around it, just initialize them at the beginning of the second function:
int *ptr2 = new int[SIZE_OF_ARRAY * 2];
for (size_t i = 0; i < SIZE_OF_ARRAY * 2; ++ i) ptr2[i] = 0;
With these two changes you should get the desired behavior.
Also, if you allocate something with new[], you need to delete it with delete[], otherwise you get a memory leak. Add these two lines at the end of main:
delete[] ptr1;
delete[] ptr2;
Note, that using delete instead of delete[] would be wrong in this case. If something is allocated as an array, it must be deleted as an array.
I need to add either +0.25 or -0.25 to all elements within an array. Here is what I have so far. Any help would be appreciated.
int main() {
double i;
// Arrays
double x[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
double x2[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
for(i=1; i<=10; i++) {
const double pM[2] = {-1, 1};
int randoid = rand() % 2;
for(i=1; i<=10; i++){
x2[i] = x[i] + pM[randoid]*0.25; //Error Line
}
}
cout << x;
cout << x2;
}
I get this error at the marked line: "invalid types 'double[10][double] for array subscript"
The problem is that i is a double. Then you write x2[i].
It's not a very good error message; however with the [] operator, one of the operands must be a pointer and the other must be an integer. There is no implicit conversion of floating-point to integer when using this operator.
To fix this change double i; to int i;
Another issue is that your code accesses out of bounds of the arrays. double x2[10] means that there are 10 elements whose indices are 0 through 9. But your loop tries to write to x2[10]. This causes undefined behaviour, which could explain your strange output.
There is also a potential logic error. Maybe you meant to use a different variable for the inner loop than the outer loop. As it stands, the inner loop will take i to 11 (or 10 if you fix the code) and then the outer loop will be complete and not execute any more iterations.
Based on your description though, perhaps you only meant to have one loop in the first place. If so, remove the outer loop and just leave the contents there.
Also you do not need two separate arrays, you could just perform the addition in-place.
Regarding the output, cout << x and cout << x2 will output the number of the memory address at which the array is located. To output the contents of the array instead you will need to write another loop, or use a standard library algorithm that iterates over containers.
I see 3 issues -
Change the type of i to int.
x and x2 are arrays of size 10. You need to loop from i =
0 to i = 9. But you are looping from i = 1 to i = 10. x[10]
is out of bounds since arrays are 0 indexed.
cout << x - This is a wrong way to print an array. You need
to loop through the array and print - e.g. -
for(i = 0; i < 10; i++)
cout << x[i] << " ";
Try this, it works, I converted to C
int main( )
{
int i = 0;
// Arrays
double x[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
double x2[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
for ( i = 1; i < 10; i++ )
{
const double pM[2] = { -1, 1 };
int randoid = rand( ) % 2;
for ( i = 1; i <= 10; i++ )
{
x2[i] = x[i] + pM[randoid] * 0.25; //Error Line
printf( "\nx[%d]==%2.2f", i, x[i] );
printf( "\nx2[%d]==%2.2f", i, x2[i] );
}
}
}
I am trying to get all combinations of an array with C++ such that
double* list1 = new double[size];
Items in that array is {1,2,3,4,5}
I need to add all possible combinations into a stack, such as:
1+2, 1+2+3, 1+2+3+4,1+2+3+4+5, 1+3, 1+3+4, 1+3+4+5, 1+4, 1+4+5, 1+5...
the problem I am running into is I am doing this through 2 for loops and a while loop
for(int i = 0; i < size - 1; i++)
{
for(int j = i; j < size - 1; j++)
{
double temp = list1[i] + list1[j + 1];
list1combos.push(temp);
int k = j + 2;
while (k <= size - 1)
{
temp = temp + list1[k];
list1combos.push(temp);
k++;
}
}
}
I can get the ones I listed above but I have no clue how to code in combinations such as 1+3+5, or 1+2+5
Please advise on how to get those combinations, thanks stackoverflow!
Since the order does not matter, I would suggest having an array of the same size as your x and perform a binary increment on it, i.e. you start with the array inited to only 0s and count until you have only 1s. For every addition of a 1 you would pick a permutation from your x array.
First iteration:
0 0 0 0 0 -> empty
Second iteration:
0 0 0 0 1 -> you pick 5
3rd iteration:
0 0 0 1 0 -> you pick 4
4th iteration:
0 0 0 1 1 -> you pick 4 and 5
And so on until you reach:
1 1 1 1 1 -> you pick 1, 2, 3, 4 and 5
You can approach this problem by printing all subsets of a set {1,2,3,4,5}. There are 2^5 of them - or 2^5-1 since set {0) is meaningless for you.
This code can help you.
#include<iostream>
#include<list>
#include <iterator>
void print( std::list<int> l){
std::copy( l.begin(), l.end(), std::ostream_iterator<int>( std::cout, " "));
std::cout << std::endl;
}
void subset( int arr[], int size, int left, int index, std::list<int> &l){
if( left == 0){
print(l);
return;
}
for( int i = index; i < size; i++){
l.push_back( arr[i]);
subset( arr, size, left - 1, i + 1, l);
l.pop_back();
}
}
int main() {
int array[5] = { 1, 2, 3, 4, 5} ;
std::list<int> lt;
subset( array, 5, 1, 0, lt);
subset( array, 5, 2, 0, lt);
subset( array, 5, 3, 0, lt);
subset( array, 5, 4, 0, lt);
subset( array, 5, 5, 0, lt);
return 0;
}
http://ideone.com/J78J7q
more algorithms for subsets: generate all subsets of size k from a set
Others have already answered your question. I'll point out one important thing:
double* list1=new double(size);
This does not allocate an array of double with size elements.
Instead it allocates a single double and sets the value of it to size. Attempting to access it as an array results in undefined behavior and could lead to a crash.
You want to do this instead:
double* list1=new double[size];
Notice the use of square brackets. Also remember that you must call delete[] list1; instead of simply delete list1; when you want to release the allocated memory.
Following may help: http://ideone.com/SpCejs
template <std::size_t N>
bool increase(std::bitset<N>& bs)
{
for (std::size_t i = 0; i != bs.size(); ++i) {
if (bs.flip(i).test(i) == true) {
return true;
}
}
return false;
}
template <typename T, std::size_t N>
void print_combinaison(const std::array<T, N>& a)
{
std::bitset<N> bs;
do {
for (std::size_t i = 0; i != N; ++i) {
if (bs.test(i)) {
std::cout << a[i] << " ";
}
}
std::cout << std::endl;
} while (increase(bs));
}